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:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
version: osslsigncode-2.11
version: osslsigncode-2.12
jobs:
build:
+1 -1
View File
@@ -10,7 +10,7 @@ set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
# configure basic project information
project(osslsigncode
VERSION 2.11
VERSION 2.12
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files"
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
LANGUAGES C)
+13
View File
@@ -1,5 +1,18 @@
# 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)
- added keyUsage validation for signer certificate
(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;
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
if (idc) {
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
SpcIndirectDataContent_free(idc);
return 0; /* FAILED */
}
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));
if (!idc)
return 0; /* FAILED */
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
/* get a digest algorithm a message digest of the file from the content */
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
SpcIndirectDataContent_free(idc);
return 0; /* FAILED */
}
SpcIndirectDataContent_free(idc);
if (mdtype == -1) {
+27
View File
@@ -548,6 +548,33 @@ SpcLink *spc_link_obsolete_get(void)
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] 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);
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
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);
/*
+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;
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
if (idc) {
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
SpcIndirectDataContent_free(idc);
return 0; /* FAILED */
}
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");
return 1; /* FAILED */
}
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
/* get a digest algorithm a message digest of the file from the content */
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
SpcIndirectDataContent_free(idc);
return 1; /* FAILED */
}
if (mdtype == -1) {
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);
return 0; /* FAILED */
}
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
SpcIndirectDataContent_free(idc);
return 0; /* FAILED */
}
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;
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
if (idc) {
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
if (spc_extract_digest_safe(idc, mdbuf, &mdtype) < 0) {
SpcIndirectDataContent_free(idc);
return 0; /* FAILED */
}
SpcIndirectDataContent_free(idc);
}