Fix handling of EXFLAG_INVALID_POLICY on the leaf.

X509_policy_check returns -1 if some certificate had an unparseable
extension, in which case it sets EXFLAG_INVALID_POLICY on it. The
calling code then iterates over the certificates to find the offending
one, so the callback has a chance to undo it. But it skips i = 0, the
leaf, and instead just silentely returns success.

We really should cut down on the callback's ability to mess things up
here but, in the meantime, fix this. Also add a test covering this case.

While I'm here, I've updated make_invalid_extensions.go, which I pulled
some code from, to rename fooOrPanic to mustFoo. That seems to be the
convention in the Go standard library. (regexp.MustCompile, etc.)

Change-Id: Ib07c9f4175e66483bd7c0f7d49aea931bf36e53f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/55748
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
fips-20230428
David Benjamin 2 years ago committed by Boringssl LUCI CQ
parent 97dd962a20
commit d1b20a9580
  1. 24
      crypto/x509/test/make_invalid_extensions.go
  2. 174
      crypto/x509/test/make_policy_certs.go
  3. 11
      crypto/x509/test/policy_intermediate.pem
  4. 11
      crypto/x509/test/policy_intermediate_invalid.pem
  5. 11
      crypto/x509/test/policy_leaf.pem
  6. 11
      crypto/x509/test/policy_leaf_invalid.pem
  7. 10
      crypto/x509/test/policy_root.pem
  8. 90
      crypto/x509/x509_test.cc
  9. 6
      crypto/x509/x509_vfy.c
  10. 5
      sources.cmake

@ -49,9 +49,9 @@ var extensions = []extension{
var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
func init() {
leafKey = ecdsaKeyFromPEMOrPanic(leafKeyPEM)
intermediateKey = ecdsaKeyFromPEMOrPanic(intermediateKeyPEM)
rootKey = ecdsaKeyFromPEMOrPanic(rootKeyPEM)
leafKey = mustParseECDSAKey(leafKeyPEM)
intermediateKey = mustParseECDSAKey(intermediateKeyPEM)
rootKey = mustParseECDSAKey(rootKeyPEM)
}
type templateAndKey struct {
@ -59,7 +59,7 @@ type templateAndKey struct {
key *ecdsa.PrivateKey
}
func generateCertificateOrPanic(path string, subject, issuer *templateAndKey) []byte {
func mustGenerateCertificate(path string, subject, issuer *templateAndKey) []byte {
cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
if err != nil {
panic(err)
@ -135,9 +135,9 @@ func main() {
}
// Generate a valid certificate chain from the templates.
generateCertificateOrPanic("invalid_extension_root.pem", &root, &root)
generateCertificateOrPanic("invalid_extension_intermediate.pem", &intermediate, &root)
leafDER := generateCertificateOrPanic("invalid_extension_leaf.pem", &leaf, &intermediate)
mustGenerateCertificate("invalid_extension_root.pem", &root, &root)
mustGenerateCertificate("invalid_extension_intermediate.pem", &intermediate, &root)
leafDER := mustGenerateCertificate("invalid_extension_leaf.pem", &leaf, &intermediate)
leafCert, err := x509.ParseCertificate(leafDER)
if err != nil {
@ -151,15 +151,15 @@ func main() {
rootInvalid := root
rootInvalid.template.ExtraExtensions = invalidExtension
generateCertificateOrPanic(fmt.Sprintf("invalid_extension_root_%s.pem", ext.name), &rootInvalid, &rootInvalid)
mustGenerateCertificate(fmt.Sprintf("invalid_extension_root_%s.pem", ext.name), &rootInvalid, &rootInvalid)
intermediateInvalid := intermediate
intermediateInvalid.template.ExtraExtensions = invalidExtension
generateCertificateOrPanic(fmt.Sprintf("invalid_extension_intermediate_%s.pem", ext.name), &intermediateInvalid, &root)
mustGenerateCertificate(fmt.Sprintf("invalid_extension_intermediate_%s.pem", ext.name), &intermediateInvalid, &root)
leafInvalid := leaf
leafInvalid.template.ExtraExtensions = invalidExtension
generateCertificateOrPanic(fmt.Sprintf("invalid_extension_leaf_%s.pem", ext.name), &leafInvalid, &intermediate)
mustGenerateCertificate(fmt.Sprintf("invalid_extension_leaf_%s.pem", ext.name), &leafInvalid, &intermediate)
// Additionally generate a copy of the leaf certificate with extra data in
// the extension.
@ -177,7 +177,7 @@ func main() {
leafTrailingData := leaf
leafTrailingData.template.ExtraExtensions = trailingDataExtension
generateCertificateOrPanic(fmt.Sprintf("trailing_data_leaf_%s.pem", ext.name), &leafTrailingData, &intermediate)
mustGenerateCertificate(fmt.Sprintf("trailing_data_leaf_%s.pem", ext.name), &leafTrailingData, &intermediate)
}
}
@ -199,7 +199,7 @@ Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
-----END PRIVATE KEY-----`
func ecdsaKeyFromPEMOrPanic(in string) *ecdsa.PrivateKey {
func mustParseECDSAKey(in string) *ecdsa.PrivateKey {
keyBlock, _ := pem.Decode([]byte(in))
if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
panic("could not decode private key")

@ -0,0 +1,174 @@
/* Copyright (c) 2020, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
// make_policy_certs.go generates certificates for testing policy handling.
package main
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"math/big"
"os"
"time"
)
var (
// https://davidben.net/oid
testOID1 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 1})
testOID2 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 2})
// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.2.1.4
certificatePoliciesOID = asn1.ObjectIdentifier([]int{2, 5, 29, 32})
)
var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
func init() {
leafKey = mustParseECDSAKey(leafKeyPEM)
intermediateKey = mustParseECDSAKey(intermediateKeyPEM)
rootKey = mustParseECDSAKey(rootKeyPEM)
}
type templateAndKey struct {
template x509.Certificate
key *ecdsa.PrivateKey
}
func mustGenerateCertificate(path string, subject, issuer *templateAndKey) []byte {
cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
if err != nil {
panic(err)
}
file, err := os.Create(path)
if err != nil {
panic(err)
}
defer file.Close()
err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
if err != nil {
panic(err)
}
return cert
}
func main() {
notBefore, err := time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
if err != nil {
panic(err)
}
notAfter, err := time.Parse(time.RFC3339, "2100-01-01T00:00:00Z")
if err != nil {
panic(err)
}
root := templateAndKey{
template: x509.Certificate{
SerialNumber: new(big.Int).SetInt64(1),
Subject: pkix.Name{CommonName: "Policy Root"},
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign,
SignatureAlgorithm: x509.ECDSAWithSHA256,
},
key: rootKey,
}
intermediate := templateAndKey{
template: x509.Certificate{
SerialNumber: new(big.Int).SetInt64(2),
Subject: pkix.Name{CommonName: "Policy Intermediate"},
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign,
SignatureAlgorithm: x509.ECDSAWithSHA256,
PolicyIdentifiers: []asn1.ObjectIdentifier{testOID1, testOID2},
},
key: intermediateKey,
}
leaf := templateAndKey{
template: x509.Certificate{
SerialNumber: new(big.Int).SetInt64(3),
Subject: pkix.Name{CommonName: "www.example.com"},
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
IsCA: false,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign,
SignatureAlgorithm: x509.ECDSAWithSHA256,
DNSNames: []string{"www.example.com"},
PolicyIdentifiers: []asn1.ObjectIdentifier{testOID1, testOID2},
},
key: leafKey,
}
// Generate a valid certificate chain from the templates.
mustGenerateCertificate("policy_root.pem", &root, &root)
mustGenerateCertificate("policy_intermediate.pem", &intermediate, &root)
mustGenerateCertificate("policy_leaf.pem", &leaf, &intermediate)
// Introduce syntax errors in the leaf and intermediate.
leafInvalid := leaf
leafInvalid.template.PolicyIdentifiers = nil
leafInvalid.template.ExtraExtensions = []pkix.Extension{{Id: certificatePoliciesOID, Value: []byte("INVALID")}}
mustGenerateCertificate("policy_leaf_invalid.pem", &leafInvalid, &root)
intermediateInvalid := intermediate
intermediateInvalid.template.PolicyIdentifiers = nil
intermediateInvalid.template.ExtraExtensions = []pkix.Extension{{Id: certificatePoliciesOID, Value: []byte("INVALID")}}
mustGenerateCertificate("policy_intermediate_invalid.pem", &intermediateInvalid, &root)
// TODO(davidben): Generate more certificates to test policy validation more
// extensively, including an intermediate with constraints. For now this
// just tests the basic case.
}
const leafKeyPEM = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
-----END PRIVATE KEY-----`
const intermediateKeyPEM = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6
vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE
Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw
-----END PRIVATE KEY-----`
const rootKeyPEM = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J
Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
-----END PRIVATE KEY-----`
func mustParseECDSAKey(in string) *ecdsa.PrivateKey {
keyBlock, _ := pem.Decode([]byte(in))
if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
panic("could not decode private key")
}
key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
if err != nil {
panic(err)
}
return key.(*ecdsa.PrivateKey)
}

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBrDCCAVGgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE
AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia
jQ6Dg7CTpVZVVH+bguT7JTCjgYUwgYIwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM
MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr
CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG
9xIEAYS3CQICMAoGCCqGSM49BAMCA0kAMEYCIQCcgAbQr/HNdHwPEcWotOqtXXGH
di6cAJtWaSynP8+UoQIhAPEMK79OO+tJHzmD0N01OdZefAwKlYZvDCQvAfAQVf7j
-----END CERTIFICATE-----

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBjDCCATKgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE
AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia
jQ6Dg7CTpVZVVH+bguT7JTCjZzBlMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE
YcLF6z1QWoBtrjAOBgNVHSAEB0lOVkFMSUQwCgYIKoZIzj0EAwIDSAAwRQIgf9Jt
wpHxfA3j6Z8+h88MSh2MHkDGhWcnRY9VboMR/RoCIQDiSiaPGISK/31JBhNVvNnK
IBo822QHPPMWDR/K/nyWiA==
-----END CERTIFICATE-----

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBpjCCAU2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg
SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa
MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB
BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR
qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo34wfDAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh
bXBsZS5jb20wKwYDVR0gBCQwIjAPBg0qhkiG9xIEAYS3CQIBMA8GDSqGSIb3EgQB
hLcJAgIwCgYIKoZIzj0EAwIDRwAwRAIgPTm7NO8gR+z8BqA6gV9FVwrSmOAJVzyu
5loq9ZTtIS0CIEjBbvBcY4+Y3xWL4SUFQKQk3pNZ37xJoz2v+/yvEE5/
-----END CERTIFICATE-----

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBgjCCASigAwIBAgIBAzAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowGjEYMBYGA1UE
AxMPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkSrY
vFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1SERGnEaiNLpoc0dle
TS8wQT/cjw/wPgoeV6NhMF8wDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQMMAoGCCsG
AQUFBwMBMAwGA1UdEwEB/wQCMAAwGgYDVR0RBBMwEYIPd3d3LmV4YW1wbGUuY29t
MA4GA1UdIAQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiBhnGGMJBM2gTBo9r4C
NDR89ECTU7dwdvFyOGOIOOZEFgIhAIRIhGdQ9eRRi2qMhN1F19P5VsIUuc4VL1bW
sXO8fwZM
-----END CERTIFICATE-----

@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBdDCCARqgAwIBAgIBATAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowFjEUMBIGA1UE
AxMLUG9saWN5IFJvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQmdqXYl1Gv
Y7y3jcTTK6MVXIQr44TqChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAP
EPSJwPndjolto1cwVTAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUH
AwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU0GnnoB+yeN63WMthnh6Uh1HH
dRIwCgYIKoZIzj0EAwIDSAAwRQIgctaVgroxlAkLhPEaTXvsE3ePYM2X+KGOJZXc
usyO3YkCIQDN1RLJq9vHGjZzDCEehKjxHsV+XSAkdfU7nB7KjVHTKA==
-----END CERTIFICATE-----

@ -5094,3 +5094,93 @@ TEST(X509Test, SetSerialNumberChecksASN1StringType) {
ASSERT_TRUE(ASN1_INTEGER_get_int64(&val, X509_get0_serialNumber(root.get())));
EXPECT_EQ(-1, val);
}
TEST(X509Test, Policy) {
bssl::UniquePtr<ASN1_OBJECT> oid1(
OBJ_txt2obj("1.2.840.113554.4.1.72585.2.1", /*dont_search_names=*/1));
ASSERT_TRUE(oid1);
bssl::UniquePtr<ASN1_OBJECT> oid2(
OBJ_txt2obj("1.2.840.113554.4.1.72585.2.2", /*dont_search_names=*/1));
ASSERT_TRUE(oid2);
bssl::UniquePtr<ASN1_OBJECT> oid3(
OBJ_txt2obj("1.2.840.113554.4.1.72585.2.3", /*dont_search_names=*/1));
ASSERT_TRUE(oid3);
bssl::UniquePtr<X509> root(
CertFromPEM(GetTestData("crypto/x509/test/policy_root.pem").c_str()));
ASSERT_TRUE(root);
bssl::UniquePtr<X509> intermediate(CertFromPEM(
GetTestData("crypto/x509/test/policy_intermediate.pem").c_str()));
ASSERT_TRUE(intermediate);
bssl::UniquePtr<X509> intermediate_invalid(CertFromPEM(
GetTestData("crypto/x509/test/policy_intermediate_invalid.pem").c_str()));
ASSERT_TRUE(intermediate_invalid);
bssl::UniquePtr<X509> leaf(
CertFromPEM(GetTestData("crypto/x509/test/policy_leaf.pem").c_str()));
ASSERT_TRUE(leaf);
bssl::UniquePtr<X509> leaf_invalid(CertFromPEM(
GetTestData("crypto/x509/test/policy_leaf_invalid.pem").c_str()));
ASSERT_TRUE(leaf_invalid);
// By default, OpenSSL does not check policies, so even syntax errors in the
// certificatePolicies extension go unnoticed. (This is probably not
// important.)
EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()},
{intermediate.get()}, /*crls=*/{}));
EXPECT_EQ(X509_V_OK, Verify(leaf_invalid.get(), {root.get()},
{intermediate.get()}, /*crls=*/{}));
auto set_policies = [](X509_VERIFY_PARAM *param,
std::vector<const ASN1_OBJECT *> oids) {
for (const ASN1_OBJECT *oid : oids) {
bssl::UniquePtr<ASN1_OBJECT> copy(OBJ_dup(oid));
ASSERT_TRUE(copy);
ASSERT_TRUE(X509_VERIFY_PARAM_add0_policy(param, copy.get()));
copy.release(); // |X509_VERIFY_PARAM_add0_policy| takes ownership on
// success.
}
};
// The chain is good for |oid1| and |oid2|, but not |oid3|.
EXPECT_EQ(X509_V_OK,
Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
set_policies(param, {oid1.get()});
}));
EXPECT_EQ(X509_V_OK,
Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
set_policies(param, {oid2.get()});
}));
EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY,
Verify(leaf.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.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
set_policies(param, {oid1.get(), oid2.get()});
}));
EXPECT_EQ(X509_V_OK,
Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
set_policies(param, {oid1.get(), oid3.get()});
}));
// The policy extension in the intermediate cannot be parsed.
EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
Verify(leaf.get(), {root.get()}, {intermediate_invalid.get()},
/*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
[&](X509_VERIFY_PARAM *param) {
set_policies(param, {oid1.get()});
}));
// The policy extension in the leaf cannot be parsed.
EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
Verify(leaf_invalid.get(), {root.get()}, {intermediate.get()},
/*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
[&](X509_VERIFY_PARAM *param) {
set_policies(param, {oid1.get()});
}));
}

@ -1706,10 +1706,8 @@ static int check_policy(X509_STORE_CTX *ctx) {
// Invalid or inconsistent extensions
if (ret == -1) {
// Locate certificates with bad extensions and notify callback.
X509 *x;
size_t i;
for (i = 1; i < sk_X509_num(ctx->chain); i++) {
x = sk_X509_value(ctx->chain, i);
for (size_t 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;
}

@ -111,6 +111,11 @@ set(
crypto/x509/test/many_names1.pem
crypto/x509/test/many_names2.pem
crypto/x509/test/many_names3.pem
crypto/x509/test/policy_root.pem
crypto/x509/test/policy_intermediate_invalid.pem
crypto/x509/test/policy_intermediate.pem
crypto/x509/test/policy_leaf_invalid.pem
crypto/x509/test/policy_leaf.pem
crypto/x509/test/pss_sha1_explicit.pem
crypto/x509/test/pss_sha1_mgf1_syntax_error.pem
crypto/x509/test/pss_sha1.pem

Loading…
Cancel
Save