Version in base suite: 1.1.1n-0+deb11u4 Base version: openssl_1.1.1n-0+deb11u4 Target version: openssl_1.1.1n-0+deb11u5 Base file: /srv/ftp-master.debian.org/ftp/pool/main/o/openssl/openssl_1.1.1n-0+deb11u4.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/o/openssl/openssl_1.1.1n-0+deb11u5.dsc changelog | 12 patches/Add-a-Certificate-Policies-Test.patch | 45 patches/Alternative-fix-for-CVE-2022-4304.patch | 454 +++++ patches/Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in-leaf.patch | 49 patches/Fix-documentation-of-X509_VERIFY_PARAM_add0_policy.patch | 42 patches/Generate-some-certificates-with-the-certificatePolicies-e.patch | 141 + patches/Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorrectly-.patch | 24 patches/Restrict-the-size-of-OBJECT-IDENTIFIERs-that-OBJ_obj2txt-.patch | 57 patches/Revert-Fix-Timing-Oracle-in-RSA-decryption.patch | 789 ++++++++++ patches/series | 9 patches/x509-excessive-resource-use-verifying-policy-constraints.patch | 218 ++ 11 files changed, 1840 insertions(+) diff -Nru openssl-1.1.1n/debian/changelog openssl-1.1.1n/debian/changelog --- openssl-1.1.1n/debian/changelog 2023-02-05 21:23:17.000000000 +0000 +++ openssl-1.1.1n/debian/changelog 2023-05-26 21:30:44.000000000 +0000 @@ -1,3 +1,15 @@ +openssl (1.1.1n-0+deb11u5) bullseye-security; urgency=medium + + * CVE-2023-0464 (Excessive Resource Usage Verifying X.509 Policy + Constraints) (Closes: #1034720). + * CVE-2023-0465 (Invalid certificate policies in leaf certificates are + silently ignored). + * CVE-2023-0466 (Certificate policy check not enabled). + * Alternative fix for CVE-2022-4304 (Timing Oracle in RSA Decryption). + * CVE-2023-2650 (Possible DoS translating ASN.1 object identifiers). + + -- Sebastian Andrzej Siewior Fri, 26 May 2023 23:30:44 +0200 + openssl (1.1.1n-0+deb11u4) bullseye-security; urgency=medium * CVE-2022-4450 (Double free after calling PEM_read_bio_ex). diff -Nru openssl-1.1.1n/debian/patches/Add-a-Certificate-Policies-Test.patch openssl-1.1.1n/debian/patches/Add-a-Certificate-Policies-Test.patch --- openssl-1.1.1n/debian/patches/Add-a-Certificate-Policies-Test.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Add-a-Certificate-Policies-Test.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,45 @@ +From: Matt Caswell +Date: Tue, 7 Mar 2023 17:07:57 +0000 +Subject: Add a Certificate Policies Test + +Test that a valid certificate policy is accepted and that an invalid +certificate policy is rejected. Specifically we are checking that a +leaf certificate with an invalid policy is detected. + +Related-to: CVE-2023-0465 + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20588) +--- + test/recipes/25-test_verify.t | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t +index ffa48ed20bbf..e7e352df0bf5 100644 +--- a/test/recipes/25-test_verify.t ++++ b/test/recipes/25-test_verify.t +@@ -27,7 +27,7 @@ sub verify { + run(app([@args])); + } + +-plan tests => 146; ++plan tests => 148; + + # Canonical success + ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), +@@ -409,3 +409,14 @@ SKIP: { + "ED25519 signature"); + + } ++ ++# Certificate Policies ++ok(verify("ee-cert-policies", "sslserver", ["root-cert"], ["ca-pol-cert"], ++ "-policy_check", "-policy", "1.3.6.1.4.1.16604.998855.1", ++ "-explicit_policy"), ++ "Certificate policy"); ++ ++ok(!verify("ee-cert-policies-bad", "sslserver", ["root-cert"], ["ca-pol-cert"], ++ "-policy_check", "-policy", "1.3.6.1.4.1.16604.998855.1", ++ "-explicit_policy"), ++ "Bad certificate policy"); diff -Nru openssl-1.1.1n/debian/patches/Alternative-fix-for-CVE-2022-4304.patch openssl-1.1.1n/debian/patches/Alternative-fix-for-CVE-2022-4304.patch --- openssl-1.1.1n/debian/patches/Alternative-fix-for-CVE-2022-4304.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Alternative-fix-for-CVE-2022-4304.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,454 @@ +From: Bernd Edlinger +Date: Mon, 13 Feb 2023 17:46:41 +0100 +Subject: Alternative fix for CVE-2022-4304 + +This is about a timing leak in the topmost limb +of the internal result of RSA_private_decrypt, +before the padding check. + +There are in fact at least three bugs together that +caused the timing leak: + +First and probably most important is the fact that +the blinding did not use the constant time code path +at all when the RSA object was used for a private +decrypt, due to the fact that the Montgomery context +rsa->_method_mod_n was not set up early enough in +rsa_ossl_private_decrypt, when BN_BLINDING_create_param +needed it, and that was persisted as blinding->m_ctx, +although the RSA object creates the Montgomery context +just a bit later. + +Then the infamous bn_correct_top was used on the +secret value right after the blinding was removed. + +And finally the function BN_bn2binpad did not use +the constant-time code path since the BN_FLG_CONSTTIME +was not set on the secret value. + +In order to address the first problem, this patch +makes sure that the rsa->_method_mod_n is initialized +right before the blinding context. + +And to fix the second problem, we add a new utility +function bn_correct_top_consttime, a const-time +variant of bn_correct_top. + +Together with the fact, that BN_bn2binpad is already +constant time if the flag BN_FLG_CONSTTIME is set, +this should eliminate the timing oracle completely. + +In addition the no-asm variant may also have +branches that depend on secret values, because the last +invocation of bn_sub_words in bn_from_montgomery_word +had branches when the function is compiled by certain +gcc compiler versions, due to the clumsy coding style. + +So additionally this patch stream-lined the no-asm +C-code in order to avoid branches where possible and +improve the resulting code quality. + +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20284) +--- + crypto/bn/bn_asm.c | 106 +++++++++++++++++++++++++++----------------------- + crypto/bn/bn_blind.c | 3 +- + crypto/bn/bn_lib.c | 22 +++++++++++ + crypto/bn/bn_local.h | 26 ++++++------- + crypto/rsa/rsa_ossl.c | 13 +++---- + 5 files changed, 101 insertions(+), 69 deletions(-) + +diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c +index 4d83a8cf1115..177558c6477f 100644 +--- a/crypto/bn/bn_asm.c ++++ b/crypto/bn/bn_asm.c +@@ -381,25 +381,33 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + #ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + t1 = a[0]; +- t2 = b[0]; +- r[0] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[0]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[0] = t1; ++ c += (t1 > t2); + t1 = a[1]; +- t2 = b[1]; +- r[1] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[1]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[1] = t1; ++ c += (t1 > t2); + t1 = a[2]; +- t2 = b[2]; +- r[2] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[2]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[2] = t1; ++ c += (t1 > t2); + t1 = a[3]; +- t2 = b[3]; +- r[3] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[3]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[3] = t1; ++ c += (t1 > t2); + a += 4; + b += 4; + r += 4; +@@ -408,10 +416,12 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + #endif + while (n) { + t1 = a[0]; +- t2 = b[0]; +- r[0] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[0]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[0] = t1; ++ c += (t1 > t2); + a++; + b++; + r++; +@@ -446,7 +456,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + t += c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(t); \ + hi = (BN_ULONG)Hw(t); \ +- c1 = (c1+hi)&BN_MASK2; if (c1top = (int)(rtop & ~mask) | (ntop & mask); + n->flags |= (BN_FLG_FIXED_TOP & ~mask); + } +- ret = BN_mod_mul_montgomery(n, n, r, b->m_ctx, ctx); ++ ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx); ++ bn_correct_top_consttime(n); + } else { + ret = BN_mod_mul(n, n, r, b->mod, ctx); + } +diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c +index eb4a31849bef..fe6fb0e40fbb 100644 +--- a/crypto/bn/bn_lib.c ++++ b/crypto/bn/bn_lib.c +@@ -1001,6 +1001,28 @@ BIGNUM *bn_wexpand(BIGNUM *a, int words) + return (words <= a->dmax) ? a : bn_expand2(a, words); + } + ++void bn_correct_top_consttime(BIGNUM *a) ++{ ++ int j, atop; ++ BN_ULONG limb; ++ unsigned int mask; ++ ++ for (j = 0, atop = 0; j < a->dmax; j++) { ++ limb = a->d[j]; ++ limb |= 0 - limb; ++ limb >>= BN_BITS2 - 1; ++ limb = 0 - limb; ++ mask = (unsigned int)limb; ++ mask &= constant_time_msb(j - a->top); ++ atop = constant_time_select_int(mask, j + 1, atop); ++ } ++ ++ mask = constant_time_eq_int(atop, 0); ++ a->top = atop; ++ a->neg = constant_time_select_int(mask, 0, a->neg); ++ a->flags &= ~BN_FLG_FIXED_TOP; ++} ++ + void bn_correct_top(BIGNUM *a) + { + BN_ULONG *ftl; +diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h +index 8ad69ccd3639..80b89e632d31 100644 +--- a/crypto/bn/bn_local.h ++++ b/crypto/bn/bn_local.h +@@ -495,10 +495,10 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + ret = (r); \ + BN_UMULT_LOHI(low,high,w,tmp); \ + ret += (c); \ +- (c) = (ret<(c))?1:0; \ ++ (c) = (ret<(c)); \ + (c) += high; \ + ret += low; \ +- (c) += (ret>(BN_BITS4-1); \ + m =(m&BN_MASK2l)<<(BN_BITS4+1); \ +- l=(l+m)&BN_MASK2; if (l < m) h++; \ ++ l=(l+m)&BN_MASK2; h += (l < m); \ + (lo)=l; \ + (ho)=h; \ + } +@@ -603,9 +603,9 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ +- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ ++ l=(l+(c))&BN_MASK2; h += (l < (c)); \ + (c)=(r); \ +- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ ++ l=(l+(c))&BN_MASK2; h += (l < (c)); \ + (c)=h&BN_MASK2; \ + (r)=l; \ + } +@@ -619,7 +619,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ +- l+=(c); if ((l&BN_MASK2) < (c)) h++; \ ++ l+=(c); h += ((l&BN_MASK2) < (c)); \ + (c)=h&BN_MASK2; \ + (r)=l&BN_MASK2; \ + } +@@ -649,7 +649,7 @@ BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl); + int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); +- ++void bn_correct_top_consttime(BIGNUM *a); + BIGNUM *int_bn_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, + int *noinv); +diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c +index b52a66f6a628..88371b1dbe16 100644 +--- a/crypto/rsa/rsa_ossl.c ++++ b/crypto/rsa/rsa_ossl.c +@@ -226,6 +226,7 @@ static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, + * will only read the modulus from BN_BLINDING. In both cases it's safe + * to access the blinding without a lock. + */ ++ BN_set_flags(f, BN_FLG_CONSTTIME); + return BN_BLINDING_invert_ex(f, unblind, b, ctx); + } + +@@ -412,6 +413,11 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + goto err; + } + ++ if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) ++ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, ++ rsa->n, ctx)) ++ goto err; ++ + if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) { + blinding = rsa_get_blinding(rsa, &local_blinding, ctx); + if (blinding == NULL) { +@@ -449,13 +455,6 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + goto err; + } + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); +- +- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) +- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, +- rsa->n, ctx)) { +- BN_free(d); +- goto err; +- } + if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx, + rsa->_method_mod_n)) { + BN_free(d); diff -Nru openssl-1.1.1n/debian/patches/Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in-leaf.patch openssl-1.1.1n/debian/patches/Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in-leaf.patch --- openssl-1.1.1n/debian/patches/Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in-leaf.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in-leaf.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,49 @@ +From: Matt Caswell +Date: Tue, 7 Mar 2023 16:52:55 +0000 +Subject: Ensure that EXFLAG_INVALID_POLICY is checked even in leaf certs + +Even though we check the leaf cert to confirm it is valid, we +later ignored the invalid flag and did not notice that the leaf +cert was bad. + +Fixes: CVE-2023-0465 + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20588) +--- + crypto/x509/x509_vfy.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c +index b18489f67f6e..861a1ae732c9 100644 +--- a/crypto/x509/x509_vfy.c ++++ b/crypto/x509/x509_vfy.c +@@ -1649,18 +1649,25 @@ static int check_policy(X509_STORE_CTX *ctx) + } + /* Invalid or inconsistent extensions */ + if (ret == X509_PCY_TREE_INVALID) { +- int i; ++ int i, cbcalled = 0; + + /* Locate certificates with bad extensions and notify callback. */ +- for (i = 1; i < sk_X509_num(ctx->chain); i++) { ++ for (i = 0; i < sk_X509_num(ctx->chain); i++) { + X509 *x = sk_X509_value(ctx->chain, i); + + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) + continue; ++ cbcalled = 1; + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_INVALID_POLICY_EXTENSION)) + return 0; + } ++ if (!cbcalled) { ++ /* Should not be able to get here */ ++ X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ /* The callback ignored the error so we return success */ + return 1; + } + if (ret == X509_PCY_TREE_FAILURE) { diff -Nru openssl-1.1.1n/debian/patches/Fix-documentation-of-X509_VERIFY_PARAM_add0_policy.patch openssl-1.1.1n/debian/patches/Fix-documentation-of-X509_VERIFY_PARAM_add0_policy.patch --- openssl-1.1.1n/debian/patches/Fix-documentation-of-X509_VERIFY_PARAM_add0_policy.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Fix-documentation-of-X509_VERIFY_PARAM_add0_policy.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,42 @@ +From: Tomas Mraz +Date: Tue, 21 Mar 2023 16:15:47 +0100 +Subject: Fix documentation of X509_VERIFY_PARAM_add0_policy() + +The function was incorrectly documented as enabling policy checking. + +Fixes: CVE-2023-0466 + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/20564) +--- + doc/man3/X509_VERIFY_PARAM_set_flags.pod | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/doc/man3/X509_VERIFY_PARAM_set_flags.pod b/doc/man3/X509_VERIFY_PARAM_set_flags.pod +index f6f304bf7bd0..aa292f9336fc 100644 +--- a/doc/man3/X509_VERIFY_PARAM_set_flags.pod ++++ b/doc/man3/X509_VERIFY_PARAM_set_flags.pod +@@ -92,8 +92,9 @@ B. + X509_VERIFY_PARAM_set_time() sets the verification time in B to + B. Normally the current time is used. + +-X509_VERIFY_PARAM_add0_policy() enables policy checking (it is disabled +-by default) and adds B to the acceptable policy set. ++X509_VERIFY_PARAM_add0_policy() adds B to the acceptable policy set. ++Contrary to preexisting documentation of this function it does not enable ++policy checking. + + X509_VERIFY_PARAM_set1_policies() enables policy checking (it is disabled + by default) and sets the acceptable policy set to B. Any existing +@@ -377,6 +378,10 @@ and has no effect. + + The X509_VERIFY_PARAM_get_hostflags() function was added in OpenSSL 1.1.0i. + ++The function X509_VERIFY_PARAM_add0_policy() was historically documented as ++enabling policy checking however the implementation has never done this. ++The documentation was changed to align with the implementation. ++ + =head1 COPYRIGHT + + Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. diff -Nru openssl-1.1.1n/debian/patches/Generate-some-certificates-with-the-certificatePolicies-e.patch openssl-1.1.1n/debian/patches/Generate-some-certificates-with-the-certificatePolicies-e.patch --- openssl-1.1.1n/debian/patches/Generate-some-certificates-with-the-certificatePolicies-e.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Generate-some-certificates-with-the-certificatePolicies-e.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,141 @@ +From: Matt Caswell +Date: Tue, 7 Mar 2023 15:22:40 +0000 +Subject: Generate some certificates with the certificatePolicies extension + +Related-to: CVE-2023-0465 + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20588) +--- + test/certs/ca-pol-cert.pem | 19 +++++++++++++++++++ + test/certs/ee-cert-policies-bad.pem | 20 ++++++++++++++++++++ + test/certs/ee-cert-policies.pem | 20 ++++++++++++++++++++ + test/certs/mkcert.sh | 9 +++++++-- + test/certs/setup.sh | 6 ++++++ + 5 files changed, 72 insertions(+), 2 deletions(-) + create mode 100644 test/certs/ca-pol-cert.pem + create mode 100644 test/certs/ee-cert-policies-bad.pem + create mode 100644 test/certs/ee-cert-policies.pem + +diff --git a/test/certs/ca-pol-cert.pem b/test/certs/ca-pol-cert.pem +new file mode 100644 +index 000000000000..244af3292b21 +--- /dev/null ++++ b/test/certs/ca-pol-cert.pem +@@ -0,0 +1,19 @@ ++-----BEGIN CERTIFICATE----- ++MIIDFzCCAf+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 ++IENBMCAXDTIzMDMwODEyMjMxNloYDzIxMjMwMzA5MTIyMzE2WjANMQswCQYDVQQD ++DAJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJadpD0ASxxfxsvd ++j9IxsogVzMSGLFziaYuE9KejU9+R479RifvwfBANO62sNWJ19X//9G5UjwWmkiOz ++n1k50DkYsBBA3mJzik6wjt/c58lBIlSEgAgpvDU8ht8w3t20JP9+YqXAeugqFj/W ++l9rFQtsvaWSRywjXVlp5fxuEQelNnXcJEKhsKTNExsBUZebo4/J1BWpklWzA9P0l ++YW5INvDAAwcF1nzlEf0Y6Eot03IMNyg2MTE4hehxjdgCSci8GYnFirE/ojXqqpAc ++ZGh7r2dqWgZUD1Dh+bT2vjrUzj8eTH3GdzI+oljt29102JIUaqj3yzRYkah8FLF9 ++CLNNsUcCAwEAAaN7MHkwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYD ++VR0OBBYEFLQRM/HX4l73U54gIhBPhga/H8leMB8GA1UdIwQYMBaAFI71Ja8em2uE ++PXyAmslTnE1y96NSMBkGA1UdIAQSMBAwDgYMKwYBBAGBgVy8+0cBMA0GCSqGSIb3 ++DQEBCwUAA4IBAQBbE+MO9mewWIUY2kt85yhl0oZtvVxbn9K2Hty59ItwJGRNfzx7 ++Ge7KgawkvNzMOXmj6qf8TpbJnf41ZLWdRyVZBVyIwrAKIVw1VxfGh8aEifHKN97H ++unZkBPcUkAhUJSiC1BOD/euaMYqOi8QwiI702Q6q1NBY1/UKnV/ZIBLecnqfj9vZ ++7T0wKxrwGYBztP4pNcxCmBoD9Dg+Dx3ZElo0WXyO4SOh/BgrsKJHKyhbuTpjrI/g ++DhcINRp6+lIzuFBtJ67+YXnAEspb3lKMk0YL/LXrCNF2scdmNfOPwHi+OKBqt69C ++9FJyWFEMxx2qm/ENE9sbOswgJRnKkaAqHBHx ++-----END CERTIFICATE----- +diff --git a/test/certs/ee-cert-policies-bad.pem b/test/certs/ee-cert-policies-bad.pem +new file mode 100644 +index 000000000000..0fcd6372b317 +--- /dev/null ++++ b/test/certs/ee-cert-policies-bad.pem +@@ -0,0 +1,20 @@ ++-----BEGIN CERTIFICATE----- ++MIIDTTCCAjWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJDQTAg ++Fw0yMzAzMDgxMjIzMzJaGA8yMTIzMDMwOTEyMjMzMlowGTEXMBUGA1UEAwwOc2Vy ++dmVyLmV4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo/4lY ++YYWu3tssD9Vz++K3qBt6dWAr1H08c3a1rt6TL38kkG3JHPSKOM2fooAWVsu0LLuT ++5Rcf/w3GQ/4xNPgo2HXpo7uIgu+jcuJTYgVFTeAxl++qnRDSWA2eBp4yuxsIVl1l ++Dz9mjsI2oBH/wFk1/Ukc3RxCMwZ4rgQ4I+XndWfTlK1aqUAfrFkQ9QzBZK1KxMY1 ++U7OWaoIbFYvRmavknm+UqtKW5Vf7jJFkijwkFsbSGb6CYBM7YrDtPh2zyvlr3zG5 ++ep5LR2inKcc/SuIiJ7TvkGPX79ByST5brbkb1Ctvhmjd1XMSuEPJ3EEPoqNGT4tn ++iIQPYf55NB9KiR+3AgMBAAGjgakwgaYwHQYDVR0OBBYEFOeb4iqtimw6y3ZR5Y4H ++mCKX4XOiMB8GA1UdIwQYMBaAFLQRM/HX4l73U54gIhBPhga/H8leMAkGA1UdEwQC ++MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGQYDVR0RBBIwEIIOc2VydmVyLmV4YW1w ++bGUwKQYDVR0gBCIwIDAOBgwrBgEEAYGBXLz7RwEwDgYMKwYBBAGBgVy8+0cBMA0G ++CSqGSIb3DQEBCwUAA4IBAQArwtwNO++7kStcJeMg3ekz2D/m/8UEjTA1rknBjQiQ ++P0FK7tNeRqus9i8PxthNWk+biRayvDzaGIBV7igpDBPfXemDgmW9Adc4MKyiQDfs ++YfkHi3xJKvsK2fQmyCs2InVDaKpVAkNFcgAW8nSOhGliqIxLb0EOLoLNwaktou0N ++XQHmRzY8S7aIr8K9Qo9y/+MLar+PS4h8l6FkLLkTICiFzE4/wje5S3NckAnadRJa ++QpjwM2S6NuA+tYWuOcN//r7BSpW/AZKanYWPzHMrKlqCh+9o7sthPd72+hObG9kx ++wSGdzfStNK1I1zM5LiI08WtXCvR6AfLANTo2x1AYhSxF ++-----END CERTIFICATE----- +diff --git a/test/certs/ee-cert-policies.pem b/test/certs/ee-cert-policies.pem +new file mode 100644 +index 000000000000..2f06d7433fd9 +--- /dev/null ++++ b/test/certs/ee-cert-policies.pem +@@ -0,0 +1,20 @@ ++-----BEGIN CERTIFICATE----- ++MIIDPTCCAiWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJDQTAg ++Fw0yMzAzMDgxMjIzMjNaGA8yMTIzMDMwOTEyMjMyM1owGTEXMBUGA1UEAwwOc2Vy ++dmVyLmV4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo/4lY ++YYWu3tssD9Vz++K3qBt6dWAr1H08c3a1rt6TL38kkG3JHPSKOM2fooAWVsu0LLuT ++5Rcf/w3GQ/4xNPgo2HXpo7uIgu+jcuJTYgVFTeAxl++qnRDSWA2eBp4yuxsIVl1l ++Dz9mjsI2oBH/wFk1/Ukc3RxCMwZ4rgQ4I+XndWfTlK1aqUAfrFkQ9QzBZK1KxMY1 ++U7OWaoIbFYvRmavknm+UqtKW5Vf7jJFkijwkFsbSGb6CYBM7YrDtPh2zyvlr3zG5 ++ep5LR2inKcc/SuIiJ7TvkGPX79ByST5brbkb1Ctvhmjd1XMSuEPJ3EEPoqNGT4tn ++iIQPYf55NB9KiR+3AgMBAAGjgZkwgZYwHQYDVR0OBBYEFOeb4iqtimw6y3ZR5Y4H ++mCKX4XOiMB8GA1UdIwQYMBaAFLQRM/HX4l73U54gIhBPhga/H8leMAkGA1UdEwQC ++MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGQYDVR0RBBIwEIIOc2VydmVyLmV4YW1w ++bGUwGQYDVR0gBBIwEDAOBgwrBgEEAYGBXLz7RwEwDQYJKoZIhvcNAQELBQADggEB ++AGbWslmAAdMX3+5ChcnFrX+NqDGoyhb3PTgWdtlQB5qtWdIt4rSxN50OcQxFTX0D ++QOBabSzR0DDKrgfBe4waL19WsdEvR9GyO4M7ASze/A3IEZue9C9k0n7Vq8zDaAZl ++CiR/Zqo9nAOuhKHMgmC/NjUlX7STv5pJVgc4SH8VEKmSRZDmNihaOalUtK5X8/Oa ++dawKxsZcaP5IKnOEPPKjtVNJxBu5CXywJHsO0GcoDEnEx1/NLdFoJ6WFw8NuTyDK ++NGLq2MHEdyKaigHQlptEs9bXyu9McJjzbx0uXj3BenRULASreccFej0L1RU6jDlk ++D3brBn24UISaFRZoB7jsjok= ++-----END CERTIFICATE----- +diff --git a/test/certs/mkcert.sh b/test/certs/mkcert.sh +index d8e70423911f..dd04aee48d23 100755 +--- a/test/certs/mkcert.sh ++++ b/test/certs/mkcert.sh +@@ -117,11 +117,12 @@ genca() { + local OPTIND=1 + local purpose= + +- while getopts p: o ++ while getopts p:c: o + do + case $o in + p) purpose="$OPTARG";; +- *) echo "Usage: $0 genca [-p EKU] cn keyname certname cakeyname cacertname" >&2 ++ c) certpol="$OPTARG";; ++ *) echo "Usage: $0 genca [-p EKU][-c policyoid] cn keyname certname cakeyname cacertname" >&2 + return 1;; + esac + done +@@ -142,6 +143,10 @@ genca() { + if [ -n "$NC" ]; then + exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC") + fi ++ if [ -n "$certpol" ]; then ++ exts=$(printf "%s\ncertificatePolicies = %s\n" "$exts" "$certpol") ++ fi ++ + csr=$(req "$key" "CN = $cn") || return 1 + echo "$csr" | + cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \ +diff --git a/test/certs/setup.sh b/test/certs/setup.sh +index 020f6ce97342..1cbef67ae00f 100755 +--- a/test/certs/setup.sh ++++ b/test/certs/setup.sh +@@ -405,3 +405,9 @@ OPENSSL_SIGALG=ED448 OPENSSL_KEYALG=ed448 ./mkcert.sh genroot "Root Ed448" \ + root-ed448-key root-ed448-cert + OPENSSL_SIGALG=ED448 OPENSSL_KEYALG=ed448 ./mkcert.sh genee ed448 \ + server-ed448-key server-ed448-cert root-ed448-key root-ed448-cert ++ ++# certificatePolicies extension ++./mkcert.sh genca -c "1.3.6.1.4.1.16604.998855.1" "CA" ca-key ca-pol-cert root-key root-cert ++./mkcert.sh geneeextra server.example ee-key ee-cert-policies ca-key ca-cert "certificatePolicies=1.3.6.1.4.1.16604.998855.1" ++# We can create a cert with a duplicate policy oid - but its actually invalid! ++./mkcert.sh geneeextra server.example ee-key ee-cert-policies-bad ca-key ca-cert "certificatePolicies=1.3.6.1.4.1.16604.998855.1,1.3.6.1.4.1.16604.998855.1" diff -Nru openssl-1.1.1n/debian/patches/Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorrectly-.patch openssl-1.1.1n/debian/patches/Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorrectly-.patch --- openssl-1.1.1n/debian/patches/Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorrectly-.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorrectly-.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,24 @@ +From: Tomas Mraz +Date: Thu, 20 Apr 2023 10:24:38 +0200 +Subject: Re-add BN_F_OSSL_BN_RSA_DO_UNBLIND which was incorrectly removed + +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/20784) +--- + include/openssl/bnerr.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/openssl/bnerr.h b/include/openssl/bnerr.h +index 9f3c7cfaab67..a0752cea52d7 100644 +--- a/include/openssl/bnerr.h ++++ b/include/openssl/bnerr.h +@@ -72,6 +72,7 @@ int ERR_load_BN_strings(void); + # define BN_F_BN_SET_WORDS 144 + # define BN_F_BN_STACK_PUSH 148 + # define BN_F_BN_USUB 115 ++# define BN_F_OSSL_BN_RSA_DO_UNBLIND 151 + + /* + * BN reason codes. diff -Nru openssl-1.1.1n/debian/patches/Restrict-the-size-of-OBJECT-IDENTIFIERs-that-OBJ_obj2txt-.patch openssl-1.1.1n/debian/patches/Restrict-the-size-of-OBJECT-IDENTIFIERs-that-OBJ_obj2txt-.patch --- openssl-1.1.1n/debian/patches/Restrict-the-size-of-OBJECT-IDENTIFIERs-that-OBJ_obj2txt-.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Restrict-the-size-of-OBJECT-IDENTIFIERs-that-OBJ_obj2txt-.patch 2023-05-26 21:30:44.000000000 +0000 @@ -0,0 +1,57 @@ +From: Richard Levitte +Date: Fri, 12 May 2023 10:00:13 +0200 +Subject: Restrict the size of OBJECT IDENTIFIERs that OBJ_obj2txt will + translate + +OBJ_obj2txt() would translate any size OBJECT IDENTIFIER to canonical +numeric text form. For gigantic sub-identifiers, this would take a very +long time, the time complexity being O(n^2) where n is the size of that +sub-identifier. + +To mitigate this, a restriction on the size that OBJ_obj2txt() will +translate to canonical numeric text form is added, based on RFC 2578 +(STD 58), which says this: + +> 3.5. OBJECT IDENTIFIER values +> +> An OBJECT IDENTIFIER value is an ordered list of non-negative numbers. +> For the SMIv2, each number in the list is referred to as a sub-identifier, +> there are at most 128 sub-identifiers in a value, and each sub-identifier +> has a maximum value of 2^32-1 (4294967295 decimal). + +Fixes otc/security#96 +Fixes CVE-2023-2650 +--- + crypto/objects/obj_dat.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c +index 7e8de727f310..d699915b20e7 100644 +--- a/crypto/objects/obj_dat.c ++++ b/crypto/objects/obj_dat.c +@@ -428,6 +428,25 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) + first = 1; + bl = NULL; + ++ /* ++ * RFC 2578 (STD 58) says this about OBJECT IDENTIFIERs: ++ * ++ * > 3.5. OBJECT IDENTIFIER values ++ * > ++ * > An OBJECT IDENTIFIER value is an ordered list of non-negative ++ * > numbers. For the SMIv2, each number in the list is referred to as a ++ * > sub-identifier, there are at most 128 sub-identifiers in a value, ++ * > and each sub-identifier has a maximum value of 2^32-1 (4294967295 ++ * > decimal). ++ * ++ * So a legitimate OID according to this RFC is at most (32 * 128 / 7), ++ * i.e. 586 bytes long. ++ * ++ * Ref: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5 ++ */ ++ if (len > 586) ++ goto err; ++ + while (len > 0) { + l = 0; + use_bn = 0; diff -Nru openssl-1.1.1n/debian/patches/Revert-Fix-Timing-Oracle-in-RSA-decryption.patch openssl-1.1.1n/debian/patches/Revert-Fix-Timing-Oracle-in-RSA-decryption.patch --- openssl-1.1.1n/debian/patches/Revert-Fix-Timing-Oracle-in-RSA-decryption.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/Revert-Fix-Timing-Oracle-in-RSA-decryption.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,789 @@ +From: Sebastian Andrzej Siewior +Date: Fri, 26 May 2023 23:12:04 +0200 +Subject: Revert "Fix Timing Oracle in RSA decryption" + +This reverts commit ce888cab5b576f53bfe6aebe374efdba5e74e519. +--- + crypto/bn/bn_blind.c | 14 ++ + crypto/bn/bn_err.c | 2 - + crypto/bn/bn_local.h | 14 -- + crypto/bn/build.info | 3 +- + crypto/bn/rsa_sup_mul.c | 614 ------------------------------------------------ + crypto/err/openssl.txt | 3 +- + crypto/rsa/rsa_ossl.c | 17 +- + include/crypto/bn.h | 5 - + include/openssl/bnerr.h | 1 - + 9 files changed, 20 insertions(+), 653 deletions(-) + delete mode 100644 crypto/bn/rsa_sup_mul.c + +diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c +index 6e9d23932119..76fc7ebcffc0 100644 +--- a/crypto/bn/bn_blind.c ++++ b/crypto/bn/bn_blind.c +@@ -13,6 +13,20 @@ + + #define BN_BLINDING_COUNTER 32 + ++struct bn_blinding_st { ++ BIGNUM *A; ++ BIGNUM *Ai; ++ BIGNUM *e; ++ BIGNUM *mod; /* just a reference */ ++ CRYPTO_THREAD_ID tid; ++ int counter; ++ unsigned long flags; ++ BN_MONT_CTX *m_ctx; ++ int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, ++ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); ++ CRYPTO_RWLOCK *lock; ++}; ++ + BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) + { + BN_BLINDING *ret = NULL; +diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c +index 3dd8d9a5682b..dd87c152cf37 100644 +--- a/crypto/bn/bn_err.c ++++ b/crypto/bn/bn_err.c +@@ -73,8 +73,6 @@ static const ERR_STRING_DATA BN_str_functs[] = { + {ERR_PACK(ERR_LIB_BN, BN_F_BN_SET_WORDS, 0), "bn_set_words"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_STACK_PUSH, 0), "BN_STACK_push"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_USUB, 0), "BN_usub"}, +- {ERR_PACK(ERR_LIB_BN, BN_F_OSSL_BN_RSA_DO_UNBLIND, 0), +- "ossl_bn_rsa_do_unblind"}, + {0, NULL} + }; + +diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h +index 096513533b70..8ad69ccd3639 100644 +--- a/crypto/bn/bn_local.h ++++ b/crypto/bn/bn_local.h +@@ -263,20 +263,6 @@ struct bn_gencb_st { + } cb; + }; + +-struct bn_blinding_st { +- BIGNUM *A; +- BIGNUM *Ai; +- BIGNUM *e; +- BIGNUM *mod; /* just a reference */ +- CRYPTO_THREAD_ID tid; +- int counter; +- unsigned long flags; +- BN_MONT_CTX *m_ctx; +- int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, +- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +- CRYPTO_RWLOCK *lock; +-}; +- + /*- + * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions + * +diff --git a/crypto/bn/build.info b/crypto/bn/build.info +index c9fe2fdada69..b9ed5322fa68 100644 +--- a/crypto/bn/build.info ++++ b/crypto/bn/build.info +@@ -5,8 +5,7 @@ SOURCE[../../libcrypto]=\ + bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c \ + {- $target{bn_asm_src} -} \ + bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \ +- bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c \ +- rsa_sup_mul.c ++ bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c + + INCLUDE[bn_exp.o]=.. + +diff --git a/crypto/bn/rsa_sup_mul.c b/crypto/bn/rsa_sup_mul.c +deleted file mode 100644 +index acafefd5febf..000000000000 +--- a/crypto/bn/rsa_sup_mul.c ++++ /dev/null +@@ -1,614 +0,0 @@ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "internal/numbers.h" +-#include "internal/constant_time.h" +-#include "bn_local.h" +- +-# if BN_BYTES == 8 +-typedef uint64_t limb_t; +-# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 +-/* nonstandard; implemented by gcc on 64-bit platforms */ +-typedef __uint128_t limb2_t; +-# define HAVE_LIMB2_T +-# endif +-# define LIMB_BIT_SIZE 64 +-# define LIMB_BYTE_SIZE 8 +-# elif BN_BYTES == 4 +-typedef uint32_t limb_t; +-typedef uint64_t limb2_t; +-# define LIMB_BIT_SIZE 32 +-# define LIMB_BYTE_SIZE 4 +-# define HAVE_LIMB2_T +-# else +-# error "Not supported" +-# endif +- +-/* +- * For multiplication we're using schoolbook multiplication, +- * so if we have two numbers, each with 6 "digits" (words) +- * the multiplication is calculated as follows: +- * A B C D E F +- * x I J K L M N +- * -------------- +- * N*F +- * N*E +- * N*D +- * N*C +- * N*B +- * N*A +- * M*F +- * M*E +- * M*D +- * M*C +- * M*B +- * M*A +- * L*F +- * L*E +- * L*D +- * L*C +- * L*B +- * L*A +- * K*F +- * K*E +- * K*D +- * K*C +- * K*B +- * K*A +- * J*F +- * J*E +- * J*D +- * J*C +- * J*B +- * J*A +- * I*F +- * I*E +- * I*D +- * I*C +- * I*B +- * + I*A +- * ========================== +- * N*B N*D N*F +- * + N*A N*C N*E +- * + M*B M*D M*F +- * + M*A M*C M*E +- * + L*B L*D L*F +- * + L*A L*C L*E +- * + K*B K*D K*F +- * + K*A K*C K*E +- * + J*B J*D J*F +- * + J*A J*C J*E +- * + I*B I*D I*F +- * + I*A I*C I*E +- * +- * 1+1 1+3 1+5 +- * 1+0 1+2 1+4 +- * 0+1 0+3 0+5 +- * 0+0 0+2 0+4 +- * +- * 0 1 2 3 4 5 6 +- * which requires n^2 multiplications and 2n full length additions +- * as we can keep every other result of limb multiplication in two separate +- * limbs +- */ +- +-#if defined HAVE_LIMB2_T +-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) +-{ +- limb2_t t; +- /* +- * this is idiomatic code to tell compiler to use the native mul +- * those three lines will actually compile to single instruction +- */ +- +- t = (limb2_t)a * b; +- *hi = t >> LIMB_BIT_SIZE; +- *lo = (limb_t)t; +-} +-#elif (BN_BYTES == 8) && (defined _MSC_VER) +-/* https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170 */ +-#pragma intrinsic(_umul128) +-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) +-{ +- *lo = _umul128(a, b, hi); +-} +-#else +-/* +- * if the compiler doesn't have either a 128bit data type nor a "return +- * high 64 bits of multiplication" +- */ +-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) +-{ +- limb_t a_low = (limb_t)(uint32_t)a; +- limb_t a_hi = a >> 32; +- limb_t b_low = (limb_t)(uint32_t)b; +- limb_t b_hi = b >> 32; +- +- limb_t p0 = a_low * b_low; +- limb_t p1 = a_low * b_hi; +- limb_t p2 = a_hi * b_low; +- limb_t p3 = a_hi * b_hi; +- +- uint32_t cy = (uint32_t)(((p0 >> 32) + (uint32_t)p1 + (uint32_t)p2) >> 32); +- +- *lo = p0 + (p1 << 32) + (p2 << 32); +- *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy; +-} +-#endif +- +-/* add two limbs with carry in, return carry out */ +-static ossl_inline limb_t _add_limb(limb_t *ret, limb_t a, limb_t b, limb_t carry) +-{ +- limb_t carry1, carry2, t; +- /* +- * `c = a + b; if (c < a)` is idiomatic code that makes compilers +- * use add with carry on assembly level +- */ +- +- *ret = a + carry; +- if (*ret < a) +- carry1 = 1; +- else +- carry1 = 0; +- +- t = *ret; +- *ret = t + b; +- if (*ret < t) +- carry2 = 1; +- else +- carry2 = 0; +- +- return carry1 + carry2; +-} +- +-/* +- * add two numbers of the same size, return overflow +- * +- * add a to b, place result in ret; all arrays need to be n limbs long +- * return overflow from addition (0 or 1) +- */ +-static ossl_inline limb_t add(limb_t *ret, limb_t *a, limb_t *b, size_t n) +-{ +- limb_t c = 0; +- ossl_ssize_t i; +- +- for(i = n - 1; i > -1; i--) +- c = _add_limb(&ret[i], a[i], b[i], c); +- +- return c; +-} +- +-/* +- * return number of limbs necessary for temporary values +- * when multiplying numbers n limbs large +- */ +-static ossl_inline size_t mul_limb_numb(size_t n) +-{ +- return 2 * n * 2; +-} +- +-/* +- * multiply two numbers of the same size +- * +- * multiply a by b, place result in ret; a and b need to be n limbs long +- * ret needs to be 2*n limbs long, tmp needs to be mul_limb_numb(n) limbs +- * long +- */ +-static void limb_mul(limb_t *ret, limb_t *a, limb_t *b, size_t n, limb_t *tmp) +-{ +- limb_t *r_odd, *r_even; +- size_t i, j, k; +- +- r_odd = tmp; +- r_even = &tmp[2 * n]; +- +- memset(ret, 0, 2 * n * sizeof(limb_t)); +- +- for (i = 0; i < n; i++) { +- for (k = 0; k < i + n + 1; k++) { +- r_even[k] = 0; +- r_odd[k] = 0; +- } +- for (j = 0; j < n; j++) { +- /* +- * place results from even and odd limbs in separate arrays so that +- * we don't have to calculate overflow every time we get individual +- * limb multiplication result +- */ +- if (j % 2 == 0) +- _mul_limb(&r_even[i + j], &r_even[i + j + 1], a[i], b[j]); +- else +- _mul_limb(&r_odd[i + j], &r_odd[i + j + 1], a[i], b[j]); +- } +- /* +- * skip the least significant limbs when adding multiples of +- * more significant limbs (they're zero anyway) +- */ +- add(ret, ret, r_even, n + i + 1); +- add(ret, ret, r_odd, n + i + 1); +- } +-} +- +-/* modifies the value in place by performing a right shift by one bit */ +-static ossl_inline void rshift1(limb_t *val, size_t n) +-{ +- limb_t shift_in = 0, shift_out = 0; +- size_t i; +- +- for (i = 0; i < n; i++) { +- shift_out = val[i] & 1; +- val[i] = shift_in << (LIMB_BIT_SIZE - 1) | (val[i] >> 1); +- shift_in = shift_out; +- } +-} +- +-/* extend the LSB of flag to all bits of limb */ +-static ossl_inline limb_t mk_mask(limb_t flag) +-{ +- flag |= flag << 1; +- flag |= flag << 2; +- flag |= flag << 4; +- flag |= flag << 8; +- flag |= flag << 16; +-#if (LIMB_BYTE_SIZE == 8) +- flag |= flag << 32; +-#endif +- return flag; +-} +- +-/* +- * copy from either a or b to ret based on flag +- * when flag == 0, then copies from b +- * when flag == 1, then copies from a +- */ +-static ossl_inline void cselect(limb_t flag, limb_t *ret, limb_t *a, limb_t *b, size_t n) +-{ +- /* +- * would be more efficient with non volatile mask, but then gcc +- * generates code with jumps +- */ +- volatile limb_t mask; +- size_t i; +- +- mask = mk_mask(flag); +- for (i = 0; i < n; i++) { +-#if (LIMB_BYTE_SIZE == 8) +- ret[i] = constant_time_select_64(mask, a[i], b[i]); +-#else +- ret[i] = constant_time_select_32(mask, a[i], b[i]); +-#endif +- } +-} +- +-static limb_t _sub_limb(limb_t *ret, limb_t a, limb_t b, limb_t borrow) +-{ +- limb_t borrow1, borrow2, t; +- /* +- * while it doesn't look constant-time, this is idiomatic code +- * to tell compilers to use the carry bit from subtraction +- */ +- +- *ret = a - borrow; +- if (*ret > a) +- borrow1 = 1; +- else +- borrow1 = 0; +- +- t = *ret; +- *ret = t - b; +- if (*ret > t) +- borrow2 = 1; +- else +- borrow2 = 0; +- +- return borrow1 + borrow2; +-} +- +-/* +- * place the result of a - b into ret, return the borrow bit. +- * All arrays need to be n limbs long +- */ +-static limb_t sub(limb_t *ret, limb_t *a, limb_t *b, size_t n) +-{ +- limb_t borrow = 0; +- ossl_ssize_t i; +- +- for (i = n - 1; i > -1; i--) +- borrow = _sub_limb(&ret[i], a[i], b[i], borrow); +- +- return borrow; +-} +- +-/* return the number of limbs necessary to allocate for the mod() tmp operand */ +-static ossl_inline size_t mod_limb_numb(size_t anum, size_t modnum) +-{ +- return (anum + modnum) * 3; +-} +- +-/* +- * calculate a % mod, place the result in ret +- * size of a is defined by anum, size of ret and mod is modnum, +- * size of tmp is returned by mod_limb_numb() +- */ +-static void mod(limb_t *ret, limb_t *a, size_t anum, limb_t *mod, +- size_t modnum, limb_t *tmp) +-{ +- limb_t *atmp, *modtmp, *rettmp; +- limb_t res; +- size_t i; +- +- memset(tmp, 0, mod_limb_numb(anum, modnum) * LIMB_BYTE_SIZE); +- +- atmp = tmp; +- modtmp = &tmp[anum + modnum]; +- rettmp = &tmp[(anum + modnum) * 2]; +- +- for (i = modnum; i 0; i--, rp--) { +- v = _mul_add_limb(rp, mod, modnum, rp[modnum - 1] * ni0, tmp2); +- v = v + carry + rp[-1]; +- carry |= (v != rp[-1]); +- carry &= (v <= rp[-1]); +- rp[-1] = v; +- } +- +- /* perform the final reduction by mod... */ +- carry -= sub(ret, rp, mod, modnum); +- +- /* ...conditionally */ +- cselect(carry, ret, rp, ret, modnum); +-} +- +-/* allocated buffer should be freed afterwards */ +-static void BN_to_limb(const BIGNUM *bn, limb_t *buf, size_t limbs) +-{ +- int i; +- int real_limbs = (BN_num_bytes(bn) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; +- limb_t *ptr = buf + (limbs - real_limbs); +- +- for (i = 0; i < real_limbs; i++) +- ptr[i] = bn->d[real_limbs - i - 1]; +-} +- +-#if LIMB_BYTE_SIZE == 8 +-static ossl_inline uint64_t be64(uint64_t host) +-{ +- const union { +- long one; +- char little; +- } is_endian = { 1 }; +- +- if (is_endian.little) { +- uint64_t big = 0; +- +- big |= (host & 0xff00000000000000) >> 56; +- big |= (host & 0x00ff000000000000) >> 40; +- big |= (host & 0x0000ff0000000000) >> 24; +- big |= (host & 0x000000ff00000000) >> 8; +- big |= (host & 0x00000000ff000000) << 8; +- big |= (host & 0x0000000000ff0000) << 24; +- big |= (host & 0x000000000000ff00) << 40; +- big |= (host & 0x00000000000000ff) << 56; +- return big; +- } else { +- return host; +- } +-} +- +-#else +-/* Not all platforms have htobe32(). */ +-static ossl_inline uint32_t be32(uint32_t host) +-{ +- const union { +- long one; +- char little; +- } is_endian = { 1 }; +- +- if (is_endian.little) { +- uint32_t big = 0; +- +- big |= (host & 0xff000000) >> 24; +- big |= (host & 0x00ff0000) >> 8; +- big |= (host & 0x0000ff00) << 8; +- big |= (host & 0x000000ff) << 24; +- return big; +- } else { +- return host; +- } +-} +-#endif +- +-/* +- * We assume that intermediate, possible_arg2, blinding, and ctx are used +- * similar to BN_BLINDING_invert_ex() arguments. +- * to_mod is RSA modulus. +- * buf and num is the serialization buffer and its length. +- * +- * Here we use classic/Montgomery multiplication and modulo. After the calculation finished +- * we serialize the new structure instead of BIGNUMs taking endianness into account. +- */ +-int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate, +- const BN_BLINDING *blinding, +- const BIGNUM *possible_arg2, +- const BIGNUM *to_mod, BN_CTX *ctx, +- unsigned char *buf, int num) +-{ +- limb_t *l_im = NULL, *l_mul = NULL, *l_mod = NULL; +- limb_t *l_ret = NULL, *l_tmp = NULL, l_buf; +- size_t l_im_count = 0, l_mul_count = 0, l_size = 0, l_mod_count = 0; +- size_t l_tmp_count = 0; +- int ret = 0; +- size_t i; +- unsigned char *tmp; +- const BIGNUM *arg1 = intermediate; +- const BIGNUM *arg2 = (possible_arg2 == NULL) ? blinding->Ai : possible_arg2; +- +- l_im_count = (BN_num_bytes(arg1) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; +- l_mul_count = (BN_num_bytes(arg2) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; +- l_mod_count = (BN_num_bytes(to_mod) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; +- +- l_size = l_im_count > l_mul_count ? l_im_count : l_mul_count; +- l_im = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE); +- l_mul = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE); +- l_mod = OPENSSL_zalloc(l_mod_count * LIMB_BYTE_SIZE); +- +- if ((l_im == NULL) || (l_mul == NULL) || (l_mod == NULL)) +- goto err; +- +- BN_to_limb(arg1, l_im, l_size); +- BN_to_limb(arg2, l_mul, l_size); +- BN_to_limb(to_mod, l_mod, l_mod_count); +- +- l_ret = OPENSSL_malloc(2 * l_size * LIMB_BYTE_SIZE); +- +- if (blinding->m_ctx != NULL) { +- l_tmp_count = mul_limb_numb(l_size) > mod_montgomery_limb_numb(l_mod_count) ? +- mul_limb_numb(l_size) : mod_montgomery_limb_numb(l_mod_count); +- l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE); +- } else { +- l_tmp_count = mul_limb_numb(l_size) > mod_limb_numb(2 * l_size, l_mod_count) ? +- mul_limb_numb(l_size) : mod_limb_numb(2 * l_size, l_mod_count); +- l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE); +- } +- +- if ((l_ret == NULL) || (l_tmp == NULL)) +- goto err; +- +- if (blinding->m_ctx != NULL) { +- limb_mul(l_ret, l_im, l_mul, l_size, l_tmp); +- mod_montgomery(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, +- blinding->m_ctx->n0[0], l_tmp); +- } else { +- limb_mul(l_ret, l_im, l_mul, l_size, l_tmp); +- mod(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, l_tmp); +- } +- +- /* modulus size in bytes can be equal to num but after limbs conversion it becomes bigger */ +- if (num < BN_num_bytes(to_mod)) { +- BNerr(BN_F_OSSL_BN_RSA_DO_UNBLIND, ERR_R_PASSED_INVALID_ARGUMENT); +- goto err; +- } +- +- memset(buf, 0, num); +- tmp = buf + num - BN_num_bytes(to_mod); +- for (i = 0; i < l_mod_count; i++) { +-#if LIMB_BYTE_SIZE == 8 +- l_buf = be64(l_ret[i]); +-#else +- l_buf = be32(l_ret[i]); +-#endif +- if (i == 0) { +- int delta = LIMB_BYTE_SIZE - ((l_mod_count * LIMB_BYTE_SIZE) - num); +- +- memcpy(tmp, ((char *)&l_buf) + LIMB_BYTE_SIZE - delta, delta); +- tmp += delta; +- } else { +- memcpy(tmp, &l_buf, LIMB_BYTE_SIZE); +- tmp += LIMB_BYTE_SIZE; +- } +- } +- ret = num; +- +- err: +- OPENSSL_free(l_im); +- OPENSSL_free(l_mul); +- OPENSSL_free(l_mod); +- OPENSSL_free(l_tmp); +- OPENSSL_free(l_ret); +- +- return ret; +-} +diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt +index e0f0ab7c76f8..902e97b84355 100644 +--- a/crypto/err/openssl.txt ++++ b/crypto/err/openssl.txt +@@ -1,4 +1,4 @@ +-# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. ++# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + # + # Licensed under the OpenSSL license (the "License"). You may not use + # this file except in compliance with the License. You can obtain a copy +@@ -232,7 +232,6 @@ BN_F_BN_RSHIFT:146:BN_rshift + BN_F_BN_SET_WORDS:144:bn_set_words + BN_F_BN_STACK_PUSH:148:BN_STACK_push + BN_F_BN_USUB:115:BN_usub +-BN_F_OSSL_BN_RSA_DO_UNBLIND:151:ossl_bn_rsa_do_unblind + BUF_F_BUF_MEM_GROW:100:BUF_MEM_grow + BUF_F_BUF_MEM_GROW_CLEAN:105:BUF_MEM_grow_clean + BUF_F_BUF_MEM_NEW:101:BUF_MEM_new +diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c +index 6c3c0cf78d30..b52a66f6a628 100644 +--- a/crypto/rsa/rsa_ossl.c ++++ b/crypto/rsa/rsa_ossl.c +@@ -465,20 +465,11 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + BN_free(d); + } + +- if (blinding) { +- /* +- * ossl_bn_rsa_do_unblind() combines blinding inversion and +- * 0-padded BN BE serialization +- */ +- j = ossl_bn_rsa_do_unblind(ret, blinding, unblind, rsa->n, ctx, +- buf, num); +- if (j == 0) ++ if (blinding) ++ if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) + goto err; +- } else { +- j = BN_bn2binpad(ret, buf, num); +- if (j < 0) +- goto err; +- } ++ ++ j = BN_bn2binpad(ret, buf, num); + + switch (padding) { + case RSA_PKCS1_PADDING: +diff --git a/include/crypto/bn.h b/include/crypto/bn.h +index b5f36fb25aa2..60afda1dadee 100644 +--- a/include/crypto/bn.h ++++ b/include/crypto/bn.h +@@ -86,10 +86,5 @@ int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n); + int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n); + int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + const BIGNUM *d, BN_CTX *ctx); +-int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate, +- const BN_BLINDING *blinding, +- const BIGNUM *possible_arg2, +- const BIGNUM *to_mod, BN_CTX *ctx, +- unsigned char *buf, int num); + + #endif +diff --git a/include/openssl/bnerr.h b/include/openssl/bnerr.h +index a0752cea52d7..9f3c7cfaab67 100644 +--- a/include/openssl/bnerr.h ++++ b/include/openssl/bnerr.h +@@ -72,7 +72,6 @@ int ERR_load_BN_strings(void); + # define BN_F_BN_SET_WORDS 144 + # define BN_F_BN_STACK_PUSH 148 + # define BN_F_BN_USUB 115 +-# define BN_F_OSSL_BN_RSA_DO_UNBLIND 151 + + /* + * BN reason codes. diff -Nru openssl-1.1.1n/debian/patches/series openssl-1.1.1n/debian/patches/series --- openssl-1.1.1n/debian/patches/series 2023-02-05 21:23:17.000000000 +0000 +++ openssl-1.1.1n/debian/patches/series 2023-05-26 21:30:44.000000000 +0000 @@ -17,3 +17,12 @@ Fix-Timing-Oracle-in-RSA-decryption.patch Fix-AES-OCB-encrypt-decrypt-for-x86-AES-NI.patch AES-OCB-test-vectors.patch +x509-excessive-resource-use-verifying-policy-constraints.patch +Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in-leaf.patch +Generate-some-certificates-with-the-certificatePolicies-e.patch +Add-a-Certificate-Policies-Test.patch +Fix-documentation-of-X509_VERIFY_PARAM_add0_policy.patch +Revert-Fix-Timing-Oracle-in-RSA-decryption.patch +Alternative-fix-for-CVE-2022-4304.patch +Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorrectly-.patch +Restrict-the-size-of-OBJECT-IDENTIFIERs-that-OBJ_obj2txt-.patch diff -Nru openssl-1.1.1n/debian/patches/x509-excessive-resource-use-verifying-policy-constraints.patch openssl-1.1.1n/debian/patches/x509-excessive-resource-use-verifying-policy-constraints.patch --- openssl-1.1.1n/debian/patches/x509-excessive-resource-use-verifying-policy-constraints.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.1.1n/debian/patches/x509-excessive-resource-use-verifying-policy-constraints.patch 2023-05-26 21:28:42.000000000 +0000 @@ -0,0 +1,218 @@ +From: Pauli +Date: Wed, 8 Mar 2023 15:28:20 +1100 +Subject: x509: excessive resource use verifying policy constraints + +A security vulnerability has been identified in all supported versions +of OpenSSL related to the verification of X.509 certificate chains +that include policy constraints. Attackers may be able to exploit this +vulnerability by creating a malicious certificate chain that triggers +exponential use of computational resources, leading to a denial-of-service +(DoS) attack on affected systems. + +Fixes CVE-2023-0464 + +Reviewed-by: Tomas Mraz +Reviewed-by: Shane Lontis +(Merged from https://github.com/openssl/openssl/pull/20569) +--- + crypto/x509v3/pcy_local.h | 8 +++++++- + crypto/x509v3/pcy_node.c | 12 +++++++++--- + crypto/x509v3/pcy_tree.c | 37 +++++++++++++++++++++++++++---------- + 3 files changed, 43 insertions(+), 14 deletions(-) + +diff --git a/crypto/x509v3/pcy_local.h b/crypto/x509v3/pcy_local.h +index 5daf78de4585..344aa067659c 100644 +--- a/crypto/x509v3/pcy_local.h ++++ b/crypto/x509v3/pcy_local.h +@@ -111,6 +111,11 @@ struct X509_POLICY_LEVEL_st { + }; + + struct X509_POLICY_TREE_st { ++ /* The number of nodes in the tree */ ++ size_t node_count; ++ /* The maximum number of nodes in the tree */ ++ size_t node_maximum; ++ + /* This is the tree 'level' data */ + X509_POLICY_LEVEL *levels; + int nlevel; +@@ -159,7 +164,8 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk, + X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, +- X509_POLICY_TREE *tree); ++ X509_POLICY_TREE *tree, ++ int extra_data); + void policy_node_free(X509_POLICY_NODE *node); + int policy_node_match(const X509_POLICY_LEVEL *lvl, + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid); +diff --git a/crypto/x509v3/pcy_node.c b/crypto/x509v3/pcy_node.c +index e2d7b1532236..d574fb9d665d 100644 +--- a/crypto/x509v3/pcy_node.c ++++ b/crypto/x509v3/pcy_node.c +@@ -59,10 +59,15 @@ X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, +- X509_POLICY_TREE *tree) ++ X509_POLICY_TREE *tree, ++ int extra_data) + { + X509_POLICY_NODE *node; + ++ /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */ ++ if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum) ++ return NULL; ++ + node = OPENSSL_zalloc(sizeof(*node)); + if (node == NULL) { + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); +@@ -70,7 +75,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + } + node->data = data; + node->parent = parent; +- if (level) { ++ if (level != NULL) { + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (level->anyPolicy) + goto node_error; +@@ -90,7 +95,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + } + } + +- if (tree) { ++ if (extra_data) { + if (tree->extra_data == NULL) + tree->extra_data = sk_X509_POLICY_DATA_new_null(); + if (tree->extra_data == NULL){ +@@ -103,6 +108,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + } + } + ++ tree->node_count++; + if (parent) + parent->nchild++; + +diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c +index 6e8322cbc5e3..6c7fd3540500 100644 +--- a/crypto/x509v3/pcy_tree.c ++++ b/crypto/x509v3/pcy_tree.c +@@ -13,6 +13,18 @@ + + #include "pcy_local.h" + ++/* ++ * If the maximum number of nodes in the policy tree isn't defined, set it to ++ * a generous default of 1000 nodes. ++ * ++ * Defining this to be zero means unlimited policy tree growth which opens the ++ * door on CVE-2023-0464. ++ */ ++ ++#ifndef OPENSSL_POLICY_TREE_NODES_MAX ++# define OPENSSL_POLICY_TREE_NODES_MAX 1000 ++#endif ++ + /* + * Enable this to print out the complete policy tree at various point during + * evaluation. +@@ -168,6 +180,9 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + return X509_PCY_TREE_INTERNAL; + } + ++ /* Limit the growth of the tree to mitigate CVE-2023-0464 */ ++ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX; ++ + /* + * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3. + * +@@ -184,7 +199,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + level = tree->levels; + if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL) + goto bad_tree; +- if (level_add_node(level, data, NULL, tree) == NULL) { ++ if (level_add_node(level, data, NULL, tree, 1) == NULL) { + policy_data_free(data); + goto bad_tree; + } +@@ -243,7 +258,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + * Return value: 1 on success, 0 otherwise + */ + static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, +- X509_POLICY_DATA *data) ++ X509_POLICY_DATA *data, ++ X509_POLICY_TREE *tree) + { + X509_POLICY_LEVEL *last = curr - 1; + int i, matched = 0; +@@ -253,13 +269,13 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, + X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i); + + if (policy_node_match(last, node, data->valid_policy)) { +- if (level_add_node(curr, data, node, NULL) == NULL) ++ if (level_add_node(curr, data, node, tree, 0) == NULL) + return 0; + matched = 1; + } + } + if (!matched && last->anyPolicy) { +- if (level_add_node(curr, data, last->anyPolicy, NULL) == NULL) ++ if (level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL) + return 0; + } + return 1; +@@ -272,7 +288,8 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, + * Return value: 1 on success, 0 otherwise. + */ + static int tree_link_nodes(X509_POLICY_LEVEL *curr, +- const X509_POLICY_CACHE *cache) ++ const X509_POLICY_CACHE *cache, ++ X509_POLICY_TREE *tree) + { + int i; + +@@ -280,7 +297,7 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, + X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i); + + /* Look for matching nodes in previous level */ +- if (!tree_link_matching_nodes(curr, data)) ++ if (!tree_link_matching_nodes(curr, data, tree)) + return 0; + } + return 1; +@@ -311,7 +328,7 @@ static int tree_add_unmatched(X509_POLICY_LEVEL *curr, + /* Curr may not have anyPolicy */ + data->qualifier_set = cache->anyPolicy->qualifier_set; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; +- if (level_add_node(curr, data, node, tree) == NULL) { ++ if (level_add_node(curr, data, node, tree, 1) == NULL) { + policy_data_free(data); + return 0; + } +@@ -373,7 +390,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, + } + /* Finally add link to anyPolicy */ + if (last->anyPolicy && +- level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL) == NULL) ++ level_add_node(curr, cache->anyPolicy, last->anyPolicy, tree, 0) == NULL) + return 0; + return 1; + } +@@ -555,7 +572,7 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree, + extra->qualifier_set = anyPolicy->data->qualifier_set; + extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS + | POLICY_DATA_FLAG_EXTRA_NODE; +- node = level_add_node(NULL, extra, anyPolicy->parent, tree); ++ node = level_add_node(NULL, extra, anyPolicy->parent, tree, 1); + } + if (!tree->user_policies) { + tree->user_policies = sk_X509_POLICY_NODE_new_null(); +@@ -582,7 +599,7 @@ static int tree_evaluate(X509_POLICY_TREE *tree) + + for (i = 1; i < tree->nlevel; i++, curr++) { + cache = policy_cache_set(curr->cert); +- if (!tree_link_nodes(curr, cache)) ++ if (!tree_link_nodes(curr, cache, tree)) + return X509_PCY_TREE_INTERNAL; + + if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)