Version in base suite: 3.5.5-1~deb13u1 Base version: openssl_3.5.5-1~deb13u1 Target version: openssl_3.5.5-1~deb13u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/o/openssl/openssl_3.5.5-1~deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/o/openssl/openssl_3.5.5-1~deb13u2.dsc /srv/release.debian.org/tmp/MjFRCxvtut/openssl-3.5.5/debian/binary.tar |binary openssl-3.5.5/debian/changelog | 15 openssl-3.5.5/debian/patches/Add-test-for-CMS-decryption-with-RSA-keys.patch | 44 openssl-3.5.5/debian/patches/Added-test-for-CVE-2026-28388.patch | 124 ++ openssl-3.5.5/debian/patches/Avoid-possible-buffer-overflow-in-buf2hex-conversion.patch | 40 openssl-3.5.5/debian/patches/Fix-NULL-Dereference-When-Delta-CRL-Lacks-CRL-Number-Exte.patch | 23 openssl-3.5.5/debian/patches/Fix-NULL-deref-in-ec-dh_cms_set_shared_info.patch | 100 ++ openssl-3.5.5/debian/patches/Fix-NULL-deref-in-rsa_cms_decrypt.patch | 82 + openssl-3.5.5/debian/patches/Fix-group-tuple-handling-in-DEFAULT-expansion.patch | 469 ++++++++++ openssl-3.5.5/debian/patches/Test-for-DH-ECDH-CMS-KARI-processing-NULL-pointer-derefer.patch | 157 +++ openssl-3.5.5/debian/patches/dane_match_cert-should-X509_free-on-mcert-instead.patch | 32 openssl-3.5.5/debian/patches/rsa_kem-test-RSA_public_encrypt-result-in-RSASVE.patch | 108 ++ openssl-3.5.5/debian/patches/rsa_kem-validate-RSA_public_encrypt-result-in-RSASVE.patch | 56 + openssl-3.5.5/debian/patches/series | 11 openssl-3.5.5/debian/rules | 1 openssl-3.5.5/debian/source/include-binaries | 1 16 files changed, 1263 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp8rgdunox/openssl_3.5.5-1~deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp8rgdunox/openssl_3.5.5-1~deb13u2.dsc: no acceptable signature found Binary files /srv/release.debian.org/tmp/eMxcJe8YnX/openssl-3.5.5/debian/binary.tar and /srv/release.debian.org/tmp/MjFRCxvtut/openssl-3.5.5/debian/binary.tar differ diff -Nru openssl-3.5.5/debian/changelog openssl-3.5.5/debian/changelog --- openssl-3.5.5/debian/changelog 2026-02-22 12:03:11.000000000 +0000 +++ openssl-3.5.5/debian/changelog 2026-04-03 10:05:32.000000000 +0000 @@ -1,3 +1,18 @@ +openssl (3.5.5-1~deb13u2) trixie-security; urgency=medium + + * CVE-2026-2673 ("OpenSSL TLS 1.3 server may choose unexpected key agreement + group") (Closes: #1130650). + * CVE-2026-28387 ("Potential use-after-free in DANE client code") + * CVE-2026-28389 ("Possible NULL dereference when processing CMS + KeyAgreeRecipientInfo") + * CVE-2026-28390 ("Possible NULL dereference when processing CMS + KeyTransportRecipient Info") + * CVE-2026-31789 ("Heap buffer overflow in hexadecimal conversion") + * CVE-2026-31790 ("Incorrect failure handling in RSA KEM RSASVE + encapsulation") + + -- Sebastian Andrzej Siewior Fri, 03 Apr 2026 12:05:32 +0200 + openssl (3.5.5-1~deb13u1) trixie; urgency=medium * Import 3.5.5 diff -Nru openssl-3.5.5/debian/patches/Add-test-for-CMS-decryption-with-RSA-keys.patch openssl-3.5.5/debian/patches/Add-test-for-CMS-decryption-with-RSA-keys.patch --- openssl-3.5.5/debian/patches/Add-test-for-CMS-decryption-with-RSA-keys.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Add-test-for-CMS-decryption-with-RSA-keys.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,44 @@ +From: Neil Horman +Date: Sun, 29 Mar 2026 10:47:03 -0400 +Subject: Add test for CMS decryption with RSA keys + +Ensure we don't encounter a segfault when decrypting CMS messages with +malformed EnvelopedData when using RSA-OAEP. + +Co-authored-by: Tomas Mraz +--- + test/recipes/80-test_cms.t | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t +index 90aeb2959707..bbf3925ba98b 100644 +--- a/test/recipes/80-test_cms.t ++++ b/test/recipes/80-test_cms.t +@@ -53,7 +53,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) + + $no_rc2 = 1 if disabled("legacy"); + +-plan tests => 33; ++plan tests => 34; + + ok(run(test(["pkcs7_test"])), "test pkcs7"); + +@@ -1391,6 +1391,18 @@ with({ exit_checker => sub { return shift == 4; } }, + } + }); + ++$smcont_malformed = srctop_file("test", "recipes", "80-test_cms_data", "rsa-malformed.der"); ++my $smrsacert = catfile($smdir, "smrsa3.pem"); ++my $smrsakey = catfile($smdir, "smrsa3-key.pem"); ++ ++# Test case for CVE-2026-28390 ++with({ exit_checker => sub { return shift == 4; } }, ++ sub { ++ ok(run(app(["openssl", "cms", @prov, "-decrypt", "-in", $smcont_malformed, "-inform", ++ "DER", "-recip", $smrsacert, "-inkey", $smrsakey, "-out", "{output}.cms"])), ++ "Must not crash on malformed cms inputs with RSA key"); ++ }); ++ + # Test encrypt to three recipients, and decrypt using key-only; + # i.e. do not follow the recommended practice of providing the + # recipient cert in the decrypt op. diff -Nru openssl-3.5.5/debian/patches/Added-test-for-CVE-2026-28388.patch openssl-3.5.5/debian/patches/Added-test-for-CVE-2026-28388.patch --- openssl-3.5.5/debian/patches/Added-test-for-CVE-2026-28388.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Added-test-for-CVE-2026-28388.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,124 @@ +From: Daniel Kubec +Date: Tue, 17 Mar 2026 11:14:56 +0100 +Subject: Added test for CVE-2026-28388 + +--- + test/certs/cve-2026-28388-ca.pem | 19 +++++++++++++++++++ + test/certs/cve-2026-28388-crls.pem | 22 ++++++++++++++++++++++ + test/certs/cve-2026-28388-leaf.pem | 19 +++++++++++++++++++ + test/recipes/25-test_verify.t | 14 +++++++++++++- + 4 files changed, 73 insertions(+), 1 deletion(-) + create mode 100644 test/certs/cve-2026-28388-ca.pem + create mode 100644 test/certs/cve-2026-28388-crls.pem + create mode 100644 test/certs/cve-2026-28388-leaf.pem + +diff --git a/test/certs/cve-2026-28388-ca.pem b/test/certs/cve-2026-28388-ca.pem +new file mode 100644 +index 000000000000..9e36d11c4b4b +--- /dev/null ++++ b/test/certs/cve-2026-28388-ca.pem +@@ -0,0 +1,19 @@ ++-----BEGIN CERTIFICATE----- ++MIIDFTCCAf2gAwIBAgIUOl5NN/jfsuLU9JSGLZAfRzviF+owDQYJKoZIhvcNAQEL ++BQAwEjEQMA4GA1UEAwwHVGVzdCBDQTAeFw0yNjAzMTcwODE5NDdaFw0yNzAzMTcw ++ODE5NDdaMBIxEDAOBgNVBAMMB1Rlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB ++DwAwggEKAoIBAQD0m4KETjF0c25spNWUiNChWP0GalDL0gVDFbtAoMVF/lvlZEcp ++hcg62ifHJRPntWyVAmH70DAI87cWzl/73QYGaOcMVcH5yEM31BoK83FvhsS3RTPO ++FSrNCHaZrrWuga+QkBmMcR6qX7GF5eb6ASMBsLuuDqbkCRbTJ2ryhYeWF+VFemBF ++pSHpcinSSLvswTVbZiCqmoy0WkK8eiyfLMZA17PgVLQpyPZ3rp5YG5vEZZoqFc/f ++1bCHjwQ7fNdLCEMqPvE/I0mg2skRClb1L1Vieud/jmjL8nVd9I12j1eUOcSKtCkW ++nj4BFa7TRz13sN3LZOFvV774ZaXRJ1GxoAlnAgMBAAGjYzBhMB0GA1UdDgQWBBSt ++UxfaVbV9QMmfwMoImdgi4MZHzTAfBgNVHSMEGDAWgBStUxfaVbV9QMmfwMoImdgi ++4MZHzTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B ++AQsFAAOCAQEA84w49n0pPJlqiD1/mn3pUZ66lBP0fFZiCuV/3YatBZcW+xcboW0Q ++xImYztjZo0i+sQLZOalI4GoBqD77Dv4Qas0QoJZIp0wM8DjE3YcudCr4cpUhT1XC ++ruHVHQA9bY5rW0GsfUBW6/3RbRpiK4SaFG3sUBbXPo0dC2EaLDjpLM7o2UljRrWu ++d/vg6ieKuAicexLxqQLdM4SxjyvBpCwHg/dnMxawSj4Xhks1BHJ0hTLKJGDgfVHh ++ex8+878u6Gf7fAOZa5idWUgTvdt5WHSW5x+Tm/P6LGG3HkM425ZU6BLTCHONoBud ++cOlfWTTuIyweX5TRL5HY3SuO1cpMBpjiAA== ++-----END CERTIFICATE----- +diff --git a/test/certs/cve-2026-28388-crls.pem b/test/certs/cve-2026-28388-crls.pem +new file mode 100644 +index 000000000000..46cbd7876dcd +--- /dev/null ++++ b/test/certs/cve-2026-28388-crls.pem +@@ -0,0 +1,22 @@ ++-----BEGIN X509 CRL----- ++MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB1Rlc3QgQ0EXDTI2 ++MDMxNzA4MTk0N1oXDTI2MDQxNjA4MTk0N1qgLzAtMB8GA1UdIwQYMBaAFK1TF9pV ++tX1AyZ/AygiZ2CLgxkfNMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBl ++3vVknchCNA/oW0ovtnrE+xQs8yAk3uElooQlw88moTcts2YAcKWl49lnNWZk/RbF ++Zs8m+MUuNb2W861siuvY3EwnSKVaJB2tKPfCRBP4xt+Q0g/Tn5CWxzpzHjQfLT6l ++pvWOwaO7aE6bthX7MQ9XBpnHSPxsbul+MhV5PER11BYZGVh5MH0XxfMI0jDHFh2M ++klTamgaao3TkVOI3OQPgzUx/q0Lz/YoCIH0pYGGP6KTGUX2x7UfD1tcIOcUp6tvO ++6hG3utMgJOpZJl9yMzhG+ZURjbz4MSbBM0FVIaWnBn2VzY1jHGky0nK83IZhiddf ++OohWoSH8tqwrNFZkblAH ++-----END X509 CRL----- ++-----BEGIN X509 CRL----- ++MIIBjjB4AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB1Rlc3QgQ0EXDTI2 ++MDEwODEyMDAwMFoXDTI2MDIwODEyMDAwMFqgMjAwMB8GA1UdIwQYMBaAFK1TF9pV ++tX1AyZ/AygiZ2CLgxkfNMA0GA1UdGwEB/wQDAgEBMA0GCSqGSIb3DQEBCwUAA4IB ++AQCyYxa5iVUFxBpdXgBGSMqkuxJqQzVni8nXK0DiXHfgbTud+HD5Qp/6PX2EQuwK ++SrT0yeNJBU1gxxMMsbdA0yVTPa7N2Ny39mjq/27yBXduiljo3Gs4NLEW9grJRnep ++WOD1cQe3Fea5HlEfUoQJF1WVekF6CnOSqESaDvTAzqpZd7pxU8cuduiRJPin93ki ++1nicQAU/G4Td190+JEAWD3/dJTg2LF6LKrmHiv2ZUTuNsVBfcbhFSoC6FpnjFUAI ++kF8EgJpuBEfqV6erIuT1GD+5p1QGNqdcNl7LO9erJaUFnssJBJtj84iXd7RZARNs ++njcibOSKC9YWgNmZUy0QV5D8 ++-----END X509 CRL----- +diff --git a/test/certs/cve-2026-28388-leaf.pem b/test/certs/cve-2026-28388-leaf.pem +new file mode 100644 +index 000000000000..02b22997cdd8 +--- /dev/null ++++ b/test/certs/cve-2026-28388-leaf.pem +@@ -0,0 +1,19 @@ ++-----BEGIN CERTIFICATE----- ++MIIDHTCCAgWgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdUZXN0 ++IENBMB4XDTI2MDMxNzA4MTk0N1oXDTI3MDMxNzA4MTk0N1owFDESMBAGA1UEAwwJ ++VGVzdCBMZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqx7jpC6+ ++nRZ4ol6sShkpv04hGYtt7y+Ns4oIfdQTqo57DItFab8D8cH04zR8NND42MMnsPPn ++Ovh9gv2l1mj9ZfwgXI5PvaKc6CoXvXb0ttekdDUS1iw9g04BxIXTDANxsdSXrCDd ++Npyr1Pxdo3N2fiH6qN9/Lsh7yg0vJW/aJzdvhLcCTFcr89qmCsh17XfcTR0wZJXP ++QdlRib9EK8aa6aKOYmm44SBbuXXyWojhheUaqVuzDj6A0L9opmh/DVXa9bdIN/FX ++CKJB+d60Qxy5pKwpzDDxbCdG2vA1U2cPz8yAgelFG5AmXSHF7Id4G6GTCAY6PbTO ++Jy2Z4I6NY+mj5wIDAQABo3wwejAdBgNVHQ4EFgQUlf2YZ93MvS4kZm7fshosgp+J ++ImkwHwYDVR0jBBgwFoAUrVMX2lW1fUDJn8DKCJnYIuDGR80wCQYDVR0TBAIwADAt ++BgNVHS4EJjAkMCKgIKAehhxodHRwOi8vZXhhbXBsZS5jb20vZGVsdGEucGVtMA0G ++CSqGSIb3DQEBCwUAA4IBAQDoNAQGLS0Juf3i2fhuVQyWIFvNIMElLexeLnnd/y80 ++13nsP68ZGT2D3DoHQSz3SL7sNjLBc2CiUVftdaRQ4dNCz8sBY5BRTS5XEGbbTAFZ ++bQUReykuuTy83CGw/JYN6YT/OHcf4gEhUnWtRMCmIz3J/NMRVSRnpV2Ezjltm/Q+ ++emFS/QclRhkP6Vu+lwM/nV6uAN8T7Ba68Hym2MN0clozrpoKeqFouB7D0i+iCZMw ++zbac5as0hn7Fm+HGTbfTs2/fqUslvE6PmagepceP37pTSSVmYRmdpOD2cyCb30A+ ++nJFGQg7PcacGSL1re65W35XzdU8Si8OYD+PxjDaRbPcP ++-----END CERTIFICATE----- +diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t +index 673c3d5f1772..fcb343b9ee3a 100644 +--- a/test/recipes/25-test_verify.t ++++ b/test/recipes/25-test_verify.t +@@ -30,7 +30,7 @@ sub verify { + run(app([@args])); + } + +-plan tests => 203; ++plan tests => 204; + + # Canonical success + ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), +@@ -594,6 +594,18 @@ ok(!verify("ee-cert-policies-bad", "", ["root-cert"], ["ca-pol-cert"], + "-explicit_policy"), + "Bad certificate policy"); + ++# CVE-2026-28388 ++my $cve_28388_stderr = "cve-2026-28388.err"; ++run(app(["openssl", "verify", ++ "-attime", "1739527200", ++ "-CAfile", srctop_file(@certspath, "cve-2026-28388-ca.pem"), ++ "-crl_check", "-use_deltas", ++ "-CRLfile", srctop_file(@certspath, "cve-2026-28388-crls.pem"), ++ srctop_file(@certspath, "cve-2026-28388-leaf.pem")], ++ stderr => $cve_28388_stderr)); ++ok(grep(/CRL is not yet valid/, do { open my $fh, '<', $cve_28388_stderr; <$fh> }), ++ "CVE-2026-28388"); ++ + # CAstore option + my $rootcertname = "root-cert"; + my $rootcert = srctop_file(@certspath, "${rootcertname}.pem"); diff -Nru openssl-3.5.5/debian/patches/Avoid-possible-buffer-overflow-in-buf2hex-conversion.patch openssl-3.5.5/debian/patches/Avoid-possible-buffer-overflow-in-buf2hex-conversion.patch --- openssl-3.5.5/debian/patches/Avoid-possible-buffer-overflow-in-buf2hex-conversion.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Avoid-possible-buffer-overflow-in-buf2hex-conversion.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,40 @@ +From: Igor Ustinov +Date: Thu, 5 Mar 2026 15:47:34 +0100 +Subject: Avoid possible buffer overflow in buf2hex conversion + +Fixes CVE-2026-31789 +--- + crypto/o_str.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/crypto/o_str.c b/crypto/o_str.c +index 35540630be25..9b9e7751fdd9 100644 +--- a/crypto/o_str.c ++++ b/crypto/o_str.c +@@ -296,6 +296,11 @@ static int buf2hexstr_sep(char *str, size_t str_n, size_t *strlength, + int has_sep = (sep != CH_ZERO); + size_t i, len = has_sep ? buflen * 3 : 1 + buflen * 2; + ++ if (buflen > (has_sep ? SIZE_MAX / 3 : (SIZE_MAX - 1) / 2)) { ++ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES); ++ return 0; ++ } ++ + if (len == 0) + ++len; + if (strlength != NULL) +@@ -339,7 +344,13 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep) + if (buflen == 0) + return OPENSSL_zalloc(1); + +- tmp_n = (sep != CH_ZERO) ? buflen * 3 : 1 + buflen * 2; ++ if ((sep != CH_ZERO && (size_t)buflen > SIZE_MAX / 3) ++ || (sep == CH_ZERO && (size_t)buflen > (SIZE_MAX - 1) / 2)) { ++ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES); ++ return NULL; ++ } ++ ++ tmp_n = (sep != CH_ZERO) ? (size_t)buflen * 3 : 1 + (size_t)buflen * 2; + if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) + return NULL; + diff -Nru openssl-3.5.5/debian/patches/Fix-NULL-Dereference-When-Delta-CRL-Lacks-CRL-Number-Exte.patch openssl-3.5.5/debian/patches/Fix-NULL-Dereference-When-Delta-CRL-Lacks-CRL-Number-Exte.patch --- openssl-3.5.5/debian/patches/Fix-NULL-Dereference-When-Delta-CRL-Lacks-CRL-Number-Exte.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Fix-NULL-Dereference-When-Delta-CRL-Lacks-CRL-Number-Exte.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,23 @@ +From: Daniel Kubec +Date: Tue, 17 Mar 2026 11:11:22 +0100 +Subject: Fix NULL Dereference When Delta CRL Lacks CRL Number Extension + +Fixes CVE-2026-28388 +Fixes https://github.com/openssl/srt/issues/77 +--- + crypto/x509/x509_vfy.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c +index ca3ffc420473..e71d71e9caa6 100644 +--- a/crypto/x509/x509_vfy.c ++++ b/crypto/x509/x509_vfy.c +@@ -1307,6 +1307,8 @@ static int check_delta_base(X509_CRL *delta, X509_CRL *base) + if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0) + return 0; + /* Delta CRL number must exceed full CRL number */ ++ if (delta->crl_number == NULL) ++ return 0; + return ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0; + } + diff -Nru openssl-3.5.5/debian/patches/Fix-NULL-deref-in-ec-dh_cms_set_shared_info.patch openssl-3.5.5/debian/patches/Fix-NULL-deref-in-ec-dh_cms_set_shared_info.patch --- openssl-3.5.5/debian/patches/Fix-NULL-deref-in-ec-dh_cms_set_shared_info.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Fix-NULL-deref-in-ec-dh_cms_set_shared_info.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,100 @@ +From: Neil Horman +Date: Mon, 16 Mar 2026 13:49:07 -0400 +Subject: Fix NULL deref in [ec]dh_cms_set_shared_info + +Multiple independent reports indicated a SIGSEGV was possible in CMS +processing when a crafted CMS EnvelopedData message using A Key +Agreement Recipient Info field. If the +KeyEncryptionAlgorithmIdentifier omits the optional parameter field, the +referenced functions above will attempt to dereference the +alg->parameter data prior to checking if the parameter field is NULL. + +Confirmed to resolve the issues using the reproducers provided in the +security reports. + +Co-authored-by: Tomas Mraz + +Fixes CVE-2026-28389 +--- + crypto/cms/cms_dh.c | 13 +++++++++---- + crypto/cms/cms_ec.c | 14 ++++++++++---- + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c +index ab3453d1c7c1..424729523697 100644 +--- a/crypto/cms/cms_dh.c ++++ b/crypto/cms/cms_dh.c +@@ -89,16 +89,21 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) + int keylen, plen; + EVP_CIPHER *kekcipher = NULL; + EVP_CIPHER_CTX *kekctx; ++ const ASN1_OBJECT *aoid; ++ const void *parameter = NULL; ++ int ptype = 0; + char name[OSSL_MAX_NAME_SIZE]; + + if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) + goto err; + ++ X509_ALGOR_get0(&aoid, &ptype, ¶meter, alg); ++ + /* + * For DH we only have one OID permissible. If ever any more get defined + * we will need something cleverer. + */ +- if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) { ++ if (OBJ_obj2nid(aoid) != NID_id_smime_alg_ESDH) { + ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR); + goto err; + } +@@ -107,11 +112,11 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) + || EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0) + goto err; + +- if (alg->parameter->type != V_ASN1_SEQUENCE) ++ if (ptype != V_ASN1_SEQUENCE) + goto err; + +- p = alg->parameter->value.sequence->data; +- plen = alg->parameter->value.sequence->length; ++ p = ASN1_STRING_get0_data(parameter); ++ plen = ASN1_STRING_length(parameter); + kekalg = d2i_X509_ALGOR(NULL, &p, plen); + if (kekalg == NULL) + goto err; +diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c +index ff8adad61668..e60d0a786ec5 100644 +--- a/crypto/cms/cms_ec.c ++++ b/crypto/cms/cms_ec.c +@@ -166,21 +166,27 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) + int plen, keylen; + EVP_CIPHER *kekcipher = NULL; + EVP_CIPHER_CTX *kekctx; ++ const ASN1_OBJECT *aoid = NULL; ++ int ptype = 0; ++ const void *parameter = NULL; ++ + char name[OSSL_MAX_NAME_SIZE]; + + if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) + return 0; + +- if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) { ++ X509_ALGOR_get0(&aoid, &ptype, ¶meter, alg); ++ ++ if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(aoid))) { + ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR); + return 0; + } + +- if (alg->parameter->type != V_ASN1_SEQUENCE) ++ if (ptype != V_ASN1_SEQUENCE) + return 0; + +- p = alg->parameter->value.sequence->data; +- plen = alg->parameter->value.sequence->length; ++ p = ASN1_STRING_get0_data(parameter); ++ plen = ASN1_STRING_length(parameter); + kekalg = d2i_X509_ALGOR(NULL, &p, plen); + if (kekalg == NULL) + goto err; diff -Nru openssl-3.5.5/debian/patches/Fix-NULL-deref-in-rsa_cms_decrypt.patch openssl-3.5.5/debian/patches/Fix-NULL-deref-in-rsa_cms_decrypt.patch --- openssl-3.5.5/debian/patches/Fix-NULL-deref-in-rsa_cms_decrypt.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Fix-NULL-deref-in-rsa_cms_decrypt.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,82 @@ +From: Neil Horman +Date: Wed, 1 Apr 2026 10:56:44 +0200 +Subject: Fix NULL deref in rsa_cms_decrypt + +Very simmilar to CVE-2026-28389, ensure that if we are missing +parameters in RSA-OAEP SourceFunc in CMS KeyTransportRecipientInfo, +we don't segfault when decrypting. + +Co-authored-by: Tomas Mraz + +Fixes CVE-2026-28390 +--- + crypto/cms/cms_rsa.c | 31 +++++++++++++++++++------------ + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/crypto/cms/cms_rsa.c b/crypto/cms/cms_rsa.c +index 6b65842cc14e..34c739a9825a 100644 +--- a/crypto/cms/cms_rsa.c ++++ b/crypto/cms/cms_rsa.c +@@ -42,10 +42,13 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri) + X509_ALGOR *cmsalg; + int nid; + int rv = -1; +- unsigned char *label = NULL; ++ const unsigned char *label = NULL; + int labellen = 0; + const EVP_MD *mgf1md = NULL, *md = NULL; + RSA_OAEP_PARAMS *oaep; ++ const ASN1_OBJECT *aoid; ++ const void *parameter = NULL; ++ int ptype = 0; + + pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (pkctx == NULL) +@@ -75,21 +78,19 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri) + goto err; + + if (oaep->pSourceFunc != NULL) { +- X509_ALGOR *plab = oaep->pSourceFunc; ++ X509_ALGOR_get0(&aoid, &ptype, ¶meter, oaep->pSourceFunc); + +- if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) { ++ if (OBJ_obj2nid(aoid) != NID_pSpecified) { + ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_LABEL_SOURCE); + goto err; + } +- if (plab->parameter->type != V_ASN1_OCTET_STRING) { ++ if (ptype != V_ASN1_OCTET_STRING) { + ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_LABEL); + goto err; + } + +- label = plab->parameter->value.octet_string->data; +- /* Stop label being freed when OAEP parameters are freed */ +- plab->parameter->value.octet_string->data = NULL; +- labellen = plab->parameter->value.octet_string->length; ++ label = ASN1_STRING_get0_data(parameter); ++ labellen = ASN1_STRING_length(parameter); + } + + if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) +@@ -98,10 +99,16 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri) + goto err; + if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) + goto err; +- if (label != NULL +- && EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) { +- OPENSSL_free(label); +- goto err; ++ if (label != NULL) { ++ unsigned char *dup_label = OPENSSL_memdup(label, labellen); ++ ++ if (dup_label == NULL) ++ goto err; ++ ++ if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, dup_label, labellen) <= 0) { ++ OPENSSL_free(dup_label); ++ goto err; ++ } + } + /* Carry on */ + rv = 1; diff -Nru openssl-3.5.5/debian/patches/Fix-group-tuple-handling-in-DEFAULT-expansion.patch openssl-3.5.5/debian/patches/Fix-group-tuple-handling-in-DEFAULT-expansion.patch --- openssl-3.5.5/debian/patches/Fix-group-tuple-handling-in-DEFAULT-expansion.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Fix-group-tuple-handling-in-DEFAULT-expansion.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,469 @@ +From: Viktor Dukhovni +Date: Tue, 17 Feb 2026 18:37:06 +1100 +Subject: Fix group tuple handling in DEFAULT expansion + +Also fine-tune docs and add tests. + +Fixes: #30109 +Fixes: CVE-2026-2673 + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +MergeDate: Fri Mar 13 12:44:06 2026 +(Merged from https://github.com/openssl/openssl/pull/30110) +--- + CHANGES.md | 10 ++++ + NEWS.md | 1 + + doc/man3/SSL_CTX_set1_curves.pod | 123 +++++++++++++++++++++++++++------------ + ssl/t1_lib.c | 92 +++++++++++++++++------------ + test/tls13groupselection_test.c | 37 ++++++++++-- + 5 files changed, 183 insertions(+), 80 deletions(-) + +diff --git a/CHANGES.md b/CHANGES.md +index 1a65b72b2965..da430a6c6efb 100644 +--- a/CHANGES.md ++++ b/CHANGES.md +@@ -28,6 +28,15 @@ OpenSSL Releases + OpenSSL 3.5 + ----------- + ++ * Fixed loss of key agreement group tuple structure when the `DEFAULT` keyword ++ is used in the server-side configuration of the key-agreement group list. ++ This could result in accepting a less preferred than intended client ++ keyshare. ++ ++ ([CVE-2026-2673]) ++ ++ *Viktor Dukhovni* ++ + ### Changes between 3.5.4 and 3.5.5 [27 Jan 2026] + + * Fixed Improper validation of PBMAC1 parameters in PKCS#12 MAC verification. +@@ -21607,6 +21616,7 @@ ndif + + + ++[CVE-2026-2673]: https://www.openssl.org/news/vulnerabilities.html#CVE-2026-2673 + [CVE-2026-22796]: https://www.openssl.org/news/vulnerabilities.html#CVE-2026-22796 + [CVE-2026-22795]: https://www.openssl.org/news/vulnerabilities.html#CVE-2026-22795 + [CVE-2025-69421]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-69421 +diff --git a/NEWS.md b/NEWS.md +index f4ec14718d71..85e298ac8cb0 100644 +--- a/NEWS.md ++++ b/NEWS.md +@@ -1988,6 +1988,7 @@ OpenSSL 0.9.x + * Support for various new platforms + + ++[CVE-2026-2673]: https://www.openssl.org/news/vulnerabilities.html#CVE-2026-2673 + [CVE-2026-22796]: https://www.openssl.org/news/vulnerabilities.html#CVE-2026-22796 + [CVE-2026-22795]: https://www.openssl.org/news/vulnerabilities.html#CVE-2026-22795 + [CVE-2025-69421]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-69421 +diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod +index 017eefd3176a..472d3858315a 100755 +--- a/doc/man3/SSL_CTX_set1_curves.pod ++++ b/doc/man3/SSL_CTX_set1_curves.pod +@@ -40,13 +40,13 @@ SSL_get1_curves, SSL_get_shared_curve, SSL_CTX_get0_implemented_groups + + For all of the functions below that set the supported groups there must be at + least one group in the list. A number of these functions identify groups via a +-unique integer NID value. However, support for some groups may be added by +-external providers. In this case there will be no NID assigned for the group. ++unique integer B value. However, support for some groups may be added by ++external providers. In this case there will be no B assigned for the group. + When setting such groups applications should use the "list" form of these + functions (i.e. SSL_CTX_set1_groups_list() and SSL_set1_groups_list()). + + SSL_CTX_set1_groups() sets the supported groups for B to B +-groups in the array B. The array consist of all NIDs of supported groups. ++groups in the array B. The array consist of all B of supported groups. + The supported groups for B include: + B, + B, +@@ -73,20 +73,27 @@ B is set, the order of the elements in the + array determines the selected group. Otherwise, the order is ignored and the + client's order determines the selection. + +-For a TLS 1.3 server, the groups determine the selected group, but +-selection is more complex. A TLS 1.3 client sends both a group list as well as a +-predicted subset of groups. Choosing a group outside the predicted subset incurs +-an extra roundtrip. However, in some situations, the most preferred group may +-not be predicted. OpenSSL considers all supported groups in I to be comparable +-in security and prioritizes avoiding roundtrips above either client or server +-preference order. If an application uses an external provider to extend OpenSSL +-with, e.g., a post-quantum algorithm, this behavior may allow a network attacker +-to downgrade connections to a weaker algorithm. It is therefore recommended +-to use SSL_CTX_set1_groups_list() with the ability to specify group tuples. ++For a TLS 1.3 server, the groups determine the selected group, but selection is ++more complex. ++A TLS 1.3 client sends both a group list and predicted keyshares for a subset ++of groups. ++A server choosing a group outside the client's predicted subset incurs an extra ++roundtrip. ++However, in some situations, the most preferred group may not be predicted. ++ ++When groups are specified via SSL_CTX_set1_groups() as a list of B ++values, OpenSSL considers all supported groups in I to be comparable in ++security and prioritises avoiding roundtrips above either client or server ++preference order. ++If an application uses an external provider to extend OpenSSL with, e.g., a ++post-quantum algorithm, this behavior may allow a network attacker to downgrade ++connections to a weaker algorithm. ++It is therefore recommended to use SSL_CTX_set1_groups_list() instead, making ++it possible to specify group tuples as described below. + + SSL_CTX_set1_groups_list() sets the supported groups for B to + string I. In contrast to SSL_CTX_set1_groups(), the names of the +-groups, rather than their NIDs, are used. ++groups, rather than their B, are used. + + The commands below list the available groups for TLS 1.2 and TLS 1.3, + respectively: +@@ -102,30 +109,72 @@ The preferred group names are those defined by + L. + + The I can be used to define several group tuples of comparable security +-levels, and can specify which key shares should be sent by a client. +-The specified list elements can optionally be ignored, if not implemented ++levels, and can specify which predicted key shares should be sent by a client. ++Group tuples are used by OpenSSL TLS servers to decide whether to request a ++stronger keyshare than those predicted by sending a Hello Retry Request ++(B) even if some of the predicted groups are supported. ++OpenSSL clients ignore tuple boundaries, and pay attenion only to the overall ++order of I elements and which groups are selected as predicted keyshares ++as described below. ++ ++The specified list elements can optionally be ignored if not implemented + (listing unknown groups otherwise results in error). +-It is also possible to specify the built-in default set of groups, and to explicitly +-remove a group from that list. +- +-In its simplest form, the string I is just a colon separated list +-of group names, for example "P-521:P-384:P-256:X25519:ffdhe2048". The first +-group listed will also be used for the B sent by a client in a +-TLSv1.3 B. For servers note the discussion above. The list should +-be in order of preference with the most preferred group first. +- +-Group tuples of comparable security are defined by separating them from each +-other by a tuple separator C. Keyshares to be sent by a client are specified +-by prepending a C<*> to the group name, while any C<*> will be ignored by a +-server. The following string I for example defines three tuples when +-used on the server-side, and triggers the generation of three key shares +-when used on the client-side: P-521:*P-256/*P-384/*X25519:P-384:ffdhe2048. +- +-If a group name is preceded with the C character, it will be ignored if an +-implementation is missing. If a group name is preceded with the C<-> character, it +-will be removed from the list of groups if present (including not sending a +-key share for this group), ignored otherwise. The pseudo group name +-C can be used to select the OpenSSL built-in default list of groups. ++It is also possible to specify the built-in default set of groups, and to ++explicitly remove a group from that list. ++ ++In its simplest legacy form, the string I is just a colon separated list ++of group names, for example "P-521:P-384:P-256:X25519:ffdhe2048". ++The first group listed will in this case be used as the sole predicted ++B sent by a client in a TLSv1.3 B. ++The list should be in order of preference with the most preferred group first. ++ ++A more expressive syntax supports definition of group tuples of comparable ++security by separating them from each other with C characters. ++ ++The predicted keyshares to be sent by clients can be explicitly specified by ++adding a C<*> prefix to the associated group name. ++These C<*> prefixes are ignored by servers. ++ ++If a group name is prefixed with the C character, it will be ignored if an ++implementation is missing. ++Otherwise, listing an unknown group name will cause a failure to parse the ++I. ++Note that whether a group is known or not may depend on the OpenSSL version, ++how OpenSSL was compiled and/or which providers are loaded. ++Make sure you have the correct spelling of the group name and when in doubt ++prefix it with a C to handle configurations in which it might nevertheless ++be unknown. ++ ++If a group name is prefixed with the C<-> character, it will be removed from ++the list of groups specified up to that point. ++It can be added again if specified later. ++Removal of groups that have not been included earlier in the list is silently ++ignored. ++ ++The pseudo group name C can be used to select the OpenSSL built-in ++default list of groups. ++Prepending one or more groups to C using only C<:> separators prepends those ++groups to the built-in default list's first tuple. ++Additional tuples can be prepended by use of the C separator. ++Appending a set of groups to C using only C<:> separators appends those ++groups to the built-in default list's last tuple. ++Additional tuples can be appended by use of the C separator. ++ ++The B list selects B as one of the predicted keyshares. ++In rare cases this can lead to failures or timeouts because the resulting ++larger TLS Client Hello message may no longer fit in a single TCP segment and ++firewall software may erroneously disrupt the TLS handshake. ++If this is an issue or concern, prepending C without a C<*> ++prefix leads to its occurrence in the default list to be ignored as a duplicate, ++and along with that also the keyshare prediction. ++The group will then only be selected by servers that specifically expect it, ++after a Hello Retry Request (HRR). ++Servers that specifically prefer B, are much less likely to be ++found behind problematic firewalls. ++ ++The following string I for example defines three tuples when used on the ++server-side, and triggers the generation of three key shares when used on the ++client-side: P-521:*P-256/*P-384/*X25519:P-384:ffdhe2048. + + For a TLS 1.3 client, all the groups in the string I are added to the + supported groups extension of a C, in the order in which they are listed, +diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c +index cd471a636db1..4e83e40995f3 100644 +--- a/ssl/t1_lib.c ++++ b/ssl/t1_lib.c +@@ -211,7 +211,7 @@ static const uint16_t suiteb_curves[] = { + + /* Group list string of the built-in pseudo group DEFAULT_SUITE_B */ + #define SUITE_B_GROUP_NAME "DEFAULT_SUITE_B" +-#define SUITE_B_GROUP_LIST "secp256r1:secp384r1", ++#define SUITE_B_GROUP_LIST "?secp256r1:?secp384r1", + + struct provider_ctx_data_st { + SSL_CTX *ctx; +@@ -1244,8 +1244,8 @@ typedef struct { + size_t ksidcnt; /* Number of key shares */ + uint16_t *ksid_arr; /* The IDs of the key share groups (flat list) */ + /* Variable to keep state between execution of callback or helper functions */ +- size_t tuple_mode; /* Keeps track whether tuple_cb called from 'the top' or from gid_cb */ +- int ignore_unknown_default; /* Flag such that unknown groups for DEFAULT[_XYZ] are ignored */ ++ int inner; /* Are we expanding a DEFAULT list */ ++ int first; /* First tuple of possibly nested expansion? */ + } gid_cb_st; + + /* Forward declaration of tuple callback function */ +@@ -1320,16 +1320,16 @@ static int gid_cb(const char *elem, int len, void *arg) + for (i = 0; i < OSSL_NELEM(default_group_strings); i++) { + if ((size_t)len == (strlen(default_group_strings[i].list_name)) + && OPENSSL_strncasecmp(default_group_strings[i].list_name, elem, len) == 0) { ++ int saved_first; ++ + /* + * We're asked to insert an entire list of groups from a + * DEFAULT[_XYZ] 'pseudo group' which we do by + * recursively calling this function (indirectly via + * CONF_parse_list and tuple_cb); essentially, we treat a DEFAULT + * group string like a tuple which is appended to the current tuple +- * rather then starting a new tuple. Variable tuple_mode is the flag which +- * controls append tuple vs start new tuple. ++ * rather then starting a new tuple. + */ +- + if (ignore_unknown || remove_group) + return -1; /* removal or ignore not allowed here -> syntax error */ + +@@ -1350,15 +1350,17 @@ static int gid_cb(const char *elem, int len, void *arg) + default_group_strings[i].group_string, + strlen(default_group_strings[i].group_string)); + restored_default_group_string[strlen(default_group_strings[i].group_string) + restored_prefix_index] = '\0'; +- /* We execute the recursive call */ +- garg->ignore_unknown_default = 1; /* We ignore unknown groups for DEFAULT_XYZ */ +- /* we enforce group mode (= append tuple) for DEFAULT_XYZ group lists */ +- garg->tuple_mode = 0; +- /* We use the tuple_cb callback to process the pseudo group tuple */ ++ /* ++ * Append first tuple of result to current tuple, and don't ++ * terminate the last tuple until we return to a top-level ++ * tuple_cb. ++ */ ++ saved_first = garg->first; ++ garg->inner = garg->first = 1; + retval = CONF_parse_list(restored_default_group_string, + TUPLE_DELIMITER_CHARACTER, 1, tuple_cb, garg); +- garg->tuple_mode = 1; /* next call to tuple_cb will again start new tuple */ +- garg->ignore_unknown_default = 0; /* reset to original value */ ++ garg->inner = 0; ++ garg->first = saved_first; + /* We don't need the \0-terminated string anymore */ + OPENSSL_free(restored_default_group_string); + +@@ -1378,9 +1380,6 @@ static int gid_cb(const char *elem, int len, void *arg) + if (len == 0) + return -1; /* Seems we have prefxes without a group name -> syntax error */ + +- if (garg->ignore_unknown_default == 1) /* Always ignore unknown groups for DEFAULT[_XYZ] */ +- ignore_unknown = 1; +- + /* Memory management in case more groups are present compared to initial allocation */ + if (garg->gidcnt == garg->gidmax) { + uint16_t *tmp = OPENSSL_realloc(garg->gid_arr, +@@ -1514,7 +1513,7 @@ static int gid_cb(const char *elem, int len, void *arg) + /* and update the book keeping for the number of groups in current tuple */ + garg->tuplcnt_arr[garg->tplcnt]++; + +- /* We memorize if needed that we want to add a key share for the current group */ ++ /* We want to add a key share for the current group */ + if (add_keyshare) + garg->ksid_arr[garg->ksidcnt++] = gid; + } +@@ -1523,6 +1522,39 @@ static int gid_cb(const char *elem, int len, void *arg) + return retval; + } + ++static int grow_tuples(gid_cb_st *garg) ++{ ++ static size_t max_tplcnt = (~(size_t)0) / sizeof(size_t); ++ ++ /* This uses OPENSSL_realloc_array() in newer releases */ ++ if (garg->tplcnt == garg->tplmax) { ++ size_t newcnt = garg->tplmax + GROUPLIST_INCREMENT; ++ size_t newsz = newcnt * sizeof(size_t); ++ size_t *tmp; ++ ++ if (newsz > max_tplcnt ++ || (tmp = OPENSSL_realloc(garg->tuplcnt_arr, newsz)) == NULL) ++ return 0; ++ ++ garg->tplmax = newcnt; ++ garg->tuplcnt_arr = tmp; ++ } ++ return 1; ++} ++ ++static int close_tuple(gid_cb_st *garg) ++{ ++ size_t gidcnt = garg->tuplcnt_arr[garg->tplcnt]; ++ ++ if (gidcnt == 0) ++ return 1; ++ if (!grow_tuples(garg)) ++ return 0; ++ ++ garg->tuplcnt_arr[++garg->tplcnt] = 0; ++ return 1; ++} ++ + /* Extract and process a tuple of groups */ + static int tuple_cb(const char *tuple, int len, void *arg) + { +@@ -1536,16 +1568,9 @@ static int tuple_cb(const char *tuple, int len, void *arg) + return 0; + } + +- /* Memory management for tuples */ +- if (garg->tplcnt == garg->tplmax) { +- size_t *tmp = OPENSSL_realloc(garg->tuplcnt_arr, +- (garg->tplmax + GROUPLIST_INCREMENT) * sizeof(*garg->tuplcnt_arr)); +- +- if (tmp == NULL) +- return 0; +- garg->tplmax += GROUPLIST_INCREMENT; +- garg->tuplcnt_arr = tmp; +- } ++ if (garg->inner && !garg->first && !close_tuple(garg)) ++ return 0; ++ garg->first = 0; + + /* Convert to \0-terminated string */ + restored_tuple_string = OPENSSL_malloc((len + 1 /* \0 */) * sizeof(char)); +@@ -1560,15 +1585,8 @@ static int tuple_cb(const char *tuple, int len, void *arg) + /* We don't need the \o-terminated string anymore */ + OPENSSL_free(restored_tuple_string); + +- if (garg->tuplcnt_arr[garg->tplcnt] > 0) { /* Some valid groups are present in current tuple... */ +- if (garg->tuple_mode) { +- /* We 'close' the tuple */ +- garg->tplcnt++; +- garg->tuplcnt_arr[garg->tplcnt] = 0; /* Next tuple is initialized to be empty */ +- garg->tuple_mode = 1; /* next call will start a tuple (unless overridden in gid_cb) */ +- } +- } +- ++ if (!garg->inner && !close_tuple(garg)) ++ return 0; + return retval; + } + +@@ -1599,8 +1617,6 @@ int tls1_set_groups_list(SSL_CTX *ctx, + } + + memset(&gcb, 0, sizeof(gcb)); +- gcb.tuple_mode = 1; /* We prepare to collect the first tuple */ +- gcb.ignore_unknown_default = 0; + gcb.gidmax = GROUPLIST_INCREMENT; + gcb.tplmax = GROUPLIST_INCREMENT; + gcb.ksidmax = GROUPLIST_INCREMENT; +diff --git a/test/tls13groupselection_test.c b/test/tls13groupselection_test.c +index 8340a9fd2b3b..bcae5e715944 100644 +--- a/test/tls13groupselection_test.c ++++ b/test/tls13groupselection_test.c +@@ -40,6 +40,12 @@ typedef enum SERVER_RESPONSE { + SH = 2 + } SERVER_RESPONSE; + ++static const char *response_desc[] = { ++ "HRR", ++ "INIT", ++ "SH", ++}; ++ + static char *cert = NULL; + static char *privkey = NULL; + +@@ -307,7 +313,23 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] = { + { "*brainpoolP256r1:X25519", /* test 43 */ + "X25519", + SERVER_PREFERENCE, +- NEGOTIATION_FAILURE, INIT } ++ NEGOTIATION_FAILURE, INIT }, ++ ++ /* DEFAULT retains tuple structure */ ++ { "*X25519:secp256r1", ++ "secp256r1:DEFAULT", /* test 44 */ ++ SERVER_PREFERENCE, ++ "secp256r1", HRR }, ++#ifndef OPENSSL_NO_DH ++ { "*ffdhe2048:secp256r1", ++ "DEFAULT:ffdhe4096", /* test 45 */ ++ CLIENT_PREFERENCE, ++ "secp256r1", HRR }, ++ { "x25519:ffdhe2048:*ffdhe4096", ++ "DEFAULT:ffdhe4096", /* test 46 */ ++ SERVER_PREFERENCE, ++ "x25519", HRR }, ++#endif + }; + + static void server_response_check_cb(int write_p, int version, +@@ -318,10 +340,12 @@ static void server_response_check_cb(int write_p, int version, + enum SERVER_RESPONSE *server_response = (enum SERVER_RESPONSE *)arg; + /* Prepare check for HRR */ + const uint8_t *incoming_random = (uint8_t *)buf + 6; +- const uint8_t magic_HRR_random[32] = { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, ++ const uint8_t magic_HRR_random[32] = { ++ 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, +- 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C }; ++ 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C ++ }; + + /* Did a server hello arrive? */ + if (write_p == 0 && /* Incoming data... */ +@@ -450,13 +474,16 @@ static int test_groupnegotiation(const struct tls13groupselection_test_st *curre + group_name_client = SSL_group_to_name(clientssl, negotiated_group_client); + if (!TEST_int_eq(negotiated_group_client, negotiated_group_server)) + goto end; +- if (!TEST_int_eq((int)current_test_vector->expected_server_response, (int)server_response)) ++ if (!TEST_str_eq(response_desc[current_test_vector->expected_server_response], ++ response_desc[server_response])) + goto end; + if (TEST_str_eq(group_name_client, current_test_vector->expected_group)) + ok = 1; + } else { + TEST_false_or_end(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)); +- if (test_type == TEST_NEGOTIATION_FAILURE && !TEST_int_eq((int)current_test_vector->expected_server_response, (int)server_response)) ++ if (test_type == TEST_NEGOTIATION_FAILURE ++ && !TEST_str_eq(response_desc[current_test_vector->expected_server_response], ++ response_desc[server_response])) + goto end; + ok = 1; + } diff -Nru openssl-3.5.5/debian/patches/Test-for-DH-ECDH-CMS-KARI-processing-NULL-pointer-derefer.patch openssl-3.5.5/debian/patches/Test-for-DH-ECDH-CMS-KARI-processing-NULL-pointer-derefer.patch --- openssl-3.5.5/debian/patches/Test-for-DH-ECDH-CMS-KARI-processing-NULL-pointer-derefer.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/Test-for-DH-ECDH-CMS-KARI-processing-NULL-pointer-derefer.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,157 @@ +From: Neil Horman +Date: Tue, 31 Mar 2026 14:38:03 -0400 +Subject: Test for DH/ECDH CMS KARI processing NULL pointer dereference + +Test to ensure that, if we attempt to decrypt a CMS message with a +missing parameter field of KeyEncryptionAlgorithmIdentifier +we fail, rather than segfault. + +Co-authored-by: Tomas Mraz +--- + test/recipes/80-test_cms.t | 33 ++++++++++++++++++++++++++++- + test/recipes/80-test_cms_data/dh-cert.pem | 31 +++++++++++++++++++++++++++ + test/recipes/80-test_cms_data/dh-key.pem | 15 +++++++++++++ + test/recipes/80-test_cms_data/ecdh-cert.pem | 10 +++++++++ + test/recipes/80-test_cms_data/ecdh-key.pem | 5 +++++ + 5 files changed, 93 insertions(+), 1 deletion(-) + create mode 100644 test/recipes/80-test_cms_data/dh-cert.pem + create mode 100644 test/recipes/80-test_cms_data/dh-key.pem + create mode 100644 test/recipes/80-test_cms_data/ecdh-cert.pem + create mode 100644 test/recipes/80-test_cms_data/ecdh-key.pem + +diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t +index 279a498475c8..90aeb2959707 100644 +--- a/test/recipes/80-test_cms.t ++++ b/test/recipes/80-test_cms.t +@@ -53,7 +53,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) + + $no_rc2 = 1 if disabled("legacy"); + +-plan tests => 31; ++plan tests => 33; + + ok(run(test(["pkcs7_test"])), "test pkcs7"); + +@@ -1360,6 +1360,37 @@ with({ exit_checker => sub { return shift == 3; } }, + "Check for failure when cipher does not have an assigned OID (issue#22225)"); + }); + ++# Test cases for CVE-2026-28389 ++my $smcont_malformed = srctop_file("test", "recipes", "80-test_cms_data", "dh-malformed.der"); ++my $smdhcert = srctop_file("test", "recipes", "80-test_cms_data", "dh-cert.pem"); ++my $smdhkey = srctop_file("test", "recipes", "80-test_cms_data", "dh-key.pem"); ++ ++with({ exit_checker => sub { return shift == 4; } }, ++ sub { ++ SKIP: { ++ skip "DH is not supported in this build", 1 if $no_dh; ++ ++ ok(run(app(["openssl", "cms", @prov, "-decrypt", "-in", $smcont_malformed, ++ "-inform", "DER", "-recip", $smdhcert, "-inkey", $smdhkey])), ++ "Must not crash on malformed cms inputs with dh key"); ++ } ++ }); ++ ++$smcont_malformed = srctop_file("test", "recipes", "80-test_cms_data", "ecdh-malformed.der"); ++my $smecdhcert = srctop_file("test", "recipes", "80-test_cms_data", "ecdh-cert.pem"); ++my $smecdhkey = srctop_file("test", "recipes", "80-test_cms_data", "ecdh-key.pem"); ++ ++with({ exit_checker => sub { return shift == 4; } }, ++ sub { ++ SKIP: { ++ skip "EC is not supported in this build", 1 if $no_ec; ++ ++ ok(run(app(["openssl", "cms", @prov, "-decrypt", "-in", $smcont_malformed, ++ "-inform", "DER", "-recip", $smecdhcert, "-inkey", $smecdhkey])), ++ "Must not crash on malformed cms inputs with ecdh key"); ++ } ++ }); ++ + # Test encrypt to three recipients, and decrypt using key-only; + # i.e. do not follow the recommended practice of providing the + # recipient cert in the decrypt op. +diff --git a/test/recipes/80-test_cms_data/dh-cert.pem b/test/recipes/80-test_cms_data/dh-cert.pem +new file mode 100644 +index 000000000000..f5fb90b9009b +--- /dev/null ++++ b/test/recipes/80-test_cms_data/dh-cert.pem +@@ -0,0 +1,31 @@ ++-----BEGIN CERTIFICATE----- ++MIIFSjCCBDKgAwIBAgIUAV5WB+HkJTxtCmGX88OYfIRfEu8wDQYJKoZIhvcNAQEL ++BQAwVjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM ++GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGcm9vdENBMB4XDTI2 ++MDMzMTA4NDUwOVoXDTI2MDQwMTA4NDUwOVowDjEMMAoGA1UEAwwDcG9jMIIDJzCC ++AhkGByqGSM4+AgEwggIMAoIBAQD//////////634VFiiu0qar9xWICc9PPHYucWD ++zi02lanhNkEUZDP7zJOdziSbPvl9L+NjYwx12PaBsgKuxGF6098e1dX9ZWEkM/Uf ++XwZu0IVjZVU97RrztVcTXn9XyTWYTwxw4OaLd+Kmidrz7+hyHfFYoTat5zUwrMpP ++SDp5erwKsYKzJPth0QipS7LI4/u5atq3YNf0aB1PQqPeOU30rlbt52NyuxkLB6fI ++7gptcJ4C/OHN9+LswDQEzSg0L2GRcv6c6YWD/45PEjLu8oGDw/47G0xvrXM7tfy8 ++LsIgBcWO8YN9FoOyxvNKJsGy7/qIa0I4YShcl///////////AgECAoIBAH////// ++////1vwqLFFdpU1X7isQE56eeOxc4sHnFptK1PCbIIoyGf3mSc7nEk2ffL6X8bGx ++hjrse0DZAVdiML1p749q6v6ysJIZ+o+vgzdoQrGyqp72jXnaq4mvP6vkmswnhjhw ++c0W78VNE7Xn39DkO+KxQm1bzmphWZSekHTy9XgVYwVmSfbDohFSl2WRx/dy1bVuw ++a/o0DqehUe8cpvpXK3bzsbldjIWD0+R3BTa4TwF+cOb78XZgGgJmlBoXsMi5f050 ++wsH/xyeJGXd5QMHh/x2NpjfWuZ3a/l4XYRAC4sd4wb6LQdljeaUTYNl3/UQ1oRww ++lC5L//////////8DggEGAAKCAQEA8IGxSTAsrdMqlK3rFejocWZ0fmXhLzlhnARX ++l3RL+jHyiFoCyCPRLmGBMaL9HqfcVp7E98IvFBxEjtDVc2tcbUJrbv922QaNYqQl ++IwuUhdBHDpg0aSbDTV0Vvbny0hDuD7T7VTUO5D7XJammA2hlbpcfO8xuWFmRjdBJ ++ctA+MaUbWL21ZzsF8A5rz58mVRHchrAez5ksNb8xaLd0lZqtbiBDntA52XnSp1bO ++M2CPlKcb4qMMxVop2DGakChcxu7BUzob22HpRQl+k5K4Tq+kkToHKMR6obpl9Leu ++lzJdR8cH9WqF6TE2YFYkpvzE7V7/Rp4uC6UqOGr62oS4thwLtqNTMFEwHwYDVR0j ++BBgwFoAUhVaJNeKfABrhhgMLS692Emszbf0wDwYDVR0TAQH/BAUwAwEB/zAdBgNV ++HQ4EFgQUIpXhOwY+ufefb4dBhx3niO/ntO0wDQYJKoZIhvcNAQELBQADggEBABWo ++cJfSVwpnYmDHi9U0r0yickvRyFLiOK1vruoKfbkxfYk9J9OwLr4n4S5P5bGXXOSW ++AAVXnvYKs6Xn07sg+1X1Sti/1wd/OLOvjaz1ebRqP5MiZRbKIlRHkv2maJEmcdyp ++JGR4gHGnu/0I5Zp4DOi+xv1R3vGIkkcl/WIncrJflMJcCRMM4YdMV838kFU2esGm ++eB8pTv7acyYsGeSTIk+AYEtS84w3ZQ2sOuGAep0hp9saV/LKiRzNUG0yX2LWP8EO ++VMqGSXJqg1TYgAa7lcidtXfQgm+xdTeZzJRbl8Ti3d5YbgXW2vt4vhwkXtPGy5Y3 ++NGpnrpeWX4rk4kQmx/I= ++-----END CERTIFICATE----- +diff --git a/test/recipes/80-test_cms_data/dh-key.pem b/test/recipes/80-test_cms_data/dh-key.pem +new file mode 100644 +index 000000000000..16010785214e +--- /dev/null ++++ b/test/recipes/80-test_cms_data/dh-key.pem +@@ -0,0 +1,15 @@ ++-----BEGIN PRIVATE KEY----- ++MIICQAIBADCCAhkGByqGSM4+AgEwggIMAoIBAQD//////////634VFiiu0qar9xW ++ICc9PPHYucWDzi02lanhNkEUZDP7zJOdziSbPvl9L+NjYwx12PaBsgKuxGF6098e ++1dX9ZWEkM/UfXwZu0IVjZVU97RrztVcTXn9XyTWYTwxw4OaLd+Kmidrz7+hyHfFY ++oTat5zUwrMpPSDp5erwKsYKzJPth0QipS7LI4/u5atq3YNf0aB1PQqPeOU30rlbt ++52NyuxkLB6fI7gptcJ4C/OHN9+LswDQEzSg0L2GRcv6c6YWD/45PEjLu8oGDw/47 ++G0xvrXM7tfy8LsIgBcWO8YN9FoOyxvNKJsGy7/qIa0I4YShcl///////////AgEC ++AoIBAH//////////1vwqLFFdpU1X7isQE56eeOxc4sHnFptK1PCbIIoyGf3mSc7n ++Ek2ffL6X8bGxhjrse0DZAVdiML1p749q6v6ysJIZ+o+vgzdoQrGyqp72jXnaq4mv ++P6vkmswnhjhwc0W78VNE7Xn39DkO+KxQm1bzmphWZSekHTy9XgVYwVmSfbDohFSl ++2WRx/dy1bVuwa/o0DqehUe8cpvpXK3bzsbldjIWD0+R3BTa4TwF+cOb78XZgGgJm ++lBoXsMi5f050wsH/xyeJGXd5QMHh/x2NpjfWuZ3a/l4XYRAC4sd4wb6LQdljeaUT ++YNl3/UQ1oRwwlC5L//////////8EHgIcJmHQRSrQ2wQnNyMZhx9Xdkf8hro/xi1r ++xDHoWg== ++-----END PRIVATE KEY----- +diff --git a/test/recipes/80-test_cms_data/ecdh-cert.pem b/test/recipes/80-test_cms_data/ecdh-cert.pem +new file mode 100644 +index 000000000000..3a0ab6624ca2 +--- /dev/null ++++ b/test/recipes/80-test_cms_data/ecdh-cert.pem +@@ -0,0 +1,10 @@ ++-----BEGIN CERTIFICATE----- ++MIIBcTCCARegAwIBAgIUFyBfipahA11TzFxBhYY2WfTejGswCgYIKoZIzj0EAwIw ++DjEMMAoGA1UEAwwDcG9jMB4XDTI2MDMzMTA3MzQyOVoXDTI2MDQwMTA3MzQyOVow ++DjEMMAoGA1UEAwwDcG9jMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6iA2FR7s ++OgRtpf8cRXDSLSSB5nSzQt2/hzueZTiQXUT1Knto2U5zRqUoioZ/FKsazdhQVQQC ++EN0/WYGND+XwmaNTMFEwHwYDVR0jBBgwFoAU+AH0MqgJJ4WYRK+BmEDebmjREYcw ++DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+AH0MqgJJ4WYRK+BmEDebmjREYcw ++CgYIKoZIzj0EAwIDSAAwRQIhAPTS8MWoylN+jfLgRfr75WkJqNFlsrfxCDvMtWV+ ++NT2yAiBaY72EVG36EP2gGFEhkBaXb0vLx0r7umDgejEwBWQ9mQ== ++-----END CERTIFICATE----- +diff --git a/test/recipes/80-test_cms_data/ecdh-key.pem b/test/recipes/80-test_cms_data/ecdh-key.pem +new file mode 100644 +index 000000000000..ef9488b3c516 +--- /dev/null ++++ b/test/recipes/80-test_cms_data/ecdh-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgeDjy2W+FHVPt1Kg1 ++unwzzD9yBC+NtbH/UaZ9PY4wZP6hRANCAATqIDYVHuw6BG2l/xxFcNItJIHmdLNC ++3b+HO55lOJBdRPUqe2jZTnNGpSiKhn8UqxrN2FBVBAIQ3T9ZgY0P5fCZ ++-----END PRIVATE KEY----- diff -Nru openssl-3.5.5/debian/patches/dane_match_cert-should-X509_free-on-mcert-instead.patch openssl-3.5.5/debian/patches/dane_match_cert-should-X509_free-on-mcert-instead.patch --- openssl-3.5.5/debian/patches/dane_match_cert-should-X509_free-on-mcert-instead.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/dane_match_cert-should-X509_free-on-mcert-instead.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,32 @@ +From: Alexandr Nedvedicky +Date: Tue, 3 Mar 2026 13:23:46 +0100 +Subject: dane_match_cert() should X509_free() on ->mcert instead of + OPENSSL_free() + +Fixes: 170b735820ac "DANE support for X509_verify_cert()" + +Reviewed-by: Eugene Syromiatnikov +Reviewed-by: Tomas Mraz +Reviewed-by: Paul Dale +Reviewed-by: Neil Horman +MergeDate: Thu Mar 5 12:37:17 2026 +(Merged from https://github.com/openssl/openssl/pull/30250) + +(cherry picked from commit 8b5cd6a682f0f6e7b8bf55137137c567d1899c4a) +--- + crypto/x509/x509_vfy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c +index 20c012def2f3..ca3ffc420473 100644 +--- a/crypto/x509/x509_vfy.c ++++ b/crypto/x509/x509_vfy.c +@@ -3015,7 +3015,7 @@ static int dane_match_cert(X509_STORE_CTX *ctx, X509 *cert, int depth) + break; + } + +- OPENSSL_free(dane->mcert); ++ X509_free(dane->mcert); + dane->mcert = cert; + dane->mdpth = depth; + dane->mtlsa = t; diff -Nru openssl-3.5.5/debian/patches/rsa_kem-test-RSA_public_encrypt-result-in-RSASVE.patch openssl-3.5.5/debian/patches/rsa_kem-test-RSA_public_encrypt-result-in-RSASVE.patch --- openssl-3.5.5/debian/patches/rsa_kem-test-RSA_public_encrypt-result-in-RSASVE.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/rsa_kem-test-RSA_public_encrypt-result-in-RSASVE.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,108 @@ +From: Nikola Pajkovsky +Date: Mon, 23 Mar 2026 08:41:20 +0100 +Subject: rsa_kem: test RSA_public_encrypt() result in RSASVE + +RSA_public_encrypt() returns the number of bytes written on success and +-1 on failure. + +Add regression coverage in evp_extra_test using invalid RSA pubkey +which triggers -1 in RSA_public_encrypt() using encapsulation. + +Fixes: https://github.com/openssl/srt/issues/95 +Signed-off-by: Nikola Pajkovsky +--- + test/evp_extra_test.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c +index f55d17258d1f..d45f497f032a 100644 +--- a/test/evp_extra_test.c ++++ b/test/evp_extra_test.c +@@ -929,6 +929,32 @@ static EVP_PKEY *load_example_ec_key(void) + #endif + + #ifndef OPENSSL_NO_DEPRECATED_3_0 ++ ++static EVP_PKEY *make_bad_rsa_pubkey(void) ++{ ++ RSA *rsa = NULL; ++ BIGNUM *n = NULL, *e = NULL; ++ EVP_PKEY *pkey = NULL; ++ ++ /* Deliberately invalid public key: n = 17, e = 17 */ ++ if (!TEST_ptr(pkey = EVP_PKEY_new()) ++ || !TEST_ptr(rsa = RSA_new()) ++ || !TEST_ptr(n = BN_new()) ++ || !TEST_ptr(e = BN_new()) ++ || !TEST_true(BN_set_word(n, 17)) ++ || !TEST_true(BN_set_word(e, 17)) ++ || !TEST_true(RSA_set0_key(rsa, n, e, NULL)) ++ || !EVP_PKEY_assign_RSA(pkey, rsa)) ++ goto err; ++ ++ return pkey; ++err: ++ BN_free(n); ++ BN_free(e); ++ RSA_free(rsa); ++ return NULL; ++} ++ + #ifndef OPENSSL_NO_DH + static EVP_PKEY *load_example_dh_key(void) + { +@@ -5898,6 +5924,46 @@ static int test_custom_ciph_meth(void) + return testresult; + } + ++static int test_rsasve_kem_with_invalid_pub_key(void) ++{ ++ RSA *rsa = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ unsigned char *ct = NULL; ++ unsigned char *secret = NULL; ++ size_t ctlen = 0, secretlen = 0; ++ int testresult = 0; ++ ++ if (nullprov != NULL) { ++ testresult = TEST_skip("Test does not support a non-default library context"); ++ goto err; ++ } ++ ++ if (!TEST_ptr(pkey = make_bad_rsa_pubkey())) ++ goto err; ++ ++ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pkey, NULL)) ++ || !TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1) ++ || !TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE"), 1) ++ || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &ctlen, NULL, &secretlen), 1) ++ || !TEST_ptr(ct = OPENSSL_malloc(ctlen)) ++ || !TEST_ptr(secret = OPENSSL_malloc(secretlen))) ++ goto err; ++ ++ if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, ct, &ctlen, secret, &secretlen), 0)) ++ goto err; ++ ++ testresult = 1; ++ ++err: ++ OPENSSL_free(secret); ++ OPENSSL_free(ct); ++ EVP_PKEY_CTX_free(ctx); ++ RSA_free(rsa); ++ EVP_PKEY_free(pkey); ++ return testresult; ++} ++ + #ifndef OPENSSL_NO_DYNAMIC_ENGINE + /* Test we can create a signature keys with an associated ENGINE */ + static int test_signatures_with_engine(int tst) +@@ -6854,6 +6920,7 @@ int setup_tests(void) + ADD_TEST(test_evp_md_cipher_meth); + ADD_TEST(test_custom_md_meth); + ADD_TEST(test_custom_ciph_meth); ++ ADD_TEST(test_rsasve_kem_with_invalid_pub_key); + + #ifndef OPENSSL_NO_DYNAMIC_ENGINE + /* Tests only support the default libctx */ diff -Nru openssl-3.5.5/debian/patches/rsa_kem-validate-RSA_public_encrypt-result-in-RSASVE.patch openssl-3.5.5/debian/patches/rsa_kem-validate-RSA_public_encrypt-result-in-RSASVE.patch --- openssl-3.5.5/debian/patches/rsa_kem-validate-RSA_public_encrypt-result-in-RSASVE.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/patches/rsa_kem-validate-RSA_public_encrypt-result-in-RSASVE.patch 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1,56 @@ +From: Nikola Pajkovsky +Date: Thu, 19 Mar 2026 12:16:08 +0100 +Subject: rsa_kem: validate RSA_public_encrypt() result in RSASVE + +RSA_public_encrypt() returns the number of bytes written on success and +-1 on failure. With the existing `if (ret)` check, a provider-side RSA KEM +encapsulation can incorrectly succeed when the underlying RSA public +encrypt operation fails. In that case the code reports success, returns +lengths as if encapsulation completed normally, and leaves the freshly +generated secret available instead of discarding it. + +Tighten the success condition so RSASVE only succeeds when +RSA_public_encrypt() returns a positive value equal to the modulus-sized +output expected for RSA_NO_PADDING. Any other return value is treated as +failure, and the generated secret is cleansed before returning. + +Fixes CVE: CVE-2026-31790 +Fixes: https://github.com/openssl/srt/issues/95 +Signed-off-by: Nikola Pajkovsky +--- + providers/implementations/kem/rsa_kem.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c +index f7bf368a0dfc..74dfafddd9e0 100644 +--- a/providers/implementations/kem/rsa_kem.c ++++ b/providers/implementations/kem/rsa_kem.c +@@ -316,17 +316,19 @@ static int rsasve_generate(PROV_RSA_CTX *prsactx, + return 0; + + /* Step(3): out = RSAEP((n,e), z) */ +- ret = RSA_public_encrypt(nlen, secret, out, prsactx->rsa, RSA_NO_PADDING); +- if (ret) { +- ret = 1; +- if (outlen != NULL) +- *outlen = nlen; +- if (secretlen != NULL) +- *secretlen = nlen; +- } else { ++ ret = RSA_public_encrypt((int)nlen, secret, out, prsactx->rsa, ++ RSA_NO_PADDING); ++ if (ret <= 0 || ret != (int)nlen) { + OPENSSL_cleanse(secret, nlen); ++ return 0; + } +- return ret; ++ ++ if (outlen != NULL) ++ *outlen = nlen; ++ if (secretlen != NULL) ++ *secretlen = nlen; ++ ++ return 1; + } + + /** diff -Nru openssl-3.5.5/debian/patches/series openssl-3.5.5/debian/patches/series --- openssl-3.5.5/debian/patches/series 2026-02-22 12:03:11.000000000 +0000 +++ openssl-3.5.5/debian/patches/series 2026-04-03 10:05:32.000000000 +0000 @@ -5,3 +5,14 @@ c_rehash-compat.patch Configure-allow-to-enable-ktls-if-target-does-not-start-w.patch conf-Serialize-allocation-free-of-ssl_names.patch +Fix-group-tuple-handling-in-DEFAULT-expansion.patch +dane_match_cert-should-X509_free-on-mcert-instead.patch +Fix-NULL-Dereference-When-Delta-CRL-Lacks-CRL-Number-Exte.patch +Added-test-for-CVE-2026-28388.patch +Fix-NULL-deref-in-ec-dh_cms_set_shared_info.patch +Test-for-DH-ECDH-CMS-KARI-processing-NULL-pointer-derefer.patch +Fix-NULL-deref-in-rsa_cms_decrypt.patch +Add-test-for-CMS-decryption-with-RSA-keys.patch +Avoid-possible-buffer-overflow-in-buf2hex-conversion.patch +rsa_kem-validate-RSA_public_encrypt-result-in-RSASVE.patch +rsa_kem-test-RSA_public_encrypt-result-in-RSASVE.patch diff -Nru openssl-3.5.5/debian/rules openssl-3.5.5/debian/rules --- openssl-3.5.5/debian/rules 2026-02-22 12:03:11.000000000 +0000 +++ openssl-3.5.5/debian/rules 2026-04-03 10:05:32.000000000 +0000 @@ -53,6 +53,7 @@ dh $@ --without autoreconf override_dh_auto_configure: + tar xf debian/binary.tar test -z "$(OPTS)" || for opt in $(OPTS); \ do \ set -xe; \ diff -Nru openssl-3.5.5/debian/source/include-binaries openssl-3.5.5/debian/source/include-binaries --- openssl-3.5.5/debian/source/include-binaries 1970-01-01 00:00:00.000000000 +0000 +++ openssl-3.5.5/debian/source/include-binaries 2026-04-03 10:05:32.000000000 +0000 @@ -0,0 +1 @@ +debian/binary.tar