1 package precert
2
3 import (
4 "crypto/ecdsa"
5 "crypto/elliptic"
6 "crypto/rand"
7 "crypto/x509"
8 "crypto/x509/pkix"
9 "encoding/pem"
10 "fmt"
11 "math/big"
12 "os"
13 "strings"
14 "testing"
15 "time"
16 )
17
18 func TestCorrespondIncorrectArgumentOrder(t *testing.T) {
19 pre, final, err := readPair("testdata/good/precert.pem", "testdata/good/final.pem")
20 if err != nil {
21 t.Fatal(err)
22 }
23
24
25 err = Correspond(final, pre)
26 if err == nil {
27 t.Errorf("expected failure when final and precertificates were in wrong order, got success")
28 }
29 }
30
31 func TestCorrespondGood(t *testing.T) {
32 pre, final, err := readPair("testdata/good/precert.pem", "testdata/good/final.pem")
33 if err != nil {
34 t.Fatal(err)
35 }
36
37 err = Correspond(pre, final)
38 if err != nil {
39 t.Errorf("expected testdata/good/ certs to correspond, got %s", err)
40 }
41 }
42
43 func TestCorrespondBad(t *testing.T) {
44 pre, final, err := readPair("testdata/bad/precert.pem", "testdata/bad/final.pem")
45 if err != nil {
46 t.Fatal(err)
47 }
48
49 err = Correspond(pre, final)
50 if err == nil {
51 t.Errorf("expected testdata/bad/ certs to not correspond, got nil error")
52 }
53 expected := "precert extension 7 (0603551d20040c300a3008060667810c010201) not equal to final cert extension 7 (0603551d20044530433008060667810c0102013037060b2b0601040182df130101013028302606082b06010505070201161a687474703a2f2f6370732e6c657473656e63727970742e6f7267)"
54 if !strings.Contains(err.Error(), expected) {
55 t.Errorf("expected error to contain %q, got %q", expected, err.Error())
56 }
57 }
58
59 func TestCorrespondCompleteMismatch(t *testing.T) {
60 pre, final, err := readPair("testdata/good/precert.pem", "testdata/bad/final.pem")
61 if err != nil {
62 t.Fatal(err)
63 }
64
65 err = Correspond(pre, final)
66 if err == nil {
67 t.Errorf("expected testdata/good and testdata/bad/ certs to not correspond, got nil error")
68 }
69 expected := "checking for identical field 1: elements differ: 021203d91c3d22b404f20df3c1631c22e1754b8d != 021203e2267b786b7e338317ddd62e764fcb3c71"
70 if !strings.Contains(err.Error(), expected) {
71 t.Errorf("expected error to contain %q, got %q", expected, err.Error())
72 }
73 }
74
75 func readPair(a, b string) ([]byte, []byte, error) {
76 aDER, err := derFromPEMFile(a)
77 if err != nil {
78 return nil, nil, err
79 }
80 bDER, err := derFromPEMFile(b)
81 if err != nil {
82 return nil, nil, err
83 }
84 return aDER, bDER, nil
85 }
86
87
88 func derFromPEMFile(filename string) ([]byte, error) {
89 precertPEM, err := os.ReadFile(filename)
90 if err != nil {
91 return nil, fmt.Errorf("reading %s: %w", filename, err)
92 }
93
94 precertPEMBlock, _ := pem.Decode(precertPEM)
95 if precertPEMBlock == nil {
96 return nil, fmt.Errorf("error PEM decoding %s", filename)
97 }
98
99 return precertPEMBlock.Bytes, nil
100 }
101
102 func TestMismatches(t *testing.T) {
103 now := time.Now()
104
105 issuerKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
106 if err != nil {
107 t.Fatal(err)
108 }
109
110
111
112 untrustedIssuerKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
113 if err != nil {
114 t.Fatal(err)
115 }
116
117 subscriberKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
118 if err != nil {
119 t.Fatal(err)
120 }
121
122
123
124
125 issuer := x509.Certificate{
126 Subject: pkix.Name{
127 CommonName: "Some Issuer",
128 },
129 }
130
131 precertTemplate := x509.Certificate{
132 SerialNumber: big.NewInt(3141592653589793238),
133 NotBefore: now,
134 NotAfter: now.Add(24 * time.Hour),
135 DNSNames: []string{"example.com"},
136 ExtraExtensions: []pkix.Extension{
137 {
138 Id: poisonOID,
139 Value: []byte{0x5, 0x0},
140 },
141 },
142 }
143
144 precertDER, err := x509.CreateCertificate(rand.Reader, &precertTemplate, &issuer, &subscriberKey.PublicKey, issuerKey)
145 if err != nil {
146 t.Fatal(err)
147 }
148
149
150
151 makeFinalCert := func(modify func(c *x509.Certificate)) []byte {
152 t.Helper()
153 finalCertTemplate := &x509.Certificate{
154 SerialNumber: big.NewInt(3141592653589793238),
155 NotBefore: now,
156 NotAfter: now.Add(24 * time.Hour),
157 DNSNames: []string{"example.com"},
158 ExtraExtensions: []pkix.Extension{
159 {
160 Id: sctListOID,
161 Value: nil,
162 },
163 },
164 }
165
166 modify(finalCertTemplate)
167
168 finalCertDER, err := x509.CreateCertificate(rand.Reader, finalCertTemplate,
169 &issuer, &subscriberKey.PublicKey, untrustedIssuerKey)
170 if err != nil {
171 t.Fatal(err)
172 }
173
174 return finalCertDER
175 }
176
177
178 finalCertDER := makeFinalCert(func(c *x509.Certificate) {})
179 err = Correspond(precertDER, finalCertDER)
180 if err != nil {
181 t.Errorf("expected precert and final cert to correspond, got: %s", err)
182 }
183
184
185
186 precertTemplate2 := x509.Certificate{
187 SerialNumber: big.NewInt(3141592653589793238),
188 NotBefore: now,
189 NotAfter: now.Add(24 * time.Hour),
190 DNSNames: []string{"example.com"},
191 ExtraExtensions: []pkix.Extension{
192 {
193 Id: poisonOID,
194 Value: []byte{0x5, 0x0},
195 },
196
197 {
198 Id: []int{1, 2, 3, 4},
199 Value: []byte{0x5, 0x0},
200 },
201 },
202 }
203
204 precertDER2, err := x509.CreateCertificate(rand.Reader, &precertTemplate2, &issuer, &subscriberKey.PublicKey, issuerKey)
205 if err != nil {
206 t.Fatal(err)
207 }
208
209 finalCertDER = makeFinalCert(func(c *x509.Certificate) {
210 c.ExtraExtensions = []pkix.Extension{
211 {
212 Id: []int{1, 2, 3, 4},
213 Value: []byte{0x5, 0x0},
214 },
215 {
216 Id: sctListOID,
217 Value: nil,
218 },
219 }
220 })
221 err = Correspond(precertDER2, finalCertDER)
222 if err != nil {
223 t.Errorf("expected precert and final cert to correspond with differently positioned extensions, got: %s", err)
224 }
225
226
227 issuer = x509.Certificate{
228 Subject: pkix.Name{
229 CommonName: "Some Other Issuer",
230 },
231 }
232
233 finalCertDER = makeFinalCert(func(c *x509.Certificate) {})
234 err = Correspond(precertDER, finalCertDER)
235 if err == nil {
236 t.Errorf("expected error for mismatched issuer, got nil error")
237 }
238
239
240 issuer = x509.Certificate{
241 Subject: pkix.Name{
242 CommonName: "Some Issuer",
243 },
244 }
245
246
247 finalCertDER = makeFinalCert(func(c *x509.Certificate) {
248 c.SerialNumber = big.NewInt(2718281828459045)
249 })
250 err = Correspond(precertDER, finalCertDER)
251 if err == nil {
252 t.Errorf("expected error for mismatched serial, got nil error")
253 }
254
255
256 finalCertDER = makeFinalCert(func(c *x509.Certificate) {
257 c.DNSNames = []string{"example.com", "www.example.com"}
258 })
259
260 err = Correspond(precertDER, finalCertDER)
261 if err == nil {
262 t.Errorf("expected error for mismatched names, got nil error")
263 }
264
265
266 finalCertDER = makeFinalCert(func(c *x509.Certificate) {
267 c.NotBefore = now.Add(24 * time.Hour)
268 })
269
270 err = Correspond(precertDER, finalCertDER)
271 if err == nil {
272 t.Errorf("expected error for mismatched NotBefore, got nil error")
273 }
274
275
276 finalCertDER = makeFinalCert(func(c *x509.Certificate) {
277 c.NotAfter = now.Add(48 * time.Hour)
278 })
279 err = Correspond(precertDER, finalCertDER)
280 if err == nil {
281 t.Errorf("expected error for mismatched NotAfter, got nil error")
282 }
283
284
285 finalCertDER = makeFinalCert(func(c *x509.Certificate) {
286 c.ExtraExtensions = append(c.ExtraExtensions, pkix.Extension{
287 Critical: true,
288 Id: []int{1, 2, 3},
289 Value: []byte("hello"),
290 })
291 })
292
293 err = Correspond(precertDER, finalCertDER)
294 if err == nil {
295 t.Errorf("expected error for mismatched extensions, got nil error")
296 }
297 expectedError := "precert extension 2 () not equal to final cert extension 2 (06022a030101ff040568656c6c6f)"
298 if err.Error() != expectedError {
299 t.Errorf("expected error %q, got %q", expectedError, err)
300 }
301 }
302
303 func TestUnwrapExtensions(t *testing.T) {
304 validExtensionsOuter := []byte{0xA3, 0x3, 0x30, 0x1, 0x0}
305 _, err := unwrapExtensions(validExtensionsOuter)
306 if err != nil {
307 t.Errorf("expected success for validExtensionsOuter, got %s", err)
308 }
309
310 invalidExtensionsOuter := []byte{0xA3, 0x99, 0x30, 0x1, 0x0}
311 _, err = unwrapExtensions(invalidExtensionsOuter)
312 if err == nil {
313 t.Error("expected error for invalidExtensionsOuter, got none")
314 }
315
316 invalidExtensionsInner := []byte{0xA3, 0x3, 0x30, 0x99, 0x0}
317 _, err = unwrapExtensions(invalidExtensionsInner)
318 if err == nil {
319 t.Error("expected error for invalidExtensionsInner, got none")
320 }
321 }
322
323 func TestTBSFromCertDER(t *testing.T) {
324 validCertOuter := []byte{0x30, 0x3, 0x30, 0x1, 0x0}
325 _, err := tbsDERFromCertDER(validCertOuter)
326 if err != nil {
327 t.Errorf("expected success for validCertOuter, got %s", err)
328 }
329
330 invalidCertOuter := []byte{0x30, 0x99, 0x30, 0x1, 0x0}
331 _, err = tbsDERFromCertDER(invalidCertOuter)
332 if err == nil {
333 t.Error("expected error for invalidCertOuter, got none")
334 }
335
336 invalidCertInner := []byte{0x30, 0x3, 0x30, 0x99, 0x0}
337 _, err = tbsDERFromCertDER(invalidCertInner)
338 if err == nil {
339 t.Error("expected error for invalidExtensionsInner, got none")
340 }
341 }
342
View as plain text