git: 9c151e1fbf1a - main - openssl: Fix multiple vulnerabilities

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 27 Jan 2026 19:14:31 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=9c151e1fbf1a71a4912afa9693a39d55a00db4eb

commit 9c151e1fbf1a71a4912afa9693a39d55a00db4eb
Author:     Gordon Tetlow <gordon@FreeBSD.org>
AuthorDate: 2026-01-26 18:14:21 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-01-27 19:13:40 +0000

    openssl: Fix multiple vulnerabilities
    
    This is a rollup commit from upstream to fix:
      Improper validation of PBMAC1 parameters in PKCS#12 MAC verification (CVE-2025-11187)
      Stack buffer overflow in CMS AuthEnvelopedData parsing (CVE-2025-15467)
      NULL dereference in SSL_CIPHER_find() function on unknown cipher ID (CVE-2025-15468)
      "openssl dgst" one-shot codepath silently truncates inputs >16MB (CVE-2025-15469)
      TLS 1.3 CompressedCertificate excessive memory allocation (CVE-2025-66199)
      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-11187
    Security:       CVE-2025-15467
    Security:       CVE-2025-15468
    Security:       CVE-2025-15469
    Security:       CVE-2025-66199
    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
---
 crypto/openssl/apps/dgst.c               |  7 ++--
 crypto/openssl/apps/include/apps.h       |  2 +-
 crypto/openssl/apps/lib/apps.c           | 55 ++++++++++++++++----------------
 crypto/openssl/apps/pkeyutl.c            | 36 ++++++++++-----------
 crypto/openssl/apps/s_client.c           |  3 +-
 crypto/openssl/crypto/asn1/a_strex.c     |  6 ++--
 crypto/openssl/crypto/asn1/evp_asn1.c    | 20 ++++++++++++
 crypto/openssl/crypto/bio/bf_lbuf.c      | 32 +++++++++++++++----
 crypto/openssl/crypto/evp/evp_lib.c      |  5 ++-
 crypto/openssl/crypto/modes/ocb128.c     | 10 ++++--
 crypto/openssl/crypto/pkcs12/p12_decr.c  |  5 +++
 crypto/openssl/crypto/pkcs12/p12_kiss.c  | 10 ++++--
 crypto/openssl/crypto/pkcs12/p12_mutl.c  | 18 +++++++++--
 crypto/openssl/crypto/pkcs12/p12_utl.c   |  5 +++
 crypto/openssl/crypto/pkcs7/pk7_doit.c   |  2 ++
 crypto/openssl/crypto/ts/ts_rsp_verify.c |  4 +--
 crypto/openssl/ssl/quic/quic_impl.c      |  2 ++
 crypto/openssl/ssl/statem/statem_lib.c   |  6 ++++
 18 files changed, 158 insertions(+), 70 deletions(-)

diff --git a/crypto/openssl/apps/dgst.c b/crypto/openssl/apps/dgst.c
index 0fb1f45200a0..b002de18c94b 100644
--- a/crypto/openssl/apps/dgst.c
+++ b/crypto/openssl/apps/dgst.c
@@ -704,12 +704,11 @@ static int do_fp_oneshot_sign(BIO *out, EVP_MD_CTX *ctx, BIO *in, int sep, int b
 {
     int res, ret = EXIT_FAILURE;
     size_t len = 0;
-    int buflen = 0;
-    int maxlen = 16 * 1024 * 1024;
+    size_t buflen = 0;
+    size_t maxlen = 16 * 1024 * 1024;
     uint8_t *buf = NULL, *sig = NULL;
 
-    buflen = bio_to_mem(&buf, maxlen, in);
-    if (buflen <= 0) {
+    if (!bio_to_mem(&buf, &buflen, maxlen, in)) {
         BIO_printf(bio_err, "Read error in %s\n", file);
         return ret;
     }
diff --git a/crypto/openssl/apps/include/apps.h b/crypto/openssl/apps/include/apps.h
index 11381ea7da8c..026cbfe7aecd 100644
--- a/crypto/openssl/apps/include/apps.h
+++ b/crypto/openssl/apps/include/apps.h
@@ -253,7 +253,7 @@ int parse_yesno(const char *str, int def);
 X509_NAME *parse_name(const char *str, int chtype, int multirdn,
                       const char *desc);
 void policies_print(X509_STORE_CTX *ctx);
-int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
+int bio_to_mem(unsigned char **out, size_t *outlen, size_t maxlen, BIO *in);
 int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
 int x509_ctrl_string(X509 *x, const char *value);
 int x509_req_ctrl_string(X509_REQ *x, const char *value);
diff --git a/crypto/openssl/apps/lib/apps.c b/crypto/openssl/apps/lib/apps.c
index 1b9c9e3e9a19..6e0f756524d8 100644
--- a/crypto/openssl/apps/lib/apps.c
+++ b/crypto/openssl/apps/lib/apps.c
@@ -49,6 +49,7 @@
 #include "apps.h"
 
 #include "internal/sockets.h" /* for openssl_fdset() */
+#include "internal/numbers.h" /* for LONG_MAX */
 #include "internal/e_os.h"
 
 #ifdef _WIN32
@@ -2010,45 +2011,45 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
 }
 
 /*
- * Read whole contents of a BIO into an allocated memory buffer and return
- * it.
+ * Read whole contents of a BIO into an allocated memory buffer.
+ * The return value is one on success, zero on error.
+ * If `maxlen` is non-zero, at most `maxlen` bytes are returned, or else, if
+ * the input is longer than `maxlen`, an error is returned.
+ * If `maxlen` is zero, the limit is effectively `SIZE_MAX`.
  */
-
-int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
+int bio_to_mem(unsigned char **out, size_t *outlen, size_t maxlen, BIO *in)
 {
+    unsigned char tbuf[4096];
     BIO *mem;
-    int len, ret;
-    unsigned char tbuf[1024];
+    BUF_MEM *bufm;
+    size_t sz = 0;
+    int len;
 
     mem = BIO_new(BIO_s_mem());
     if (mem == NULL)
-        return -1;
+        return 0;
     for (;;) {
-        if ((maxlen != -1) && maxlen < 1024)
-            len = maxlen;
-        else
-            len = 1024;
-        len = BIO_read(in, tbuf, len);
-        if (len < 0) {
-            BIO_free(mem);
-            return -1;
-        }
-        if (len == 0)
+        if ((len = BIO_read(in, tbuf, 4096)) == 0)
             break;
-        if (BIO_write(mem, tbuf, len) != len) {
+        if (len < 0
+            || BIO_write(mem, tbuf, len) != len
+            || sz > SIZE_MAX - len
+            || ((sz += len) > maxlen && maxlen != 0)) {
             BIO_free(mem);
-            return -1;
+            return 0;
         }
-        if (maxlen != -1)
-            maxlen -= len;
-
-        if (maxlen == 0)
-            break;
     }
-    ret = BIO_get_mem_data(mem, (char **)out);
-    BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
+
+    /* So BIO_free orphans BUF_MEM */
+    (void)BIO_set_close(mem, BIO_NOCLOSE);
+    BIO_get_mem_ptr(mem, &bufm);
     BIO_free(mem);
-    return ret;
+    *out = (unsigned char *)bufm->data;
+    *outlen = bufm->length;
+    /* Tell BUF_MEM to orphan data */
+    bufm->data = NULL;
+    BUF_MEM_free(bufm);
+    return 1;
 }
 
 int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
diff --git a/crypto/openssl/apps/pkeyutl.c b/crypto/openssl/apps/pkeyutl.c
index 79ad4c6f29f5..5ddf1c02c09b 100644
--- a/crypto/openssl/apps/pkeyutl.c
+++ b/crypto/openssl/apps/pkeyutl.c
@@ -40,7 +40,7 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
 
 static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
                         EVP_PKEY *pkey, BIO *in,
-                        int filesize, unsigned char *sig, int siglen,
+                        int filesize, unsigned char *sig, size_t siglen,
                         unsigned char **out, size_t *poutlen);
 
 static int only_nomd(EVP_PKEY *pkey)
@@ -133,7 +133,7 @@ int pkeyutl_main(int argc, char **argv)
     char hexdump = 0, asn1parse = 0, rev = 0, *prog;
     unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL, *secret = NULL;
     OPTION_CHOICE o;
-    int buf_inlen = 0, siglen = -1;
+    size_t buf_inlen = 0, siglen = 0;
     int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
     int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
     int engine_impl = 0;
@@ -486,31 +486,31 @@ int pkeyutl_main(int argc, char **argv)
 
     if (sigfile != NULL) {
         BIO *sigbio = BIO_new_file(sigfile, "rb");
+        size_t maxsiglen = 16 * 1024 * 1024;
 
         if (sigbio == NULL) {
             BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
             goto end;
         }
-        siglen = bio_to_mem(&sig, keysize * 10, sigbio);
-        BIO_free(sigbio);
-        if (siglen < 0) {
+        if (!bio_to_mem(&sig, &siglen, maxsiglen, sigbio)) {
+            BIO_free(sigbio);
             BIO_printf(bio_err, "Error reading signature data\n");
             goto end;
         }
+        BIO_free(sigbio);
     }
 
     /* Raw input data is handled elsewhere */
     if (in != NULL && !rawin) {
         /* Read the input data */
-        buf_inlen = bio_to_mem(&buf_in, -1, in);
-        if (buf_inlen < 0) {
+        if (!bio_to_mem(&buf_in, &buf_inlen, 0, in)) {
             BIO_printf(bio_err, "Error reading input Data\n");
             goto end;
         }
         if (rev) {
             size_t i;
             unsigned char ctmp;
-            size_t l = (size_t)buf_inlen;
+            size_t l = buf_inlen;
 
             for (i = 0; i < l / 2; i++) {
                 ctmp = buf_in[i];
@@ -525,7 +525,8 @@ int pkeyutl_main(int argc, char **argv)
         && (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY)) {
         if (buf_inlen > EVP_MAX_MD_SIZE) {
             BIO_printf(bio_err,
-                       "Error: The non-raw input data length %d is too long - max supported hashed size is %d\n",
+                       "Error: The non-raw input data length %zd is too long - "
+                       "max supported hashed size is %d\n",
                        buf_inlen, EVP_MAX_MD_SIZE);
             goto end;
         }
@@ -536,8 +537,7 @@ int pkeyutl_main(int argc, char **argv)
             rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
                               NULL, 0);
         } else {
-            rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
-                                 buf_in, (size_t)buf_inlen);
+            rv = EVP_PKEY_verify(ctx, sig, siglen, buf_in, buf_inlen);
         }
         if (rv == 1) {
             BIO_puts(out, "Signature Verified Successfully\n");
@@ -556,8 +556,8 @@ int pkeyutl_main(int argc, char **argv)
             buf_outlen = kdflen;
             rv = 1;
         } else {
-            rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
-                          buf_in, (size_t)buf_inlen, NULL, (size_t *)&secretlen);
+            rv = do_keyop(ctx, pkey_op, NULL, &buf_outlen,
+                buf_in, buf_inlen, NULL, &secretlen);
         }
         if (rv > 0
             && (secretlen > 0 || (pkey_op != EVP_PKEY_OP_ENCAPSULATE
@@ -568,8 +568,8 @@ int pkeyutl_main(int argc, char **argv)
             if (secretlen > 0)
                 secret = app_malloc(secretlen, "secret output");
             rv = do_keyop(ctx, pkey_op,
-                          buf_out, (size_t *)&buf_outlen,
-                          buf_in, (size_t)buf_inlen, secret, (size_t *)&secretlen);
+                buf_out, &buf_outlen,
+                buf_in, buf_inlen, secret, &secretlen);
         }
     }
     if (rv <= 0) {
@@ -838,7 +838,7 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
 
 static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
                         EVP_PKEY *pkey, BIO *in,
-                        int filesize, unsigned char *sig, int siglen,
+                        int filesize, unsigned char *sig, size_t siglen,
                         unsigned char **out, size_t *poutlen)
 {
     int rv = 0;
@@ -861,7 +861,7 @@ static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
                 BIO_printf(bio_err, "Error reading raw input data\n");
                 goto end;
             }
-            rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
+            rv = EVP_DigestVerify(mctx, sig, siglen, mbuf, buf_len);
             break;
         case EVP_PKEY_OP_SIGN:
             buf_len = BIO_read(in, mbuf, filesize);
@@ -895,7 +895,7 @@ static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
                 goto end;
             }
         }
-        rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
+        rv = EVP_DigestVerifyFinal(mctx, sig, siglen);
         break;
     case EVP_PKEY_OP_SIGN:
         for (;;) {
diff --git a/crypto/openssl/apps/s_client.c b/crypto/openssl/apps/s_client.c
index ffb4597a197c..5c7f4a93c9fa 100644
--- a/crypto/openssl/apps/s_client.c
+++ b/crypto/openssl/apps/s_client.c
@@ -2834,8 +2834,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;
             }
diff --git a/crypto/openssl/crypto/asn1/a_strex.c b/crypto/openssl/crypto/asn1/a_strex.c
index 4b031a73add5..cfe2644f572c 100644
--- a/crypto/openssl/crypto/asn1/a_strex.c
+++ b/crypto/openssl/crypto/asn1/a_strex.c
@@ -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
diff --git a/crypto/openssl/crypto/asn1/evp_asn1.c b/crypto/openssl/crypto/asn1/evp_asn1.c
index 13d8ed3893ab..6aca0117bc11 100644
--- a/crypto/openssl/crypto/asn1/evp_asn1.c
+++ b/crypto/openssl/crypto/asn1/evp_asn1.c
@@ -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)
 {
diff --git a/crypto/openssl/crypto/bio/bf_lbuf.c b/crypto/openssl/crypto/bio/bf_lbuf.c
index eed3dc4633e0..ce7123171aa3 100644
--- a/crypto/openssl/crypto/bio/bf_lbuf.c
+++ b/crypto/openssl/crypto/bio/bf_lbuf.c
@@ -186,14 +186,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;
 }
 
diff --git a/crypto/openssl/crypto/evp/evp_lib.c b/crypto/openssl/crypto/evp/evp_lib.c
index 32ada929e1be..a4aa302a0ffa 100644
--- a/crypto/openssl/crypto/evp/evp_lib.c
+++ b/crypto/openssl/crypto/evp/evp_lib.c
@@ -228,10 +228,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;
diff --git a/crypto/openssl/crypto/modes/ocb128.c b/crypto/openssl/crypto/modes/ocb128.c
index 1ae807c100d0..6fe266981005 100644
--- a/crypto/openssl/crypto/modes/ocb128.c
+++ b/crypto/openssl/crypto/modes/ocb128.c
@@ -338,7 +338,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
@@ -352,6 +352,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++) {
@@ -430,7 +433,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
@@ -444,6 +447,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;
 
diff --git a/crypto/openssl/crypto/pkcs12/p12_decr.c b/crypto/openssl/crypto/pkcs12/p12_decr.c
index 3fa9c9c8ccec..ce603878c0d6 100644
--- a/crypto/openssl/crypto/pkcs12/p12_decr.c
+++ b/crypto/openssl/crypto/pkcs12/p12_decr.c
@@ -143,6 +143,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;
diff --git a/crypto/openssl/crypto/pkcs12/p12_kiss.c b/crypto/openssl/crypto/pkcs12/p12_kiss.c
index 0901dc94085f..a813450f588c 100644
--- a/crypto/openssl/crypto/pkcs12/p12_kiss.c
+++ b/crypto/openssl/crypto/pkcs12/p12_kiss.c
@@ -197,11 +197,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:
diff --git a/crypto/openssl/crypto/pkcs12/p12_mutl.c b/crypto/openssl/crypto/pkcs12/p12_mutl.c
index b43c82f0ed29..f6c7be483de8 100644
--- a/crypto/openssl/crypto/pkcs12/p12_mutl.c
+++ b/crypto/openssl/crypto/pkcs12/p12_mutl.c
@@ -122,8 +122,6 @@ static int PBMAC1_PBKDF2_HMAC(OSSL_LIB_CTX *ctx, const char *propq,
         ERR_raise(ERR_LIB_PKCS12, ERR_R_UNSUPPORTED);
         goto err;
     }
-    keylen = ASN1_INTEGER_get(pbkdf2_param->keylength);
-    pbkdf2_salt = pbkdf2_param->salt->value.octet_string;
 
     if (pbkdf2_param->prf == NULL) {
         kdf_hmac_nid = NID_hmacWithSHA1;
@@ -138,6 +136,22 @@ static int PBMAC1_PBKDF2_HMAC(OSSL_LIB_CTX *ctx, const char *propq,
         goto err;
     }
 
+    /* Validate salt is an OCTET STRING choice */
+    if (pbkdf2_param->salt == NULL
+        || pbkdf2_param->salt->type != V_ASN1_OCTET_STRING) {
+        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
+        goto err;
+    }
+    pbkdf2_salt = pbkdf2_param->salt->value.octet_string;
+
+    /* RFC 9579 specifies missing key length as invalid */
+    if (pbkdf2_param->keylength != NULL)
+        keylen = ASN1_INTEGER_get(pbkdf2_param->keylength);
+    if (keylen <= 0 || keylen > EVP_MAX_MD_SIZE) {
+        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
+        goto err;
+    }
+
     if (PKCS5_PBKDF2_HMAC(pass, passlen, pbkdf2_salt->data, pbkdf2_salt->length,
                           ASN1_INTEGER_get(pbkdf2_param->iter), kdf_md, keylen, key) <= 0) {
         ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
diff --git a/crypto/openssl/crypto/pkcs12/p12_utl.c b/crypto/openssl/crypto/pkcs12/p12_utl.c
index a96623f19fba..082706d5f522 100644
--- a/crypto/openssl/crypto/pkcs12/p12_utl.c
+++ b/crypto/openssl/crypto/pkcs12/p12_utl.c
@@ -206,6 +206,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;
diff --git a/crypto/openssl/crypto/pkcs7/pk7_doit.c b/crypto/openssl/crypto/pkcs7/pk7_doit.c
index 6173e4608b8a..39809a0fdb96 100644
--- a/crypto/openssl/crypto/pkcs7/pk7_doit.c
+++ b/crypto/openssl/crypto/pkcs7/pk7_doit.c
@@ -1231,6 +1231,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;
 }
 
diff --git a/crypto/openssl/crypto/ts/ts_rsp_verify.c b/crypto/openssl/crypto/ts/ts_rsp_verify.c
index 0d9fa01e4337..60bc918d2d92 100644
--- a/crypto/openssl/crypto/ts/ts_rsp_verify.c
+++ b/crypto/openssl/crypto/ts/ts_rsp_verify.c
@@ -211,7 +211,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);
@@ -224,7 +224,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);
diff --git a/crypto/openssl/ssl/quic/quic_impl.c b/crypto/openssl/ssl/quic/quic_impl.c
index cec05d5bd37b..0c15ef05236c 100644
--- a/crypto/openssl/ssl/quic/quic_impl.c
+++ b/crypto/openssl/ssl/quic/quic_impl.c
@@ -5065,6 +5065,8 @@ const SSL_CIPHER *ossl_quic_get_cipher_by_char(const unsigned char *p)
 {
     const SSL_CIPHER *ciph = ssl3_get_cipher_by_char(p);
 
+    if (ciph == NULL)
+        return NULL;
     if ((ciph->algorithm2 & SSL_QUIC) == 0)
         return NULL;
 
diff --git a/crypto/openssl/ssl/statem/statem_lib.c b/crypto/openssl/ssl/statem/statem_lib.c
index 1e11d077f9e0..13f1af7e9fd0 100644
--- a/crypto/openssl/ssl/statem/statem_lib.c
+++ b/crypto/openssl/ssl/statem/statem_lib.c
@@ -2912,6 +2912,12 @@ MSG_PROCESS_RETURN tls13_process_compressed_certificate(SSL_CONNECTION *sc,
         goto err;
     }
 
+    /* Prevent excessive pre-decompression allocation */
+    if (expected_length > sc->max_cert_list) {
+        SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+        goto err;
+    }
+
     if (PACKET_remaining(pkt) != comp_length || comp_length == 0) {
         SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_DECOMPRESSION);
         goto err;