mirror of
https://github.com/mtrojnar/osslsigncode
synced 2026-06-08 16:13:39 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fac8164622 | |||
| cbee1e723c | |||
| f90327df09 |
@@ -7,7 +7,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
version: osslsigncode-2.11
|
version: osslsigncode-2.12
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
|||||||
|
|
||||||
# configure basic project information
|
# configure basic project information
|
||||||
project(osslsigncode
|
project(osslsigncode
|
||||||
VERSION 2.11
|
VERSION 2.12
|
||||||
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files"
|
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files"
|
||||||
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
||||||
LANGUAGES C)
|
LANGUAGES C)
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# osslsigncode change log
|
# osslsigncode change log
|
||||||
|
|
||||||
|
### 2.12 (2026.02.02)
|
||||||
|
|
||||||
|
**CRITICAL SECURITY VULNERABILITY**
|
||||||
|
|
||||||
|
This release fixes a critical memory corruption vulnerability. A malicious
|
||||||
|
attacker could create a signed file, which, when verified with osslsigncode,
|
||||||
|
triggers arbitrary code execution. Any previous version of osslsigncode should
|
||||||
|
be immediately upgraded if the tool is used for verification of untrusted
|
||||||
|
files.
|
||||||
|
|
||||||
|
- fixed a buffer overflow while extracting message digests
|
||||||
|
(reported and fixed by Antoni Klajn, Opera)
|
||||||
|
|
||||||
### 2.11 (2026.01.20)
|
### 2.11 (2026.01.20)
|
||||||
- added keyUsage validation for signer certificate
|
- added keyUsage validation for signer certificate
|
||||||
(thanks to Hanqing Zhao and Zi-Quan You for reporting the issue)
|
(thanks to Hanqing Zhao and Zi-Quan You for reporting the issue)
|
||||||
|
|||||||
@@ -342,9 +342,9 @@ static int cab_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|||||||
const u_char *p = content_val->data;
|
const u_char *p = content_val->data;
|
||||||
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||||
if (idc) {
|
if (idc) {
|
||||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
|
||||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
SpcIndirectDataContent_free(idc);
|
||||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
SpcIndirectDataContent_free(idc);
|
SpcIndirectDataContent_free(idc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,10 +390,9 @@ static int cat_print_content_member_digest(ASN1_TYPE *content)
|
|||||||
idc = d2i_SpcIndirectDataContent(NULL, &data, ASN1_STRING_length(value));
|
idc = d2i_SpcIndirectDataContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
if (!idc)
|
if (!idc)
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
|
||||||
/* get a digest algorithm a message digest of the file from the content */
|
SpcIndirectDataContent_free(idc);
|
||||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
return 0; /* FAILED */
|
||||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
|
||||||
}
|
}
|
||||||
SpcIndirectDataContent_free(idc);
|
SpcIndirectDataContent_free(idc);
|
||||||
if (mdtype == -1) {
|
if (mdtype == -1) {
|
||||||
|
|||||||
@@ -548,6 +548,33 @@ SpcLink *spc_link_obsolete_get(void)
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Safely extract digest from SpcIndirectDataContent
|
||||||
|
* [in] idc: parsed SpcIndirectDataContent
|
||||||
|
* [out] mdbuf: output buffer (must be EVP_MAX_MD_SIZE bytes)
|
||||||
|
* [out] mdtype: digest algorithm's NID
|
||||||
|
* [returns] -1 on error or digest length on success
|
||||||
|
*/
|
||||||
|
int spc_extract_digest_safe(SpcIndirectDataContent *idc,
|
||||||
|
u_char *mdbuf, int *mdtype)
|
||||||
|
{
|
||||||
|
int digest_len;
|
||||||
|
|
||||||
|
if (!idc || !idc->messageDigest || !idc->messageDigest->digest ||
|
||||||
|
!idc->messageDigest->digestAlgorithm) {
|
||||||
|
fprintf(stderr, "Missing digest data\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
digest_len = idc->messageDigest->digest->length;
|
||||||
|
if (digest_len <= 0 || digest_len > EVP_MAX_MD_SIZE) {
|
||||||
|
fprintf(stderr, "Invalid digest length: %d\n", digest_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)digest_len);
|
||||||
|
*mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||||
|
return digest_len;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in] mdbuf, cmdbuf: message digests
|
* [in] mdbuf, cmdbuf: message digests
|
||||||
* [in] mdtype: message digest algorithm type
|
* [in] mdtype: message digest algorithm type
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ int is_content_type(PKCS7 *p7, const char *objid);
|
|||||||
MsCtlContent *ms_ctl_content_get(PKCS7 *p7);
|
MsCtlContent *ms_ctl_content_get(PKCS7 *p7);
|
||||||
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
|
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
|
||||||
SpcLink *spc_link_obsolete_get(void);
|
SpcLink *spc_link_obsolete_get(void);
|
||||||
|
int spc_extract_digest_safe(SpcIndirectDataContent *idc,
|
||||||
|
u_char *mdbuf, int *mdtype);
|
||||||
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
|
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -419,9 +419,9 @@ static int msi_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|||||||
const u_char *p = content_val->data;
|
const u_char *p = content_val->data;
|
||||||
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||||
if (idc) {
|
if (idc) {
|
||||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
|
||||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
SpcIndirectDataContent_free(idc);
|
||||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
SpcIndirectDataContent_free(idc);
|
SpcIndirectDataContent_free(idc);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-4
@@ -3082,10 +3082,9 @@ static int verify_content_member_digest(FILE_FORMAT_CTX *ctx, ASN1_TYPE *content
|
|||||||
fprintf(stderr, "Failed to extract SpcIndirectDataContent data\n");
|
fprintf(stderr, "Failed to extract SpcIndirectDataContent data\n");
|
||||||
return 1; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
|
||||||
/* get a digest algorithm a message digest of the file from the content */
|
SpcIndirectDataContent_free(idc);
|
||||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
return 1; /* FAILED */
|
||||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
|
||||||
}
|
}
|
||||||
if (mdtype == -1) {
|
if (mdtype == -1) {
|
||||||
fprintf(stderr, "Failed to extract current message digest\n\n");
|
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||||
|
|||||||
@@ -255,9 +255,9 @@ static int pe_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|||||||
SpcIndirectDataContent_free(idc);
|
SpcIndirectDataContent_free(idc);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
|
||||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
SpcIndirectDataContent_free(idc);
|
||||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
SpcIndirectDataContent_free(idc);
|
SpcIndirectDataContent_free(idc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,9 +294,9 @@ static int script_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|||||||
const u_char *p = content_val->data;
|
const u_char *p = content_val->data;
|
||||||
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||||
if (idc) {
|
if (idc) {
|
||||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
|
||||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
SpcIndirectDataContent_free(idc);
|
||||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
SpcIndirectDataContent_free(idc);
|
SpcIndirectDataContent_free(idc);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user