Test requireAnyPolicy being a SkipCerts value And specifically that it also counts at the leaf, which was a bug I'd nearly introduced. (RFC 5280 is written somewhat confusingly. The wrap-up and prepare procedures have some duplicate processing.) Change-Id: Iea901b96f64e12199fec426dc936bfbde16f88a4 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/56035 Reviewed-by: Bob Beck <bbe@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index a1005d7..eb26611 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc
@@ -5143,6 +5143,14 @@ bssl::UniquePtr<X509> intermediate_require(CertFromPEM( GetTestData("crypto/x509/test/policy_intermediate_require.pem").c_str())); ASSERT_TRUE(intermediate_require); + bssl::UniquePtr<X509> intermediate_require1(CertFromPEM( + GetTestData("crypto/x509/test/policy_intermediate_require1.pem") + .c_str())); + ASSERT_TRUE(intermediate_require1); + bssl::UniquePtr<X509> intermediate_require2(CertFromPEM( + GetTestData("crypto/x509/test/policy_intermediate_require2.pem") + .c_str())); + ASSERT_TRUE(intermediate_require2); bssl::UniquePtr<X509> intermediate_require_duplicate(CertFromPEM( GetTestData("crypto/x509/test/policy_intermediate_require_duplicate.pem") .c_str())); @@ -5179,6 +5187,12 @@ bssl::UniquePtr<X509> leaf_oid5(CertFromPEM( GetTestData("crypto/x509/test/policy_leaf_oid5.pem").c_str())); ASSERT_TRUE(leaf_oid5); + bssl::UniquePtr<X509> leaf_require(CertFromPEM( + GetTestData("crypto/x509/test/policy_leaf_require.pem").c_str())); + ASSERT_TRUE(leaf_require); + bssl::UniquePtr<X509> leaf_require1(CertFromPEM( + GetTestData("crypto/x509/test/policy_leaf_require1.pem").c_str())); + ASSERT_TRUE(leaf_require1); // By default, OpenSSL does not check policies, so even syntax errors in the // certificatePolicies extension go unnoticed. (This is probably not @@ -5286,6 +5300,57 @@ set_policies(param, {oid3.get()}); })); + // A leaf can also set requireExplicitPolicy. + EXPECT_EQ(X509_V_OK, Verify(leaf_require.get(), {root.get()}, + {intermediate.get()}, /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid1.get()}); + })); + EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY, + Verify(leaf_require.get(), {root.get()}, {intermediate.get()}, + /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); + + // requireExplicitPolicy is a count of certificates to skip. If the value is + // not zero by the end of the chain, it doesn't count. + EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY, + Verify(leaf.get(), {root.get()}, {intermediate_require1.get()}, + /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); + EXPECT_EQ(X509_V_OK, + Verify(leaf.get(), {root.get()}, {intermediate_require2.get()}, + /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); + EXPECT_EQ(X509_V_OK, + Verify(leaf_require1.get(), {root.get()}, {intermediate.get()}, + /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); + + // If multiple certificates specify the constraint, the more constrained value + // wins. + EXPECT_EQ( + X509_V_ERR_NO_EXPLICIT_POLICY, + Verify(leaf_require1.get(), {root.get()}, {intermediate_require1.get()}, + /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); + EXPECT_EQ( + X509_V_ERR_NO_EXPLICIT_POLICY, + Verify(leaf_require.get(), {root.get()}, {intermediate_require2.get()}, + /*crls=*/{}, + /*flags=*/0, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); + // An intermediate that requires an explicit policy, but then specifies no // policies should fail verification as a result. EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY, @@ -5306,16 +5371,18 @@ // The leaf asserts anyPolicy, but the intermediate does not. The resulting // valid policies are the intersection. - EXPECT_EQ(X509_V_OK, - Verify(leaf_any.get(), {root.get()}, {intermediate.get()}, /*crls=*/{}, - X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) { - set_policies(param, {oid1.get()}); - })); - EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY, - Verify(leaf_any.get(), {root.get()}, {intermediate.get()}, /*crls=*/{}, - X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) { - set_policies(param, {oid3.get()}); - })); + EXPECT_EQ( + X509_V_OK, + Verify(leaf_any.get(), {root.get()}, {intermediate.get()}, /*crls=*/{}, + X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid1.get()}); + })); + EXPECT_EQ( + X509_V_ERR_NO_EXPLICIT_POLICY, + Verify(leaf_any.get(), {root.get()}, {intermediate.get()}, /*crls=*/{}, + X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) { + set_policies(param, {oid3.get()}); + })); // The intermediate asserts anyPolicy, but the leaf does not. The resulting // valid policies are the intersection.