From ddb327ab19b29c64c1752cef26c460ca0b7064ec Mon Sep 17 00:00:00 2001 From: Ken Zalewski Date: Tue, 16 Jun 2026 01:33:01 -0400 Subject: [PATCH] Patch to openssl-1.1.1zh. This version addresses five vulnerabilities: CVE-2026-34180, CVE-2026-42766, CVE-2026-45447, CVE-2026-7383, and CVE-2026-9076 --- CHANGES | 86 ++++++++++++++++++++++++++++++++++++++ NEWS | 11 +++++ README | 2 +- crypto/asn1/a_mbstr.c | 39 +++++++++++++++-- crypto/asn1/tasn_dec.c | 25 +++++++---- crypto/cms/cms_pwri.c | 15 +++++-- crypto/pkcs7/pk7_smime.c | 9 ++-- include/openssl/opensslv.h | 4 +- 8 files changed, 171 insertions(+), 20 deletions(-) diff --git a/CHANGES b/CHANGES index f7e81b3..e2da990 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,92 @@ https://github.com/openssl/openssl/commits/ and pick the appropriate release branch. + Changes between 1.1.1zg and 1.1.1zh [9 Jun 2026] + + *) Fixed heap use-after-free in `PKCS7_verify()`. + Severity: High + + Issue summary: A specially crafted PKCS#7 or S/MIME signed message could + trigger a use-after-free during PKCS#7 signature verification. + + Impact summary: A use-after-free may result in process crashes, heap + corruption, or, potentially, remote code execution. + + Reported by: Thai Duong (Calif.io in collaboration with Claude + and Anthropic Research). + + (CVE-2026-45447) + [Igor Ustinov] + + *) Fixed possible heap buffer overflow in ASN.1 multibyte string conversion. + + Severity: Low + + Issue summary: A signed integer overflow when sizing the destination + buffer for Unicode output in `ASN1_mbstring_ncopy()` can lead to a heap + buffer overflow. + + Impact summary: A heap buffer overflow may lead to a crash or possibly + attacker controlled code execution or other undefined behaviour. + + Reported by: Zehua Qiao and Jinwen He. + + (CVE-2026-7383) + [Viktor Dukhovni] + + *) Fixed out-of-bounds read in CMS password-based decryption. + + Severity: Low + + Issue summary: When CMS password-based decryption ([RFC 3211]/PWRI key + unwrap) processes attacker-supplied CMS data, an attacker-chosen stream-mode + KEK cipher can trigger a heap out-of-bounds read in `kek_unwrap_key()`. + + Impact summary: A heap buffer over-read may trigger a crash, which leads + to Denial of Service for an application if the input buffer ends at a memory + page boundary and the following page is unmapped. There is no information + disclosure, as the over-read bytes are not revealed to the attacker. + + Reported by: Bhabani Sankar Das and Haruki Oyama (Waseda University). + + (CVE-2026-9076) + [Nikola Pajkovsky] + + *) Fixed heap buffer over-read in ASN.1 content parsing. + + Severity: Low + + Issue summary: Parsing a crafted DER-encoded ASN.1 structure with a + primitive element whose content exceeds 2 gigabytes in length may cause a + heap buffer over-read on 64-bit Unix and Unix-like platforms. + + Impact summary: The heap buffer over-read may crash the application (Denial + of Service) or to load into the decoded ASN.1 object contents of memory + beyond the end of the input buffer. More typically, such ASN.1 elements + would instead be truncated. + + Reported by: Frank Buss. + + (CVE-2026-34180) + [Viktor Dukhovni] + + *) Fixed possible NULL dereference in password-dased CMS decryption. + + Severity: Low + + Issue summary: A specially crafted password-encrypted CMS message + could trigger a NULL pointer dereference during CMS decryption. + + Impact summary: This NULL pointer dereference could lead to an application + crash and a Denial of Service. + + Reported by: Mayank Jangid, Kushal Khemka, Hari Priandana, + Bhabani Sankar Das, and Qifan Zhang (Palo Alto Networks). + + (CVE-2026-42766) + [Igor Ustinov] + + Changes between 1.1.1ze and 1.1.1zg [7 Apr 2026] *) Fixed potential use-after-free in DANE client code. diff --git a/NEWS b/NEWS index d01ce10..dd08b3f 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,17 @@ This file gives a brief overview of the major changes between each OpenSSL release. For more details please read the CHANGES file. + Major changes between 1.1.1zg and 1.1.1zh [9 Jun 2026] + + o Fixed heap use-after-free in `PKCS7_verify()`. (CVE-2026-45447) + o Fixed possible heap buffer overflow in ASN.1 multibyte string + conversion. (CVE-2026-7383) + o Fixed out-of-bounds read in CMS password-based decryption. + (CVE-2026-9076) + o Fixed heap buffer over-read in ASN.1 content parsing. (CVE-2026-34180) + o Fixed possible NULL dereference in password-dased CMS decryption. + (CVE-2026-42766) + Major changes between 1.1.1ze and 1.1.1zg [7 Apr 2026] o Fixed potential use-after-free in DANE client code. (CVE-2026-28387) diff --git a/README b/README index 2bd7fdf..61509fa 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ - OpenSSL 1.1.1zg 7 Apr 2026 + OpenSSL 1.1.1zh 9 Jun 2026 Copyright (c) 1998-2026 The OpenSSL Project Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index bdb697a..3a1a1bf 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -171,18 +171,41 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, break; case MBSTRING_BMP: + if (nchar > INT_MAX / 2) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG); + if (free_out) { + ASN1_STRING_free(dest); + *out = NULL; + } + return -1; + } outlen = nchar << 1; cpyfunc = cpy_bmp; break; case MBSTRING_UNIV: + if (nchar > INT_MAX / 4) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG); + if (free_out) { + ASN1_STRING_free(dest); + *out = NULL; + } + return -1; + } outlen = nchar << 2; cpyfunc = cpy_univ; break; case MBSTRING_UTF8: outlen = 0; - traverse_string(in, len, inform, out_utf8, &outlen); + ret = traverse_string(in, len, inform, out_utf8, &outlen); + if (ret < 0) { + if (free_out) { + ASN1_STRING_free(dest); + *out = NULL; + } + return -1; + } cpyfunc = cpy_utf8; break; } @@ -256,9 +279,19 @@ static int in_utf8(unsigned long value, void *arg) static int out_utf8(unsigned long value, void *arg) { - int *outlen; + int *outlen, len; + + len = UTF8_putc(NULL, -1, value); + if (len <= 0) { + /* ASN1err(ASN1_F_OUT_UTF8, ASN1_R_INVALID_UTF8STRING); */ + return len; + } outlen = arg; - *outlen += UTF8_putc(NULL, -1, value); + if (*outlen > INT_MAX - len) { + /* ASN1err(ASN1_F_OUT_UTF8, ASN1_R_STRING_TOO_LONG); */ + return -1; + } + *outlen += len; return 1; } diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 82577b1..764de38 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -57,7 +57,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx); -static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, int utype, char *free_cont, const ASN1_ITEM *it); /* Table to convert tags to bit values, used for MSTRING type */ @@ -790,19 +790,25 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, /* Translate ASN1 content octets into a structure */ -static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, int utype, char *free_cont, const ASN1_ITEM *it) { ASN1_VALUE **opval = NULL; ASN1_STRING *stmp; ASN1_TYPE *typ = NULL; int ret = 0; + int ilen = (int)len; const ASN1_PRIMITIVE_FUNCS *pf; ASN1_INTEGER **tint; pf = it->funcs; - if (pf && pf->prim_c2i) - return pf->prim_c2i(pval, cont, len, utype, free_cont, it); + if (pf && pf->prim_c2i) { + if (len == (long)ilen) + return pf->prim_c2i(pval, cont, ilen, utype, free_cont, it); + ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_TOO_LONG); + return 0; + } + /* If ANY type clear type and set pointer to internal value */ if (it->utype == V_ASN1_ANY) { if (!*pval) { @@ -820,7 +826,8 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, } switch (utype) { case V_ASN1_OBJECT: - if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) + if (len != (long)ilen + || !c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) goto err; break; @@ -875,6 +882,10 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, case V_ASN1_SET: case V_ASN1_SEQUENCE: default: + if (len != (long)ilen) { + ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_TOO_LONG); + goto err; + } if (utype == V_ASN1_BMPSTRING && (len & 1)) { ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); goto err; @@ -900,10 +911,10 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, if (*free_cont) { OPENSSL_free(stmp->data); stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ - stmp->length = len; + stmp->length = ilen; *free_cont = 0; } else { - if (!ASN1_STRING_set(stmp, cont, len)) { + if (!ASN1_STRING_set(stmp, cont, ilen)) { ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); ASN1_STRING_free(stmp); *pval = NULL; diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c index 9f98840..0275117 100644 --- a/crypto/cms/cms_pwri.c +++ b/crypto/cms/cms_pwri.c @@ -177,14 +177,18 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx) { - size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); + int blocklen = EVP_CIPHER_CTX_block_size(ctx); unsigned char *tmp; int outl, rv = 0; - if (inlen < 2 * blocklen) { + + if (blocklen < 4) + return 0; + + if (inlen < 2 * (size_t)blocklen) { /* too small */ return 0; } - if (inlen % blocklen) { + if (inlen > INT_MAX || inlen % blocklen) { /* Invalid size */ return 0; } @@ -336,6 +340,11 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, /* Finish password based key derivation to setup key in "ctx" */ + if (algtmp == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, + CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); + goto err; + } if (EVP_PBE_CipherInit(algtmp->algorithm, (char *)pwri->pass, pwri->passlen, algtmp->parameter, kekctx, en_de) < 0) { diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index a95db62..8a8449a 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -213,6 +213,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, int i, j = 0, k, ret = 0; BIO *p7bio = NULL; BIO *tmpin = NULL, *tmpout = NULL; + BIO *next = NULL; if (!p7) { PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_INVALID_NULL_POINTER); @@ -360,11 +361,11 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, err: X509_STORE_CTX_free(cert_ctx); OPENSSL_free(buf); - if (tmpin == indata) { - if (indata) - BIO_pop(p7bio); + while (p7bio != NULL && p7bio != indata) { + next = BIO_pop(p7bio); + BIO_free(p7bio); + p7bio = next; } - BIO_free_all(p7bio); sk_X509_free(signers); return ret; } diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h index 0dcdd92..0759061 100644 --- a/include/openssl/opensslv.h +++ b/include/openssl/opensslv.h @@ -39,8 +39,8 @@ extern "C" { * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -# define OPENSSL_VERSION_NUMBER 0x1010120fL -# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1zg 7 Apr 2026" +# define OPENSSL_VERSION_NUMBER 0x1010121fL +# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1zh 9 Jun 2026" /*- * The macros below are to be used for shared library (.so, .dll, ...)