mirror of
https://github.com/opnsense/src.git
synced 2026-02-03 20:49:35 -05:00
openssl: Fix multiple vulnerabilities
This is a rollup commit from upstream to fix: Stack buffer overflow in CMS AuthEnvelopedData parsing (CVE-2025-15467) Heap out-of-bounds write in BIO_f_linebuffer on short writes (CVE-2025-68160) Unauthenticated/unencrypted trailing bytes with low-level OCB function calls (CVE-2025-69418) Out of bounds write in PKCS12_get_friendlyname() UTF-8 conversion (CVE-2025-69419) Missing ASN1_TYPE validation in TS_RESP_verify_response() function (CVE-2025-69420) NULL Pointer Dereference in PKCS12_item_decrypt_d2i_ex function (CVE-2025-69421) Missing ASN1_TYPE validation in PKCS#12 parsing (CVE-2026-22795) ASN1_TYPE Type Confusion in the PKCS7_digest_from_attributes() function (CVE-2026-22796) See https://openssl-library.org/news/secadv/ for additional details. Approved by: so Obtained from: OpenSSL Security: FreeBSD-SA-26:01.openssl Security: CVE-2025-15467 Security: CVE-2025-68160 Security: CVE-2025-69418 Security: CVE-2025-69419 Security: CVE-2025-69420 Security: CVE-2025-69421 Security: CVE-2026-22795 Security: CVE-2026-22796
This commit is contained in:
parent
9f93a51870
commit
7ca64ab386
11 changed files with 84 additions and 18 deletions
|
|
@ -2650,8 +2650,9 @@ int s_client_main(int argc, char **argv)
|
|||
goto end;
|
||||
}
|
||||
atyp = ASN1_generate_nconf(genstr, cnf);
|
||||
if (atyp == NULL) {
|
||||
if (atyp == NULL || atyp->type != V_ASN1_SEQUENCE) {
|
||||
NCONF_free(cnf);
|
||||
ASN1_TYPE_free(atyp);
|
||||
BIO_printf(bio_err, "ASN1_generate_nconf failed\n");
|
||||
goto end;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,8 +204,10 @@ static int do_buf(unsigned char *buf, int buflen,
|
|||
orflags = CHARTYPE_LAST_ESC_2253;
|
||||
if (type & BUF_TYPE_CONVUTF8) {
|
||||
unsigned char utfbuf[6];
|
||||
int utflen;
|
||||
utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
||||
int utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
||||
|
||||
if (utflen < 0)
|
||||
return -1; /* error happened with UTF8 */
|
||||
for (i = 0; i < utflen; i++) {
|
||||
/*
|
||||
* We don't need to worry about setting orflags correctly
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ static ossl_inline void asn1_type_init_oct(ASN1_OCTET_STRING *oct,
|
|||
oct->flags = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function copies 'anum' to 'num' and the data of 'oct' to 'data'.
|
||||
* If the length of 'data' > 'max_len', copies only the first 'max_len'
|
||||
* bytes, but returns the full length of 'oct'; this allows distinguishing
|
||||
* whether all the data was copied.
|
||||
*/
|
||||
static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum,
|
||||
long *num, unsigned char *data, int max_len)
|
||||
{
|
||||
|
|
@ -106,6 +112,13 @@ int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function decodes an int-octet sequence and copies the integer to 'num'
|
||||
* and the data of octet to 'data'.
|
||||
* If the length of 'data' > 'max_len', copies only the first 'max_len'
|
||||
* bytes, but returns the full length of 'oct'; this allows distinguishing
|
||||
* whether all the data was copied.
|
||||
*/
|
||||
int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
|
||||
unsigned char *data, int max_len)
|
||||
{
|
||||
|
|
@ -162,6 +175,13 @@ int ossl_asn1_type_set_octetstring_int(ASN1_TYPE *a, long num,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function decodes an octet-int sequence and copies the data of octet
|
||||
* to 'data' and the integer to 'num'.
|
||||
* If the length of 'data' > 'max_len', copies only the first 'max_len'
|
||||
* bytes, but returns the full length of 'oct'; this allows distinguishing
|
||||
* whether all the data was copied.
|
||||
*/
|
||||
int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num,
|
||||
unsigned char *data, int max_len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -189,14 +189,34 @@ static int linebuffer_write(BIO *b, const char *in, int inl)
|
|||
while (foundnl && inl > 0);
|
||||
/*
|
||||
* We've written as much as we can. The rest of the input buffer, if
|
||||
* any, is text that doesn't and with a NL and therefore needs to be
|
||||
* saved for the next trip.
|
||||
* any, is text that doesn't end with a NL and therefore we need to try
|
||||
* free up some space in our obuf so we can make forward progress.
|
||||
*/
|
||||
if (inl > 0) {
|
||||
memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl);
|
||||
ctx->obuf_len += inl;
|
||||
num += inl;
|
||||
while (inl > 0) {
|
||||
size_t avail = (size_t)ctx->obuf_size - (size_t)ctx->obuf_len;
|
||||
size_t to_copy;
|
||||
|
||||
if (avail == 0) {
|
||||
/* Flush buffered data to make room */
|
||||
i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
return num > 0 ? num : i;
|
||||
}
|
||||
if (i < ctx->obuf_len)
|
||||
memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i);
|
||||
ctx->obuf_len -= i;
|
||||
continue;
|
||||
}
|
||||
|
||||
to_copy = inl > (int)avail ? avail : (size_t)inl;
|
||||
memcpy(&(ctx->obuf[ctx->obuf_len]), in, to_copy);
|
||||
ctx->obuf_len += (int)to_copy;
|
||||
in += to_copy;
|
||||
inl -= (int)to_copy;
|
||||
num += (int)to_copy;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,10 +249,9 @@ int evp_cipher_get_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
|
|||
if (type == NULL || asn1_params == NULL)
|
||||
return 0;
|
||||
|
||||
i = ossl_asn1_type_get_octetstring_int(type, &tl, NULL, EVP_MAX_IV_LENGTH);
|
||||
if (i <= 0)
|
||||
i = ossl_asn1_type_get_octetstring_int(type, &tl, iv, EVP_MAX_IV_LENGTH);
|
||||
if (i <= 0 || i > EVP_MAX_IV_LENGTH)
|
||||
return -1;
|
||||
ossl_asn1_type_get_octetstring_int(type, &tl, iv, i);
|
||||
|
||||
memcpy(asn1_params->iv, iv, i);
|
||||
asn1_params->iv_len = i;
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx,
|
|||
|
||||
if (num_blocks && all_num_blocks == (size_t)all_num_blocks
|
||||
&& ctx->stream != NULL) {
|
||||
size_t max_idx = 0, top = (size_t)all_num_blocks;
|
||||
size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0;
|
||||
|
||||
/*
|
||||
* See how many L_{i} entries we need to process data at hand
|
||||
|
|
@ -356,6 +356,9 @@ int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx,
|
|||
ctx->stream(in, out, num_blocks, ctx->keyenc,
|
||||
(size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c,
|
||||
(const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c);
|
||||
processed_bytes = num_blocks * 16;
|
||||
in += processed_bytes;
|
||||
out += processed_bytes;
|
||||
} else {
|
||||
/* Loop through all full blocks to be encrypted */
|
||||
for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) {
|
||||
|
|
@ -434,7 +437,7 @@ int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx,
|
|||
|
||||
if (num_blocks && all_num_blocks == (size_t)all_num_blocks
|
||||
&& ctx->stream != NULL) {
|
||||
size_t max_idx = 0, top = (size_t)all_num_blocks;
|
||||
size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0;
|
||||
|
||||
/*
|
||||
* See how many L_{i} entries we need to process data at hand
|
||||
|
|
@ -448,6 +451,9 @@ int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx,
|
|||
ctx->stream(in, out, num_blocks, ctx->keydec,
|
||||
(size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c,
|
||||
(const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c);
|
||||
processed_bytes = num_blocks * 16;
|
||||
in += processed_bytes;
|
||||
out += processed_bytes;
|
||||
} else {
|
||||
OCB_BLOCK tmp;
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,11 @@ void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
|
|||
void *ret;
|
||||
int outlen = 0;
|
||||
|
||||
if (oct == NULL) {
|
||||
ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, oct->data, oct->length,
|
||||
&out, &outlen, 0, libctx, propq))
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -190,11 +190,17 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
|
|||
ASN1_BMPSTRING *fname = NULL;
|
||||
ASN1_OCTET_STRING *lkid = NULL;
|
||||
|
||||
if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName)))
|
||||
if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) {
|
||||
if (attrib->type != V_ASN1_BMPSTRING)
|
||||
return 0;
|
||||
fname = attrib->value.bmpstring;
|
||||
}
|
||||
|
||||
if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)))
|
||||
if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) {
|
||||
if (attrib->type != V_ASN1_OCTET_STRING)
|
||||
return 0;
|
||||
lkid = attrib->value.octet_string;
|
||||
}
|
||||
|
||||
switch (PKCS12_SAFEBAG_get_nid(bag)) {
|
||||
case NID_keyBag:
|
||||
|
|
|
|||
|
|
@ -212,6 +212,11 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen)
|
|||
/* re-run the loop emitting UTF-8 string */
|
||||
for (asclen = 0, i = 0; i < unilen; ) {
|
||||
j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i);
|
||||
/* when UTF8_putc fails */
|
||||
if (j < 0) {
|
||||
OPENSSL_free(asctmp);
|
||||
return NULL;
|
||||
}
|
||||
if (j == 4) i += 4;
|
||||
else i += 2;
|
||||
asclen += j;
|
||||
|
|
|
|||
|
|
@ -1182,6 +1182,8 @@ ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
|
|||
ASN1_TYPE *astype;
|
||||
if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL)
|
||||
return NULL;
|
||||
if (astype->type != V_ASN1_OCTET_STRING)
|
||||
return NULL;
|
||||
return astype->value.octet_string;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ static ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const PKCS7_SIGNER_INFO *si)
|
|||
const unsigned char *p;
|
||||
|
||||
attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate);
|
||||
if (attr == NULL)
|
||||
if (attr == NULL || attr->type != V_ASN1_SEQUENCE)
|
||||
return NULL;
|
||||
p = attr->value.sequence->data;
|
||||
return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
|
||||
|
|
@ -222,7 +222,7 @@ ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si)
|
|||
const unsigned char *p;
|
||||
|
||||
attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2);
|
||||
if (attr == NULL)
|
||||
if (attr == NULL || attr->type != V_ASN1_SEQUENCE)
|
||||
return NULL;
|
||||
p = attr->value.sequence->data;
|
||||
return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length);
|
||||
|
|
|
|||
Loading…
Reference in a new issue