Source file
src/crypto/x509/parser_test.go
1
2
3
4
5 package x509
6
7 import (
8 "encoding/asn1"
9 "encoding/pem"
10 "os"
11 "strings"
12 "testing"
13
14 cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
15 )
16
17 func TestParseASN1String(t *testing.T) {
18 tests := []struct {
19 name string
20 tag cryptobyte_asn1.Tag
21 value []byte
22 expected string
23 expectedErr string
24 }{
25 {
26 name: "T61String",
27 tag: cryptobyte_asn1.T61String,
28 value: []byte{80, 81, 82},
29 expected: string("PQR"),
30 },
31 {
32 name: "PrintableString",
33 tag: cryptobyte_asn1.PrintableString,
34 value: []byte{80, 81, 82},
35 expected: string("PQR"),
36 },
37 {
38 name: "PrintableString (invalid)",
39 tag: cryptobyte_asn1.PrintableString,
40 value: []byte{1, 2, 3},
41 expectedErr: "invalid PrintableString",
42 },
43 {
44 name: "UTF8String",
45 tag: cryptobyte_asn1.UTF8String,
46 value: []byte{80, 81, 82},
47 expected: string("PQR"),
48 },
49 {
50 name: "UTF8String (invalid)",
51 tag: cryptobyte_asn1.UTF8String,
52 value: []byte{255},
53 expectedErr: "invalid UTF-8 string",
54 },
55 {
56 name: "BMPString",
57 tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
58 value: []byte{80, 81},
59 expected: string("偑"),
60 },
61 {
62 name: "BMPString (invalid length)",
63 tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
64 value: []byte{255},
65 expectedErr: "invalid BMPString",
66 },
67 {
68 name: "IA5String",
69 tag: cryptobyte_asn1.IA5String,
70 value: []byte{80, 81},
71 expected: string("PQ"),
72 },
73 {
74 name: "IA5String (invalid)",
75 tag: cryptobyte_asn1.IA5String,
76 value: []byte{255},
77 expectedErr: "invalid IA5String",
78 },
79 {
80 name: "NumericString",
81 tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
82 value: []byte{49, 50},
83 expected: string("12"),
84 },
85 {
86 name: "NumericString (invalid)",
87 tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
88 value: []byte{80},
89 expectedErr: "invalid NumericString",
90 },
91 }
92
93 for _, tc := range tests {
94 t.Run(tc.name, func(t *testing.T) {
95 out, err := parseASN1String(tc.tag, tc.value)
96 if err != nil && err.Error() != tc.expectedErr {
97 t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr)
98 } else if err == nil && tc.expectedErr != "" {
99 t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr)
100 }
101 if out != tc.expected {
102 t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected)
103 }
104 })
105 }
106 }
107
108 const policyPEM = `-----BEGIN CERTIFICATE-----
109 MIIGeDCCBWCgAwIBAgIUED9KQBi0ScBDoufB2mgAJ63G5uIwDQYJKoZIhvcNAQEL
110 BQAwVTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDENMAsG
111 A1UECxMERlBLSTEdMBsGA1UEAxMURmVkZXJhbCBCcmlkZ2UgQ0EgRzQwHhcNMjAx
112 MDIyMTcwNDE5WhcNMjMxMDIyMTcwNDE5WjCBgTELMAkGA1UEBhMCVVMxHTAbBgNV
113 BAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVz
114 dCBOZXR3b3JrMTIwMAYDVQQDEylTeW1hbnRlYyBDbGFzcyAzIFNTUCBJbnRlcm1l
115 ZGlhdGUgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2p
116 75cMpx86sS2aH4r+0o8r+m/KTrPrknWP0RA9Kp6sewAzkNa7BVwg0jOhyamiv1iP
117 Cns10usoH93nxYbXLWF54vOLRdYU/53KEPNmgkj2ipMaTLuaReBghNibikWSnAmy
118 S8RItaDMs8tdF2goKPI4xWiamNwqe92VC+pic2tq0Nva3Y4kvMDJjtyje3uduTtL
119 oyoaaHkrX7i7gE67psnMKj1THUtre1JV1ohl9+oOuyot4p3eSxVlrMWiiwb11bnk
120 CakecOz/mP2DHMGg6pZ/BeJ+ThaLUylAXECARIqHc9UwRPKC9BfLaCX4edIoeYiB
121 loRs4KdqLdg/I9eTwKkCAwEAAaOCAxEwggMNMB0GA1UdDgQWBBQ1Jn1QleGhwb0F
122 1cOdd0LHDBOWjDAfBgNVHSMEGDAWgBR58ABJ6393wl1BAmU0ipAjmx4HbzAOBgNV
123 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBiAYDVR0gBIGAMH4wDAYKYIZI
124 AWUDAgEDAzAMBgpghkgBZQMCAQMMMAwGCmCGSAFlAwIBAw4wDAYKYIZIAWUDAgED
125 DzAMBgpghkgBZQMCAQMSMAwGCmCGSAFlAwIBAxMwDAYKYIZIAWUDAgEDFDAMBgpg
126 hkgBZQMCAQMlMAwGCmCGSAFlAwIBAyYwggESBgNVHSEEggEJMIIBBTAbBgpghkgB
127 ZQMCAQMDBg1ghkgBhvhFAQcXAwEGMBsGCmCGSAFlAwIBAwwGDWCGSAGG+EUBBxcD
128 AQcwGwYKYIZIAWUDAgEDDgYNYIZIAYb4RQEHFwMBDjAbBgpghkgBZQMCAQMPBg1g
129 hkgBhvhFAQcXAwEPMBsGCmCGSAFlAwIBAxIGDWCGSAGG+EUBBxcDARIwGwYKYIZI
130 AWUDAgEDEwYNYIZIAYb4RQEHFwMBETAbBgpghkgBZQMCAQMUBg1ghkgBhvhFAQcX
131 AwEUMBsGCmCGSAFlAwIBAyUGDWCGSAGG+EUBBxcDAQgwGwYKYIZIAWUDAgEDJgYN
132 YIZIAYb4RQEHFwMBJDBgBggrBgEFBQcBCwRUMFIwUAYIKwYBBQUHMAWGRGh0dHA6
133 Ly9zc3Atc2lhLnN5bWF1dGguY29tL1NUTlNTUC9DZXJ0c19Jc3N1ZWRfYnlfQ2xh
134 c3MzU1NQQ0EtRzMucDdjMA8GA1UdJAQIMAaAAQCBAQAwCgYDVR02BAMCAQAwUQYI
135 KwYBBQUHAQEERTBDMEEGCCsGAQUFBzAChjVodHRwOi8vcmVwby5mcGtpLmdvdi9i
136 cmlkZ2UvY2FDZXJ0c0lzc3VlZFRvZmJjYWc0LnA3YzA3BgNVHR8EMDAuMCygKqAo
137 hiZodHRwOi8vcmVwby5mcGtpLmdvdi9icmlkZ2UvZmJjYWc0LmNybDANBgkqhkiG
138 9w0BAQsFAAOCAQEAA751TycC1f/WTkHmedF9ZWxP58Jstmwvkyo8bKueJ0eF7LTG
139 BgQlzE2B9vke4sFhd4V+BdgOPGE1dsGzllYKCWg0BhkCBs5kIJ7F6Ay6G1TBuGU1
140 Ie8247GL+P9pcC5TVvXHC/62R2w3DuD/vAPLbYEbSQjobXlsqt8Kmtd6yK/jVuDV
141 BTZMdZmvoNtjemqmgcBXHsf0ctVm0m6tH5uYqyVxu8tfyUis6Cf303PHj+spWP1k
142 gc5PYnVF0ot7qAmNFENIpbKg3BdusBkF9rGxLaDSUBvSc7+s9iQz9d/iRuAebrYu
143 +eqUlJ2lsjS1U8qyPmlH+spfPNbAEQEsuP32Aw==
144 -----END CERTIFICATE-----
145 `
146
147 func TestPolicyParse(t *testing.T) {
148 b, _ := pem.Decode([]byte(policyPEM))
149 c, err := ParseCertificate(b.Bytes)
150 if err != nil {
151 t.Fatal(err)
152 }
153 if len(c.Policies) != 9 {
154 t.Errorf("unexpected number of policies: got %d, want %d", len(c.Policies), 9)
155 }
156 if len(c.PolicyMappings) != 9 {
157 t.Errorf("unexpected number of policy mappings: got %d, want %d", len(c.PolicyMappings), 9)
158 }
159 if !c.RequireExplicitPolicyZero {
160 t.Error("expected RequireExplicitPolicyZero to be set")
161 }
162 if !c.InhibitPolicyMappingZero {
163 t.Error("expected InhibitPolicyMappingZero to be set")
164 }
165 if !c.InhibitAnyPolicyZero {
166 t.Error("expected InhibitAnyPolicyZero to be set")
167 }
168 }
169
170 func TestParsePolicies(t *testing.T) {
171 for _, tc := range []string{
172 "testdata/policy_leaf_duplicate.pem",
173 "testdata/policy_leaf_invalid.pem",
174 } {
175 t.Run(tc, func(t *testing.T) {
176 b, err := os.ReadFile(tc)
177 if err != nil {
178 t.Fatal(err)
179 }
180 p, _ := pem.Decode(b)
181 _, err = ParseCertificate(p.Bytes)
182 if err == nil {
183 t.Error("parsing should've failed")
184 }
185 })
186 }
187 }
188
189 func TestDomainNameValid(t *testing.T) {
190 for _, tc := range []struct {
191 name string
192 dnsName string
193 constraint bool
194 valid bool
195 }{
196 {"empty name, name", "", false, false},
197 {"empty name, constraint", "", true, true},
198 {"empty label, name", "a..a", false, false},
199 {"empty label, constraint", "a..a", true, false},
200 {"period, name", ".", false, false},
201 {"period, constraint", ".", true, false},
202 {"valid, name", "a.b.c", false, true},
203 {"valid, constraint", "a.b.c", true, true},
204 {"leading period, name", ".a.b.c", false, false},
205 {"leading period, constraint", ".a.b.c", true, true},
206 {"trailing period, name", "a.", false, false},
207 {"trailing period, constraint", "a.", true, false},
208 {"bare label, name", "a", false, true},
209 {"bare label, constraint", "a", true, true},
210 {"254 char label, name", strings.Repeat("a.a", 84) + "aaa", false, false},
211 {"254 char label, constraint", strings.Repeat("a.a", 84) + "aaa", true, false},
212 {"253 char label, name", strings.Repeat("a.a", 84) + "aa", false, false},
213 {"253 char label, constraint", strings.Repeat("a.a", 84) + "aa", true, false},
214 {"64 char single label, name", strings.Repeat("a", 64), false, false},
215 {"64 char single label, constraint", strings.Repeat("a", 64), true, false},
216 {"63 char single label, name", strings.Repeat("a", 63), false, true},
217 {"63 char single label, constraint", strings.Repeat("a", 63), true, true},
218 {"64 char label, name", "a." + strings.Repeat("a", 64), false, false},
219 {"64 char label, constraint", "a." + strings.Repeat("a", 64), true, false},
220 {"63 char label, name", "a." + strings.Repeat("a", 63), false, true},
221 {"63 char label, constraint", "a." + strings.Repeat("a", 63), true, true},
222 } {
223 t.Run(tc.name, func(t *testing.T) {
224 if tc.valid != domainNameValid(tc.dnsName, tc.constraint) {
225 t.Errorf("domainNameValid(%q, %t) = %v; want %v", tc.dnsName, tc.constraint, !tc.valid, tc.valid)
226 }
227 })
228 }
229 }
230
View as plain text