Version in base suite: 3.5.4-1~deb13u1 Base version: openssl_3.5.4-1~deb13u1 Target version: openssl_3.5.4-1~deb13u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/o/openssl/openssl_3.5.4-1~deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/o/openssl/openssl_3.5.4-1~deb13u2.dsc /srv/release.debian.org/tmp/VE4bdJnm7p/openssl-3.5.4/debian/CVE-2025-11187-binary.tar |binary openssl-3.5.4/debian/changelog | 26 openssl-3.5.4/debian/patches/Add-NULL-check-to-PKCS12_item_decrypt_d2i_ex.patch | 27 + openssl-3.5.4/debian/patches/Add-testcase-for-PKCS12-with-invalid-PBMAC1-key-length.patch | 36 + openssl-3.5.4/debian/patches/Check-return-code-of-UTF8_putc.patch | 47 + openssl-3.5.4/debian/patches/Check-the-received-uncompressed-certificate-length-to-pre.patch | 107 ++++ openssl-3.5.4/debian/patches/Correct-handling-of-AEAD-encrypted-CMS-with-inadmissibly-.patch | 26 openssl-3.5.4/debian/patches/Ensure-ASN1-types-are-checked-before-use.patch | 70 ++ openssl-3.5.4/debian/patches/Fix-OCB-AES-NI-HW-stream-path-unauthenticated-unencrypted.patch | 66 ++ openssl-3.5.4/debian/patches/Fix-heap-buffer-overflow-in-BIO_f_linebuffer.patch | 63 ++ openssl-3.5.4/debian/patches/Harden-ASN1_mbstring_ncopy.patch | 119 ++++ openssl-3.5.4/debian/patches/Report-truncation-in-oneshot-openssl-dgst-sign.patch | 265 ++++++++++ openssl-3.5.4/debian/patches/Some-comments-to-clarify-functions-usage.patch | 53 ++ openssl-3.5.4/debian/patches/Test-for-handling-of-AEAD-encrypted-CMS-with-inadmissibly.patch | 121 ++++ openssl-3.5.4/debian/patches/Verify-ASN1-object-s-types-before-attempting-to-access-th.patch | 36 + openssl-3.5.4/debian/patches/ossl_quic_get_cipher_by_char-Add-a-NULL-guard-before-dere.patch | 23 openssl-3.5.4/debian/patches/pkcs12-Validate-salt-and-keylength-in-PBMAC1.patch | 53 ++ openssl-3.5.4/debian/patches/series | 15 openssl-3.5.4/debian/rules | 1 openssl-3.5.4/debian/source/include-binaries | 1 20 files changed, 1155 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp_tdvefsh/openssl_3.5.4-1~deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp_tdvefsh/openssl_3.5.4-1~deb13u2.dsc: no acceptable signature found Binary files /srv/release.debian.org/tmp/E44t3IHGt8/openssl-3.5.4/debian/CVE-2025-11187-binary.tar and /srv/release.debian.org/tmp/VE4bdJnm7p/openssl-3.5.4/debian/CVE-2025-11187-binary.tar differ diff -Nru openssl-3.5.4/debian/changelog openssl-3.5.4/debian/changelog --- openssl-3.5.4/debian/changelog 2025-11-01 11:22:59.000000000 +0000 +++ openssl-3.5.4/debian/changelog 2026-01-24 15:50:07.000000000 +0000 @@ -1,3 +1,29 @@ +openssl (3.5.4-1~deb13u2) trixie-security; urgency=medium + + * CVE-2025-11187 (Improper validation of PBMAC1 parameters in PKCS#12 MAC + verification) + * CVE-2025-15467 (Stack buffer overflow in CMS AuthEnvelopedData parsing) + * CVE-2025-15468 (NULL dereference in SSL_CIPHER_find() function on unknown + cipher ID) + * CVE-2025-15469 ("openssl dgst" one-shot codepath silently truncates inputs + >16MB) + * CVE-2025-66199 (TLS 1.3 CompressedCertificate excessive memory allocation) + * CVE-2025-68160 (Heap out-of-bounds write in BIO_f_linebuffer on short + writes) + * CVE-2025-69418 (Unauthenticated/unencrypted trailing bytes with low-level + OCB function calls) + * CVE-2025-69419 (Out of bounds write in PKCS12_get_friendlyname() UTF-8 + conversion) + * CVE-2025-69420 (Missing ASN1_TYPE validation in TS_RESP_verify_response() + function) + * CVE-2025-69421 (NULL Pointer Dereference in PKCS12_item_decrypt_d2i_ex + function) + * CVE-2026-22795 (Missing ASN1_TYPE validation in PKCS#12 parsing) + * CVE-2026-22796 (ASN1_TYPE Type Confusion in the + PKCS7_digest_from_attributes() function) + + -- Sebastian Andrzej Siewior Sat, 24 Jan 2026 16:50:07 +0100 + openssl (3.5.4-1~deb13u1) trixie; urgency=medium * Import 3.5.4 diff -Nru openssl-3.5.4/debian/patches/Add-NULL-check-to-PKCS12_item_decrypt_d2i_ex.patch openssl-3.5.4/debian/patches/Add-NULL-check-to-PKCS12_item_decrypt_d2i_ex.patch --- openssl-3.5.4/debian/patches/Add-NULL-check-to-PKCS12_item_decrypt_d2i_ex.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Add-NULL-check-to-PKCS12_item_decrypt_d2i_ex.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,27 @@ +From: Andrew Dinh +Date: Thu, 8 Jan 2026 01:24:30 +0900 +Subject: Add NULL check to PKCS12_item_decrypt_d2i_ex + +Address CVE-2025-69421 + +Add NULL check for oct parameter +--- + crypto/pkcs12/p12_decr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c +index 3fa9c9c8ccec..ce603878c0d6 100644 +--- a/crypto/pkcs12/p12_decr.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Add-testcase-for-PKCS12-with-invalid-PBMAC1-key-length.patch openssl-3.5.4/debian/patches/Add-testcase-for-PKCS12-with-invalid-PBMAC1-key-length.patch --- openssl-3.5.4/debian/patches/Add-testcase-for-PKCS12-with-invalid-PBMAC1-key-length.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Add-testcase-for-PKCS12-with-invalid-PBMAC1-key-length.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,36 @@ +From: Tomas Mraz +Date: Thu, 8 Jan 2026 15:25:18 +0100 +Subject: Add testcase for PKCS12 with invalid PBMAC1 key length + +--- + test/recipes/80-test_pkcs12.t | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t +index 06fa85af0f3e..ff720894c9bf 100644 +--- a/test/recipes/80-test_pkcs12.t ++++ b/test/recipes/80-test_pkcs12.t +@@ -56,7 +56,7 @@ $ENV{OPENSSL_WIN32_UTF8}=1; + + my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); + +-plan tests => $no_fips ? 47 : 53; ++plan tests => $no_fips ? 53 : 59; + + # Test different PKCS#12 formats + ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); +@@ -235,8 +235,12 @@ unless ($no_fips) { + } + } + +-# Test pbmac1 pkcs12 bad files, RFC 9579 +-for my $file ("pbmac1_256_256.bad-iter.p12", "pbmac1_256_256.bad-salt.p12", "pbmac1_256_256.no-len.p12") ++# Test pbmac1 pkcs12 bad files, RFC 9579 and CVE-2025-11187 ++for my $file ("pbmac1_256_256.bad-iter.p12", "pbmac1_256_256.bad-salt.p12", ++ "pbmac1_256_256.no-len.p12", "pbmac1_256_256.bad-len.p12", ++ "pbmac1_256_256.bad-salt-type.p12", "pbmac1_256_256.negative-len.p12", ++ "pbmac1_256_256.no-salt.p12", "pbmac1_256_256.very-big-len.p12", ++ "pbmac1_256_256.zero-len.p12") + { + my $path = srctop_file("test", "recipes", "80-test_pkcs12_data", $file); + with({ exit_checker => sub { return shift == 1; } }, diff -Nru openssl-3.5.4/debian/patches/Check-return-code-of-UTF8_putc.patch openssl-3.5.4/debian/patches/Check-return-code-of-UTF8_putc.patch --- openssl-3.5.4/debian/patches/Check-return-code-of-UTF8_putc.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Check-return-code-of-UTF8_putc.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,47 @@ +From: Norbert Pocs +Date: Thu, 11 Dec 2025 12:49:00 +0100 +Subject: Check return code of UTF8_putc + +Signed-off-by: Norbert Pocs + +Reviewed-by: Nikola Pajkovsky +Reviewed-by: Viktor Dukhovni +(Merged from https://github.com/openssl/openssl/pull/29376) +--- + crypto/asn1/a_strex.c | 6 ++++-- + crypto/pkcs12/p12_utl.c | 5 +++++ + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c +index 4b031a73add5..cfe2644f572c 100644 +--- a/crypto/asn1/a_strex.c ++++ b/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/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c +index a96623f19fba..082706d5f522 100644 +--- a/crypto/pkcs12/p12_utl.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Check-the-received-uncompressed-certificate-length-to-pre.patch openssl-3.5.4/debian/patches/Check-the-received-uncompressed-certificate-length-to-pre.patch --- openssl-3.5.4/debian/patches/Check-the-received-uncompressed-certificate-length-to-pre.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Check-the-received-uncompressed-certificate-length-to-pre.patch 2026-01-24 15:49:31.000000000 +0000 @@ -0,0 +1,107 @@ +From: Igor Ustinov +Date: Thu, 8 Jan 2026 14:02:54 +0100 +Subject: Check the received uncompressed certificate length to prevent + excessive pre-decompression allocation. + +The patch was proposed by Tomas Dulka and Stanislav Fort (Aisle Research). + +Fixes: CVE-2025-66199 +--- + ssl/statem/statem_lib.c | 6 ++++++ + test/recipes/70-test_tls13certcomp.t | 42 +++++++++++++++++++++++++++++++++++- + util/perl/TLSProxy/Message.pm | 1 + + 3 files changed, 48 insertions(+), 1 deletion(-) + +diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c +index 1e11d077f9e0..b24c500a5ce4 100644 +--- a/ssl/statem/statem_lib.c ++++ b/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_BAD_CERTIFICATE, 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; +diff --git a/test/recipes/70-test_tls13certcomp.t b/test/recipes/70-test_tls13certcomp.t +index 5424b128d1aa..68c410b767fb 100644 +--- a/test/recipes/70-test_tls13certcomp.t ++++ b/test/recipes/70-test_tls13certcomp.t +@@ -11,6 +11,7 @@ use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/; + use OpenSSL::Test::Utils; + use File::Temp qw(tempfile); + use TLSProxy::Proxy; ++use TLSProxy::Message; + use checkhandshake qw(checkhandshake @handmessages @extensions); + + my $test_name = "test_tls13certcomp"; +@@ -220,7 +221,7 @@ $proxy->clear(); + $proxy->serverflags("-no_tx_cert_comp -no_rx_cert_comp"); + # One final skip check + $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; +-plan tests => 8; ++plan tests => 9; + checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, + checkhandshake::DEFAULT_EXTENSIONS + | checkhandshake::CERT_COMP_CLI_EXTENSION, +@@ -296,3 +297,42 @@ $proxy->start(); + checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, + checkhandshake::DEFAULT_EXTENSIONS, + "Send but not accept compressed certificates"); ++ ++#Test 9: Excessive uncompressed certificate length in CompressedCertificate ++$proxy->clear(); ++$proxy->filter(\&excessive_uncompressed_len_filter); ++$proxy->serverflags("-cert_comp"); ++$proxy->start(); ++ok(is_alert_message(TLSProxy::Message::AL_DESC_BAD_CERTIFICATE), ++ "Excessive uncompressed certificate length rejected"); ++ ++my $done = 0; ++ ++sub excessive_uncompressed_len_filter ++{ ++ my $proxy = shift; ++ ++ return if $done; ++ ++ foreach my $m (@{$proxy->message_list}) { ++ next unless $m->mt == TLSProxy::Message::MT_COMPRESSED_CERTIFICATE; ++ ++ my $data = $m->data; ++ # RFC8879 CompressedCertificate: ++ # uint16 algorithm; uint24 uncompressed_length; ... ++ substr($data, 2, 3) = "\xFF\xFF\xFF"; # uncompressed_length ++ $m->data($data); ++ $m->repack(); ++ $done = 1; ++ last; ++ } ++} ++ ++# Test if the last message was a failure and matches the expected type. ++sub is_alert_message ++{ ++ my $alert_type = shift; ++ return 0 unless TLSProxy::Message->fail(); ++ return 1 if TLSProxy::Message->alert->description() == $alert_type; ++ return 0; ++} +diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm +index 82db4022c24f..2b9536513f0f 100644 +--- a/util/perl/TLSProxy/Message.pm ++++ b/util/perl/TLSProxy/Message.pm +@@ -45,6 +45,7 @@ use constant { + AL_DESC_CLOSE_NOTIFY => 0, + AL_DESC_UNEXPECTED_MESSAGE => 10, + AL_DESC_BAD_RECORD_MAC => 20, ++ AL_DESC_BAD_CERTIFICATE => 42, + AL_DESC_ILLEGAL_PARAMETER => 47, + AL_DESC_DECODE_ERROR => 50, + AL_DESC_PROTOCOL_VERSION => 70, diff -Nru openssl-3.5.4/debian/patches/Correct-handling-of-AEAD-encrypted-CMS-with-inadmissibly-.patch openssl-3.5.4/debian/patches/Correct-handling-of-AEAD-encrypted-CMS-with-inadmissibly-.patch --- openssl-3.5.4/debian/patches/Correct-handling-of-AEAD-encrypted-CMS-with-inadmissibly-.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Correct-handling-of-AEAD-encrypted-CMS-with-inadmissibly-.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,26 @@ +From: Igor Ustinov +Date: Mon, 12 Jan 2026 12:13:35 +0100 +Subject: Correct handling of AEAD-encrypted CMS with inadmissibly long IV + +Fixes CVE-2025-15467 +--- + crypto/evp/evp_lib.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c +index 32ada929e1be..a4aa302a0ffa 100644 +--- a/crypto/evp/evp_lib.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Ensure-ASN1-types-are-checked-before-use.patch openssl-3.5.4/debian/patches/Ensure-ASN1-types-are-checked-before-use.patch --- openssl-3.5.4/debian/patches/Ensure-ASN1-types-are-checked-before-use.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Ensure-ASN1-types-are-checked-before-use.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,70 @@ +From: Bob Beck +Date: Wed, 7 Jan 2026 11:29:48 -0700 +Subject: Ensure ASN1 types are checked before use. + +Some of these were fixed by LibreSSL in commit https://github.com/openbsd/src/commit/aa1f637d454961d22117b4353f98253e984b3ba8 +this fix includes the other fixes in that commit, as well as fixes for others found by a scan +for a similar unvalidated access paradigm in the tree. + +Reviewed-by: Kurt Roeckx +Reviewed-by: Shane Lontis +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/29582) +--- + apps/s_client.c | 3 ++- + crypto/pkcs12/p12_kiss.c | 10 ++++++++-- + crypto/pkcs7/pk7_doit.c | 2 ++ + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/apps/s_client.c b/apps/s_client.c +index ffb4597a197c..5c7f4a93c9fa 100644 +--- a/apps/s_client.c ++++ b/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/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c +index 0901dc94085f..a813450f588c 100644 +--- a/crypto/pkcs12/p12_kiss.c ++++ b/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/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c +index 6173e4608b8a..39809a0fdb96 100644 +--- a/crypto/pkcs7/pk7_doit.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Fix-OCB-AES-NI-HW-stream-path-unauthenticated-unencrypted.patch openssl-3.5.4/debian/patches/Fix-OCB-AES-NI-HW-stream-path-unauthenticated-unencrypted.patch --- openssl-3.5.4/debian/patches/Fix-OCB-AES-NI-HW-stream-path-unauthenticated-unencrypted.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Fix-OCB-AES-NI-HW-stream-path-unauthenticated-unencrypted.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,66 @@ +From: Norbert Pocs +Date: Thu, 8 Jan 2026 15:04:54 +0100 +Subject: Fix OCB AES-NI/HW stream path unauthenticated/unencrypted trailing + bytes +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +When ctx->stream (e.g., AES‑NI or ARMv8 CE) is available, the fast path +encrypts/decrypts full blocks but does not advance in/out pointers. The +tail-handling code then operates on the base pointers, effectively reprocessing +the beginning of the buffer while leaving the actual trailing bytes +unencrypted (encryption) or using the wrong plaintext (decryption). The +authentication checksum excludes the true tail. + +CVE-2025-69418 + +Fixes: https://github.com/openssl/srt/issues/58 + +Signed-off-by: Norbert Pocs +--- + crypto/modes/ocb128.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c +index 1ae807c100d0..6fe266981005 100644 +--- a/crypto/modes/ocb128.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Fix-heap-buffer-overflow-in-BIO_f_linebuffer.patch openssl-3.5.4/debian/patches/Fix-heap-buffer-overflow-in-BIO_f_linebuffer.patch --- openssl-3.5.4/debian/patches/Fix-heap-buffer-overflow-in-BIO_f_linebuffer.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Fix-heap-buffer-overflow-in-BIO_f_linebuffer.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,63 @@ +From: Neil Horman +Date: Wed, 7 Jan 2026 11:52:09 -0500 +Subject: Fix heap buffer overflow in BIO_f_linebuffer + +When a FIO_f_linebuffer is part of a bio chain, and the next BIO +preforms short writes, the remainder of the unwritten buffer is copied +unconditionally to the internal buffer ctx->obuf, which may not be +sufficiently sized to handle the remaining data, resulting in a buffer +overflow. + +Fix it by only copying data when ctx->obuf has space, flushing to the +next BIO to increase available storage if needed. + +Fixes CVE-2025-68160 +--- + crypto/bio/bf_lbuf.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/crypto/bio/bf_lbuf.c b/crypto/bio/bf_lbuf.c +index eed3dc4633e0..ce7123171aa3 100644 +--- a/crypto/bio/bf_lbuf.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Harden-ASN1_mbstring_ncopy.patch openssl-3.5.4/debian/patches/Harden-ASN1_mbstring_ncopy.patch --- openssl-3.5.4/debian/patches/Harden-ASN1_mbstring_ncopy.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Harden-ASN1_mbstring_ncopy.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,119 @@ +From: Norbert Pocs +Date: Thu, 11 Dec 2025 12:38:16 +0100 +Subject: Harden ASN1_mbstring_ncopy + +Reported by Murali Aniruddhan + +Signed-off-by: Norbert Pocs + +Reviewed-by: Nikola Pajkovsky +Reviewed-by: Viktor Dukhovni +(Merged from https://github.com/openssl/openssl/pull/29376) +--- + crypto/asn1/a_mbstr.c | 35 ++++++++++++++++++++++++++++++++--- + test/asn1_internal_test.c | 17 +++++++++++++++++ + 2 files changed, 49 insertions(+), 3 deletions(-) + +diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c +index c8170e16267d..a61fc9418254 100644 +--- a/crypto/asn1/a_mbstr.c ++++ b/crypto/asn1/a_mbstr.c +@@ -114,7 +114,10 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + return -1; + } + +- /* Now work out output format and string type */ ++ /* ++ * Now work out output format and string type. ++ * These checks should be in sync with the checks in type_str. ++ */ + outform = MBSTRING_ASC; + if (mask & B_ASN1_NUMERICSTRING) + str_type = V_ASN1_NUMERICSTRING; +@@ -182,7 +185,11 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + + 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) { ++ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING); ++ return -1; ++ } + cpyfunc = cpy_utf8; + break; + } +@@ -277,9 +284,29 @@ static int out_utf8(unsigned long value, void *arg) + + static int type_str(unsigned long value, void *arg) + { +- unsigned long types = *((unsigned long *)arg); ++ unsigned long usable_types = *((unsigned long *)arg); ++ unsigned long types = usable_types; + const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value); + ++ /* ++ * Clear out all the types which are not checked later. If any of those ++ * is present in the mask, then the UTF8 type will be added and checked ++ * below. ++ */ ++ types &= B_ASN1_NUMERICSTRING | B_ASN1_PRINTABLESTRING ++ | B_ASN1_IA5STRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING ++ | B_ASN1_UNIVERSALSTRING | B_ASN1_UTF8STRING; ++ ++ /* ++ * If any other types were in the input mask, they're effectively treated ++ * as UTF8 ++ */ ++ if (types != usable_types) ++ types |= B_ASN1_UTF8STRING; ++ ++ /* ++ * These checks should be in sync with ASN1_mbstring_ncopy. ++ */ + if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native) + || native == ' ')) + types &= ~B_ASN1_NUMERICSTRING; +@@ -348,6 +375,8 @@ static int cpy_utf8(unsigned long value, void *arg) + p = arg; + /* We already know there is enough room so pass 0xff as the length */ + ret = UTF8_putc(*p, 0xff, value); ++ if (ret < 0) ++ return ret; + *p += ret; + return 1; + } +diff --git a/test/asn1_internal_test.c b/test/asn1_internal_test.c +index 3c2222d988df..648bca90ce87 100644 +--- a/test/asn1_internal_test.c ++++ b/test/asn1_internal_test.c +@@ -264,6 +264,22 @@ static int test_obj_nid_undef(void) + return 1; + } + ++static int test_mbstring_ncopy(void) ++{ ++ ASN1_STRING *str = NULL; ++ const unsigned char in[] = { 0xFF, 0xFE, 0xFF, 0xFE }; ++ int inlen = 4; ++ int inform = MBSTRING_UNIV; ++ ++ if (!TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_GENERALSTRING, 0, 0), -1) ++ || !TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_VISIBLESTRING, 0, 0), -1) ++ || !TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_VIDEOTEXSTRING, 0, 0), -1) ++ || !TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_GENERALIZEDTIME, 0, 0), -1)) ++ return 0; ++ ++ return 1; ++} ++ + int setup_tests(void) + { + ADD_TEST(test_tbl_standard); +@@ -272,5 +288,6 @@ int setup_tests(void) + ADD_TEST(test_unicode_range); + ADD_TEST(test_obj_create); + ADD_TEST(test_obj_nid_undef); ++ ADD_TEST(test_mbstring_ncopy); + return 1; + } diff -Nru openssl-3.5.4/debian/patches/Report-truncation-in-oneshot-openssl-dgst-sign.patch openssl-3.5.4/debian/patches/Report-truncation-in-oneshot-openssl-dgst-sign.patch --- openssl-3.5.4/debian/patches/Report-truncation-in-oneshot-openssl-dgst-sign.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Report-truncation-in-oneshot-openssl-dgst-sign.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,265 @@ +From: Viktor Dukhovni +Date: Wed, 7 Jan 2026 01:21:58 +1100 +Subject: Report truncation in oneshot `openssl dgst -sign` + +Previously input was silently truncated at 16MB, now if the input is +longer than limit, an error is reported. + +The bio_to_mem() apps helper function was changed to return 0 or 1, +and return the size of the result via an output size_t pointer. + +Fixes CVE-2025-15469 +--- + apps/dgst.c | 7 +++---- + apps/include/apps.h | 2 +- + apps/lib/apps.c | 55 +++++++++++++++++++++++++++-------------------------- + apps/pkeyutl.c | 36 +++++++++++++++++------------------ + 4 files changed, 50 insertions(+), 50 deletions(-) + +diff --git a/apps/dgst.c b/apps/dgst.c +index 0fb1f45200a0..b002de18c94b 100644 +--- a/apps/dgst.c ++++ b/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/apps/include/apps.h b/apps/include/apps.h +index 11381ea7da8c..026cbfe7aecd 100644 +--- a/apps/include/apps.h ++++ b/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/apps/lib/apps.c b/apps/lib/apps.c +index 1b9c9e3e9a19..6e0f756524d8 100644 +--- a/apps/lib/apps.c ++++ b/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/apps/pkeyutl.c b/apps/pkeyutl.c +index 79ad4c6f29f5..be3d183ec650 100644 +--- a/apps/pkeyutl.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Some-comments-to-clarify-functions-usage.patch openssl-3.5.4/debian/patches/Some-comments-to-clarify-functions-usage.patch --- openssl-3.5.4/debian/patches/Some-comments-to-clarify-functions-usage.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Some-comments-to-clarify-functions-usage.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,53 @@ +From: Igor Ustinov +Date: Mon, 12 Jan 2026 12:15:42 +0100 +Subject: Some comments to clarify functions usage + +--- + crypto/asn1/evp_asn1.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/crypto/asn1/evp_asn1.c b/crypto/asn1/evp_asn1.c +index 13d8ed3893ab..6aca0117bc11 100644 +--- a/crypto/asn1/evp_asn1.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/Test-for-handling-of-AEAD-encrypted-CMS-with-inadmissibly.patch openssl-3.5.4/debian/patches/Test-for-handling-of-AEAD-encrypted-CMS-with-inadmissibly.patch --- openssl-3.5.4/debian/patches/Test-for-handling-of-AEAD-encrypted-CMS-with-inadmissibly.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Test-for-handling-of-AEAD-encrypted-CMS-with-inadmissibly.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,121 @@ +From: Igor Ustinov +Date: Sun, 11 Jan 2026 11:35:15 +0100 +Subject: Test for handling of AEAD-encrypted CMS with inadmissibly long IV + +--- + test/cmsapitest.c | 39 ++++++++++++++++++++-- + test/recipes/80-test_cmsapi.t | 3 +- + .../80-test_cmsapi_data/encDataWithTooLongIV.pem | 11 ++++++ + 3 files changed, 50 insertions(+), 3 deletions(-) + create mode 100644 test/recipes/80-test_cmsapi_data/encDataWithTooLongIV.pem + +diff --git a/test/cmsapitest.c b/test/cmsapitest.c +index 59dd7faeb284..3757e5264939 100644 +--- a/test/cmsapitest.c ++++ b/test/cmsapitest.c +@@ -9,10 +9,10 @@ + + #include + ++#include + #include + #include + #include +-#include + #include "../crypto/cms/cms_local.h" /* for d.signedData and d.envelopedData */ + + #include "testutil.h" +@@ -20,6 +20,7 @@ + static X509 *cert = NULL; + static EVP_PKEY *privkey = NULL; + static char *derin = NULL; ++static char *too_long_iv_cms_in = NULL; + + static int test_encrypt_decrypt(const EVP_CIPHER *cipher) + { +@@ -385,6 +386,38 @@ static int test_d2i_CMS_decode(const int idx) + return ret; + } + ++static int test_cms_aesgcm_iv_too_long(void) ++{ ++ int ret = 0; ++ BIO *cmsbio = NULL, *out = NULL; ++ CMS_ContentInfo *cms = NULL; ++ unsigned long err = 0; ++ ++ if (!TEST_ptr(cmsbio = BIO_new_file(too_long_iv_cms_in, "r"))) ++ goto end; ++ ++ if (!TEST_ptr(cms = PEM_read_bio_CMS(cmsbio, NULL, NULL, NULL))) ++ goto end; ++ ++ /* Must fail cleanly (no crash) */ ++ if (!TEST_false(CMS_decrypt(cms, privkey, cert, NULL, out, 0))) ++ goto end; ++ err = ERR_peek_last_error(); ++ if (!TEST_ulong_ne(err, 0)) ++ goto end; ++ if (!TEST_int_eq(ERR_GET_LIB(err), ERR_LIB_CMS)) ++ goto end; ++ if (!TEST_int_eq(ERR_GET_REASON(err), CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR)) ++ goto end; ++ ++ ret = 1; ++end: ++ CMS_ContentInfo_free(cms); ++ BIO_free(cmsbio); ++ BIO_free(out); ++ return ret; ++} ++ + OPT_TEST_DECLARE_USAGE("certfile privkeyfile derfile\n") + + int setup_tests(void) +@@ -399,7 +432,8 @@ int setup_tests(void) + + if (!TEST_ptr(certin = test_get_argument(0)) + || !TEST_ptr(privkeyin = test_get_argument(1)) +- || !TEST_ptr(derin = test_get_argument(2))) ++ || !TEST_ptr(derin = test_get_argument(2)) ++ || !TEST_ptr(too_long_iv_cms_in = test_get_argument(3))) + return 0; + + certbio = BIO_new_file(certin, "r"); +@@ -432,6 +466,7 @@ int setup_tests(void) + ADD_TEST(test_CMS_add1_cert); + ADD_TEST(test_d2i_CMS_bio_NULL); + ADD_ALL_TESTS(test_d2i_CMS_decode, 2); ++ ADD_TEST(test_cms_aesgcm_iv_too_long); + return 1; + } + +diff --git a/test/recipes/80-test_cmsapi.t b/test/recipes/80-test_cmsapi.t +index af00355a9d66..182629e71a06 100644 +--- a/test/recipes/80-test_cmsapi.t ++++ b/test/recipes/80-test_cmsapi.t +@@ -18,5 +18,6 @@ plan tests => 1; + + ok(run(test(["cmsapitest", srctop_file("test", "certs", "servercert.pem"), + srctop_file("test", "certs", "serverkey.pem"), +- srctop_file("test", "recipes", "80-test_cmsapi_data", "encryptedData.der")])), ++ srctop_file("test", "recipes", "80-test_cmsapi_data", "encryptedData.der"), ++ srctop_file("test", "recipes", "80-test_cmsapi_data", "encDataWithTooLongIV.pem")])), + "running cmsapitest"); +diff --git a/test/recipes/80-test_cmsapi_data/encDataWithTooLongIV.pem b/test/recipes/80-test_cmsapi_data/encDataWithTooLongIV.pem +new file mode 100644 +index 000000000000..4323cd2fb0c1 +--- /dev/null ++++ b/test/recipes/80-test_cmsapi_data/encDataWithTooLongIV.pem +@@ -0,0 +1,11 @@ ++-----BEGIN CMS----- ++MIIBmgYLKoZIhvcNAQkQARegggGJMIIBhQIBADGCATMwggEvAgEAMBcwEjEQMA4G ++A1UEAwwHUm9vdCBDQQIBAjANBgkqhkiG9w0BAQEFAASCAQC8ZqP1OqbletcUre1V ++b4XOobZzQr6wKMSsdjtGzVbZowUVv5DkOn9VOefrpg4HxMq/oi8IpzVYj8ZiKRMV ++NTJ+/d8FwwBwUUNNP/IDnfEpX+rT1+pGS5zAa7NenLoZgGBNjPy5I2OHP23fPnEd ++sm8YkFjzubkhAD1lod9pEOEqB3V2kTrTTiwzSNtMHggna1zPox6TkdZwFmMnp8d2 ++CVa6lIPGx26gFwCuIDSaavmQ2URJ615L8gAvpYUlpsDqjFsabWsbaOFbMz3bIGJu ++GkrX2ezX7CpuC1wjix26ojlTySJHv+L0IrpcaIzLlC5lB1rqtuija8dGm3rBNm/P ++AAUNMDcGCSqGSIb3DQEHATAjBglghkgBZQMEAQYwFgQRzxwoRQzOHVooVn3CpaWl ++paUCARCABUNdolo6BBA55E9hYaYO2S8C/ZnD8dRO ++-----END CMS----- diff -Nru openssl-3.5.4/debian/patches/Verify-ASN1-object-s-types-before-attempting-to-access-th.patch openssl-3.5.4/debian/patches/Verify-ASN1-object-s-types-before-attempting-to-access-th.patch --- openssl-3.5.4/debian/patches/Verify-ASN1-object-s-types-before-attempting-to-access-th.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/Verify-ASN1-object-s-types-before-attempting-to-access-th.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,36 @@ +From: Bob Beck +Date: Wed, 7 Jan 2026 11:29:48 -0700 +Subject: Verify ASN1 object's types before attempting to access them as a + particular type + +Issue was reported in ossl_ess_get_signing_cert but is also present in +ossl_ess_get_signing_cert_v2. + +Fixes: https://github.com/openssl/srt/issues/61 +Fixes CVE-2025-69420 +--- + crypto/ts/ts_rsp_verify.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c +index 0d9fa01e4337..60bc918d2d92 100644 +--- a/crypto/ts/ts_rsp_verify.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/ossl_quic_get_cipher_by_char-Add-a-NULL-guard-before-dere.patch openssl-3.5.4/debian/patches/ossl_quic_get_cipher_by_char-Add-a-NULL-guard-before-dere.patch --- openssl-3.5.4/debian/patches/ossl_quic_get_cipher_by_char-Add-a-NULL-guard-before-dere.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/ossl_quic_get_cipher_by_char-Add-a-NULL-guard-before-dere.patch 2026-01-24 15:48:58.000000000 +0000 @@ -0,0 +1,23 @@ +From: Daniel Kubec +Date: Fri, 9 Jan 2026 14:33:24 +0100 +Subject: ossl_quic_get_cipher_by_char(): Add a NULL guard before + dereferencing SSL_CIPHER + +Fixes CVE-2025-15468 +--- + ssl/quic/quic_impl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c +index cec05d5bd37b..0c15ef05236c 100644 +--- a/ssl/quic/quic_impl.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/pkcs12-Validate-salt-and-keylength-in-PBMAC1.patch openssl-3.5.4/debian/patches/pkcs12-Validate-salt-and-keylength-in-PBMAC1.patch --- openssl-3.5.4/debian/patches/pkcs12-Validate-salt-and-keylength-in-PBMAC1.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/patches/pkcs12-Validate-salt-and-keylength-in-PBMAC1.patch 2026-01-24 15:48:57.000000000 +0000 @@ -0,0 +1,53 @@ +From: Tomas Mraz +Date: Thu, 8 Jan 2026 14:31:19 +0100 +Subject: pkcs12: Validate salt and keylength in PBMAC1 + +The keylength value must be present and we accept +EVP_MAX_MD_SIZE at maximum. + +The salt ASN.1 type must be OCTET STRING. + +Fixes CVE-2025-11187 + +Reported by Stanislav Fort (Aisle Research) and Petr Simecek (Aisle Research). +Reported independently also by Hamza (Metadust). +--- + crypto/pkcs12/p12_mutl.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c +index b43c82f0ed29..f6c7be483de8 100644 +--- a/crypto/pkcs12/p12_mutl.c ++++ b/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 -Nru openssl-3.5.4/debian/patches/series openssl-3.5.4/debian/patches/series --- openssl-3.5.4/debian/patches/series 2025-11-01 11:22:59.000000000 +0000 +++ openssl-3.5.4/debian/patches/series 2026-01-24 15:48:58.000000000 +0000 @@ -5,3 +5,18 @@ c_rehash-compat.patch Configure-allow-to-enable-ktls-if-target-does-not-start-w.patch conf-Serialize-allocation-free-of-ssl_names.patch +pkcs12-Validate-salt-and-keylength-in-PBMAC1.patch +Add-testcase-for-PKCS12-with-invalid-PBMAC1-key-length.patch +Correct-handling-of-AEAD-encrypted-CMS-with-inadmissibly-.patch +Some-comments-to-clarify-functions-usage.patch +Test-for-handling-of-AEAD-encrypted-CMS-with-inadmissibly.patch +ossl_quic_get_cipher_by_char-Add-a-NULL-guard-before-dere.patch +Report-truncation-in-oneshot-openssl-dgst-sign.patch +Check-the-received-uncompressed-certificate-length-to-pre.patch +Fix-heap-buffer-overflow-in-BIO_f_linebuffer.patch +Fix-OCB-AES-NI-HW-stream-path-unauthenticated-unencrypted.patch +Harden-ASN1_mbstring_ncopy.patch +Check-return-code-of-UTF8_putc.patch +Verify-ASN1-object-s-types-before-attempting-to-access-th.patch +Add-NULL-check-to-PKCS12_item_decrypt_d2i_ex.patch +Ensure-ASN1-types-are-checked-before-use.patch diff -Nru openssl-3.5.4/debian/rules openssl-3.5.4/debian/rules --- openssl-3.5.4/debian/rules 2025-11-01 11:22:59.000000000 +0000 +++ openssl-3.5.4/debian/rules 2026-01-24 15:48:55.000000000 +0000 @@ -53,6 +53,7 @@ dh $@ --without autoreconf override_dh_auto_configure: + tar xf debian/CVE-2025-11187-binary.tar test -z "$(OPTS)" || for opt in $(OPTS); \ do \ set -xe; \ diff -Nru openssl-3.5.4/debian/source/include-binaries openssl-3.5.4/debian/source/include-binaries --- openssl-3.5.4/debian/source/include-binaries 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.4/debian/source/include-binaries 2026-01-24 15:48:55.000000000 +0000 @@ -0,0 +1 @@ +debian/CVE-2025-11187-binary.tar