// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package x509 import ( "encoding/json" "os" "path/filepath" "slices" "testing" ) var nistTestPolicies = map[string]OID{ "anyPolicy": anyPolicyOID, "NIST-test-policy-1": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 1}), "NIST-test-policy-2": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 2}), "NIST-test-policy-3": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 3}), "NIST-test-policy-6": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 6}), } func TestNISTPKITSPolicy(t *testing.T) { // This test runs a subset of the NIST PKI path validation test suite that // focuses of policy validation, rather than the entire suite. Since the // suite assumes you are only validating the path, rather than building // _and_ validating the path, we take the path as given and run // policiesValid on it. certDir := "testdata/nist-pkits/certs" var testcases []struct { Name string CertPath []string InitialPolicySet []string InitialPolicyMappingInhibit bool InitialExplicitPolicy bool InitialAnyPolicyInhibit bool ShouldValidate bool Skipped bool } b, err := os.ReadFile("testdata/nist-pkits/vectors.json") if err != nil { t.Fatal(err) } if err := json.Unmarshal(b, &testcases); err != nil { t.Fatal(err) } policyTests := map[string]bool{ "4.8.1 All Certificates Same Policy Test1 (Subpart 1)": true, "4.8.1 All Certificates Same Policy Test1 (Subpart 2)": true, "4.8.1 All Certificates Same Policy Test1 (Subpart 3)": true, "4.8.1 All Certificates Same Policy Test1 (Subpart 4)": true, "4.8.2 All Certificates No Policies Test2 (Subpart 1)": true, "4.8.2 All Certificates No Policies Test2 (Subpart 2)": true, "4.8.3 Different Policies Test3 (Subpart 1)": true, "4.8.3 Different Policies Test3 (Subpart 2)": true, "4.8.3 Different Policies Test3 (Subpart 3)": true, "4.8.4 Different Policies Test4": true, "4.8.5 Different Policies Test5": true, "4.8.6 Overlapping Policies Test6 (Subpart 1)": true, "4.8.6 Overlapping Policies Test6 (Subpart 2)": true, "4.8.6 Overlapping Policies Test6 (Subpart 3)": true, "4.8.7 Different Policies Test7": true, "4.8.8 Different Policies Test8": true, "4.8.9 Different Policies Test9": true, "4.8.10 All Certificates Same Policies Test10 (Subpart 1)": true, "4.8.10 All Certificates Same Policies Test10 (Subpart 2)": true, "4.8.10 All Certificates Same Policies Test10 (Subpart 3)": true, "4.8.11 All Certificates AnyPolicy Test11 (Subpart 1)": true, "4.8.11 All Certificates AnyPolicy Test11 (Subpart 2)": true, "4.8.12 Different Policies Test12": true, "4.8.13 All Certificates Same Policies Test13 (Subpart 1)": true, "4.8.13 All Certificates Same Policies Test13 (Subpart 2)": true, "4.8.13 All Certificates Same Policies Test13 (Subpart 3)": true, "4.8.14 AnyPolicy Test14 (Subpart 1)": true, "4.8.14 AnyPolicy Test14 (Subpart 2)": true, "4.8.15 User Notice Qualifier Test15": true, "4.8.16 User Notice Qualifier Test16": true, "4.8.17 User Notice Qualifier Test17": true, "4.8.18 User Notice Qualifier Test18 (Subpart 1)": true, "4.8.18 User Notice Qualifier Test18 (Subpart 2)": true, "4.8.19 User Notice Qualifier Test19": true, "4.8.20 CPS Pointer Qualifier Test20": true, "4.9.1 Valid RequireExplicitPolicy Test1": true, "4.9.2 Valid RequireExplicitPolicy Test2": true, "4.9.3 Invalid RequireExplicitPolicy Test3": true, "4.9.4 Valid RequireExplicitPolicy Test4": true, "4.9.5 Invalid RequireExplicitPolicy Test5": true, "4.9.6 Valid Self-Issued requireExplicitPolicy Test6": true, "4.9.7 Invalid Self-Issued requireExplicitPolicy Test7": true, "4.9.8 Invalid Self-Issued requireExplicitPolicy Test8": true, "4.10.1.1 Valid Policy Mapping Test1 (Subpart 1)": true, "4.10.1.2 Valid Policy Mapping Test1 (Subpart 2)": true, "4.10.1.3 Valid Policy Mapping Test1 (Subpart 3)": true, "4.10.2 Invalid Policy Mapping Test2 (Subpart 1)": true, "4.10.2 Invalid Policy Mapping Test2 (Subpart 2)": true, "4.10.3 Valid Policy Mapping Test3 (Subpart 1)": true, "4.10.3 Valid Policy Mapping Test3 (Subpart 2)": true, "4.10.4 Invalid Policy Mapping Test4": true, "4.10.5 Valid Policy Mapping Test5 (Subpart 1)": true, "4.10.5 Valid Policy Mapping Test5 (Subpart 2)": true, "4.10.6 Valid Policy Mapping Test6 (Subpart 1)": true, "4.10.6 Valid Policy Mapping Test6 (Subpart 2)": true, "4.10.7 Invalid Mapping From anyPolicy Test7": true, "4.10.8 Invalid Mapping To anyPolicy Test8": true, "4.10.9 Valid Policy Mapping Test9": true, "4.10.10 Invalid Policy Mapping Test10": true, "4.10.11 Valid Policy Mapping Test11": true, "4.10.12 Valid Policy Mapping Test12 (Subpart 1)": true, "4.10.12 Valid Policy Mapping Test12 (Subpart 2)": true, "4.10.13 Valid Policy Mapping Test13 (Subpart 1)": true, "4.10.13 Valid Policy Mapping Test13 (Subpart 2)": true, "4.10.13 Valid Policy Mapping Test13 (Subpart 3)": true, "4.10.14 Valid Policy Mapping Test14": true, "4.11.1 Invalid inhibitPolicyMapping Test1": true, "4.11.2 Valid inhibitPolicyMapping Test2": true, "4.11.3 Invalid inhibitPolicyMapping Test3": true, "4.11.4 Valid inhibitPolicyMapping Test4": true, "4.11.5 Invalid inhibitPolicyMapping Test5": true, "4.11.6 Invalid inhibitPolicyMapping Test6": true, "4.11.7 Valid Self-Issued inhibitPolicyMapping Test7": true, "4.11.8 Invalid Self-Issued inhibitPolicyMapping Test8": true, "4.11.9 Invalid Self-Issued inhibitPolicyMapping Test9": true, "4.11.10 Invalid Self-Issued inhibitPolicyMapping Test10": true, "4.11.11 Invalid Self-Issued inhibitPolicyMapping Test11": true, "4.12.1 Invalid inhibitAnyPolicy Test1": true, "4.12.2 Valid inhibitAnyPolicy Test2": true, "4.12.3 inhibitAnyPolicy Test3 (Subpart 1)": true, "4.12.3 inhibitAnyPolicy Test3 (Subpart 2)": true, "4.12.4 Invalid inhibitAnyPolicy Test4": true, "4.12.5 Invalid inhibitAnyPolicy Test5": true, "4.12.6 Invalid inhibitAnyPolicy Test6": true, "4.12.7 Valid Self-Issued inhibitAnyPolicy Test7": true, "4.12.8 Invalid Self-Issued inhibitAnyPolicy Test8": true, "4.12.9 Valid Self-Issued inhibitAnyPolicy Test9": true, "4.12.10 Invalid Self-Issued inhibitAnyPolicy Test10": true, } for _, tc := range testcases { if !policyTests[tc.Name] { continue } t.Run(tc.Name, func(t *testing.T) { var chain []*Certificate for _, c := range tc.CertPath { certDER, err := os.ReadFile(filepath.Join(certDir, c)) if err != nil { t.Fatal(err) } cert, err := ParseCertificate(certDER) if err != nil { t.Fatal(err) } chain = append(chain, cert) } slices.Reverse(chain) var initialPolicies []OID for _, pstr := range tc.InitialPolicySet { policy, ok := nistTestPolicies[pstr] if !ok { t.Fatalf("unknown test policy: %s", pstr) } initialPolicies = append(initialPolicies, policy) } valid := policiesValid(chain, VerifyOptions{ CertificatePolicies: initialPolicies, inhibitPolicyMapping: tc.InitialPolicyMappingInhibit, requireExplicitPolicy: tc.InitialExplicitPolicy, inhibitAnyPolicy: tc.InitialAnyPolicyInhibit, }) if !valid { if !tc.ShouldValidate { return } t.Fatalf("Failed to validate: %s", err) } if !tc.ShouldValidate { t.Fatal("Expected path validation to fail") } }) } }