3 Commits

Author SHA1 Message Date
Michał Trojnara fac8164622 Release 2.12
Signed-off-by: Michał Trojnara <Michal.Trojnara@stunnel.org>
2026-02-02 17:53:25 +01:00
Michał Trojnara cbee1e723c Fixed buffer overflow while extracting msg digest
Reported and fixed by Antoni Klajn, Opera
2026-02-02 17:37:45 +01:00
Michał Trojnara f90327df09 Initial 2.12-dev commit 2026-01-21 00:08:58 +01:00
11 changed files with 62 additions and 22 deletions
+1 -1
View File
@@ -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
View File
@@ -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)
+13
View File
@@ -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)
+3 -3
View File
@@ -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);
} }
+3 -4
View File
@@ -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) {
+27
View File
@@ -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
+2
View File
@@ -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);
/* /*
+3 -3
View File
@@ -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
View File
@@ -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");
+3 -3
View File
@@ -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);
} }
+3 -3
View File
@@ -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);
} }