1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package verification
17
18 import (
19 "bytes"
20 "crypto"
21 "crypto/elliptic"
22 "crypto/rand"
23 "crypto/x509"
24 "crypto/x509/pkix"
25 "encoding/asn1"
26 "encoding/json"
27 "fmt"
28 "io"
29 "math/big"
30 "strings"
31 "testing"
32 "time"
33
34 "github.com/digitorus/timestamp"
35 "github.com/sigstore/sigstore/pkg/cryptoutils"
36 "github.com/sigstore/sigstore/pkg/signature"
37 "github.com/sigstore/timestamp-authority/pkg/client/mock"
38 tsatimestamp "github.com/sigstore/timestamp-authority/pkg/generated/client/timestamp"
39 "github.com/sigstore/timestamp-authority/pkg/signer"
40 )
41
42 func TestVerifyArtifactHashedMessages(t *testing.T) {
43 c, err := mock.NewTSAClient(mock.TSAClientOptions{Time: time.Now()})
44 if err != nil {
45 t.Fatalf("unexpected error creating client: %v", err)
46 }
47
48 type test struct {
49 message string
50 forceError bool
51 expectedErrorMessage string
52 }
53
54 tests := []test{
55 {
56 message: "valid local artifact",
57 },
58 {
59 message: "nonexistant local artifact",
60 },
61 {
62 message: "valid local artifact with hash algorithm",
63 },
64 {
65 message: "valid oid",
66 },
67 {
68 message: "MIIEbjADAgEAMIIEZQYJKoZIhvcNAQcCoIIEVjCCBFICAQExDTALBglghkgBZQMEAgEwgdQGCyqGSIb3DQEJEAEEoIHEBIHBMIG+AgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgN94hMnpq0onyUi7r1zJHNiLT1/spX8MU2GBN9AdMe6wCFQDS6RL1iVlmlkwJzmpS2EH0cuX8sxgTMjAyMjExMDMxNzQyNDIrMDEwMDADAgEBAhRKnQszZjzcgJkpE8LCbmbF0s1jPaA0pDIwMDEOMAwGA1UEChMFbG9jYWwxHjAcBgNVBAMTFVRlc3QgVFNBIFRpbWVzdGFtcGluZ6CCAckwggHFMIIBaqADAgECAhRHCu9dHKS97mFo1cH5neJubRibujAKBggqhkjOPQQDAjAoMQ4wDAYDVQQKEwVsb2NhbDEWMBQGA1UEAxMNVGVzdCBUU0EgUm9vdDAeFw0yMjExMDMxMTUzMThaFw0zMTExMDMxMTU2MThaMDAxDjAMBgNVBAoTBWxvY2FsMR4wHAYDVQQDExVUZXN0IFRTQSBUaW1lc3RhbXBpbmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATo3W6NQrpx5D8z5IvgD2DlAgoJMF4KPY9Pj4UfFhfOq029ryszXp3460Z7N+x86bDvyjVrHaeiPnl1HO9Q52zso2owaDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFHSIhDdTGIsodML/iUOhx7hgo/K7MB8GA1UdIwQYMBaAFBoZYijuouZCvKDtBd0eCyaU2HWoMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMAoGCCqGSM49BAMCA0kAMEYCIQCmPVr5kwYe4Jg9PGO6apgfzSrKAtESgNHpAbE3iIvJhQIhAJIGNxshJcC8LXHRrVWM77no3d3GguSvR01OAPZwE2pqMYIBmDCCAZQCAQEwQDAoMQ4wDAYDVQQKEwVsb2NhbDEWMBQGA1UEAxMNVGVzdCBUU0EgUm9vdAIURwrvXRykve5haNXB+Z3ibm0Ym7owCwYJYIZIAWUDBAIBoIHqMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjIxMTAzMTY0MjQyWjAvBgkqhkiG9w0BCQQxIgQgrKbkOizzGoAudPhAnW5Qny788Kcd++VQwPrCMhg4MTEwfQYLKoZIhvcNAQkQAi8xbjBsMGowaAQgXqxJD0nAgg6en9P1bRrU7+6tzxOMn3YThreg7uR6T7EwRDAspCowKDEOMAwGA1UEChMFbG9jYWwxFjAUBgNVBAMTDVRlc3QgVFNBIFJvb3QCFEcK710cpL3uYWjVwfmd4m5tGJu6MAoGCCqGSM49BAMCBEcwRQIgQkc2BxMjnUMzqBDYzUiw10LoCIZ9Zmp1E0Hl6E+9mzwCIQDp2lD826Du5Ss4pNG/TksDknTUJfKvrLc2ex+x+W3VHg==",
69 },
70 {
71 expectedErrorMessage: "hashed messages don't match",
72 forceError: true,
73 },
74 }
75
76 for _, tc := range tests {
77 tsq, err := timestamp.CreateRequest(strings.NewReader(tc.message), ×tamp.RequestOptions{
78 Hash: crypto.SHA256,
79 Certificates: true,
80 })
81 if err != nil {
82 t.Fatalf("unexpected error creating request: %v", err)
83 }
84
85 chain, err := c.Timestamp.GetTimestampCertChain(nil)
86 if err != nil {
87 t.Fatalf("unexpected error getting timestamp chain: %v", err)
88 }
89
90 params := tsatimestamp.NewGetTimestampResponseParams()
91 params.SetTimeout(5 * time.Second)
92 params.Request = io.NopCloser(bytes.NewReader(tsq))
93
94 var respBytes bytes.Buffer
95 _, err = c.Timestamp.GetTimestampResponse(params, &respBytes)
96 if err != nil {
97 t.Fatalf("unexpected error getting timestamp response: %v", err)
98 }
99
100 certs, err := cryptoutils.UnmarshalCertificatesFromPEM([]byte(chain.Payload))
101 if err != nil {
102 t.Fatal("unexpected error while parsing test certificates from PEM file")
103 }
104
105 if len(certs) != 3 {
106 t.Fatalf("expected three certificates (one leaf, one intermediate, and one root), received %d", len(certs))
107 }
108
109 opts := VerifyOpts{
110 Intermediates: certs[1:2],
111 Roots: certs[2:],
112 }
113
114 ts, err := VerifyTimestampResponse(respBytes.Bytes(), strings.NewReader(tc.message), opts)
115 if err != nil {
116 t.Errorf("VerifyTimestampResponse failed to verify the timestamp: %v", err)
117 }
118 if ts == nil {
119 t.Error("VerifyTimestampResponse did not return the parsed timestamp as expected")
120 }
121
122 if tc.forceError {
123
124 msg := tc.message + "XXX"
125 ts, err := VerifyTimestampResponse(respBytes.Bytes(), strings.NewReader(msg), opts)
126 if err == nil {
127 t.Error("expected error message when verifying the timestamp response")
128 }
129 if err != nil && err.Error() != tc.expectedErrorMessage {
130 t.Errorf("expected error message when verifying the timestamp response: %s got %s", tc.expectedErrorMessage, err.Error())
131 }
132 if ts != nil {
133 t.Errorf("expected VerifyTimestampResponse to return a nil Timestamp object")
134 }
135 }
136 }
137 }
138
139 func TestVerifyNonce(t *testing.T) {
140 type test struct {
141 nonceStr string
142 expectVerifySuccess bool
143 }
144
145 tests := []test{
146 {
147 nonceStr: "312432523523431424141",
148 expectVerifySuccess: true,
149 },
150 {
151 nonceStr: "9874325235234314241230",
152 expectVerifySuccess: false,
153 },
154 }
155
156 for _, tc := range tests {
157 optsBigIntStr := "312432523523431424141"
158 optsNonce, ok := new(big.Int).SetString(optsBigIntStr, 10)
159 if !ok {
160 t.Fatalf("unexpected failure to create big int from string: %s", optsBigIntStr)
161 }
162 opts := VerifyOpts{
163 Nonce: optsNonce,
164 }
165
166 providedNonce, ok := new(big.Int).SetString(tc.nonceStr, 10)
167 if !ok {
168 t.Fatalf("unexpected failure to create big int from string: %s", tc.nonceStr)
169 }
170
171 err := verifyNonce(providedNonce, opts)
172 if tc.expectVerifySuccess && err != nil {
173 t.Errorf("expected verification to fail \n provided nonce %s should not match opts nonce %s", tc.nonceStr, optsBigIntStr)
174 }
175 if !tc.expectVerifySuccess && err == nil {
176 t.Errorf("expected verification to pass \n provided nonce %s should match opts nonce %s", tc.nonceStr, optsBigIntStr)
177 }
178 }
179 }
180
181 func TestVerifyLeafCert(t *testing.T) {
182 type test struct {
183 useOptsCert bool
184 useTSCert bool
185 expectVerifySuccess bool
186 }
187
188 tests := []test{
189 {
190 useOptsCert: false,
191 useTSCert: false,
192 expectVerifySuccess: false,
193 },
194 {
195 useOptsCert: true,
196 useTSCert: false,
197 expectVerifySuccess: true,
198 },
199 {
200 useOptsCert: false,
201 useTSCert: true,
202 expectVerifySuccess: true,
203 },
204 {
205 useOptsCert: true,
206 useTSCert: true,
207 expectVerifySuccess: true,
208 },
209 }
210
211 for _, tc := range tests {
212 criticalExtension := pkix.Extension{
213 Id: EKUOID,
214 Critical: true,
215 }
216
217 sampleCert := &x509.Certificate{
218 Raw: []byte("abc123"),
219 RawIssuer: []byte("abc123"),
220 SerialNumber: big.NewInt(int64(123)),
221 Extensions: []pkix.Extension{criticalExtension},
222 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping},
223 Subject: pkix.Name{
224 CommonName: "TSA-Service",
225 },
226 }
227
228 opts := VerifyOpts{}
229 ts := timestamp.Timestamp{}
230
231 if tc.useOptsCert {
232 opts.TSACertificate = sampleCert
233 opts.CommonName = sampleCert.Subject.CommonName
234 }
235
236 if tc.useTSCert {
237 ts.Certificates = []*x509.Certificate{sampleCert}
238 }
239
240 err := verifyLeafCert(ts, opts)
241
242 if err != nil && tc.expectVerifySuccess {
243 t.Fatalf("expected error to be nil, actual error: %v", err)
244 }
245
246 if err == nil && !tc.expectVerifySuccess {
247 t.Fatal("expected error not to be nil")
248 }
249 }
250 }
251
252 func TestVerifyEmbeddedLeafCert(t *testing.T) {
253 type test struct {
254 optsCert *x509.Certificate
255 providedCert *x509.Certificate
256 expectVerifySuccess bool
257 }
258
259 tests := []test{
260 {
261 optsCert: nil,
262 providedCert: &x509.Certificate{
263 Raw: []byte("abc123"),
264 },
265 expectVerifySuccess: true,
266 },
267 {
268 optsCert: &x509.Certificate{
269 Raw: []byte("abc123"),
270 },
271 providedCert: &x509.Certificate{
272 Raw: []byte("abc123"),
273 },
274 expectVerifySuccess: true,
275 },
276 {
277 optsCert: &x509.Certificate{
278 Raw: []byte("abc123"),
279 },
280 providedCert: &x509.Certificate{
281 Raw: []byte("def456"),
282 },
283 expectVerifySuccess: false,
284 },
285 }
286
287 for _, tc := range tests {
288 opts := VerifyOpts{
289 TSACertificate: tc.optsCert,
290 }
291
292 err := verifyEmbeddedLeafCert(tc.providedCert, opts)
293 if err == nil && !tc.expectVerifySuccess {
294 t.Errorf("expected verification to fail: provided cert unexpectedly matches opts cert")
295 }
296 if err != nil && tc.expectVerifySuccess {
297 t.Errorf("expected verification to pass: provided cert does not match opts cert")
298 }
299 }
300 }
301
302 func TestVerifySubjectCommonName(t *testing.T) {
303 type test struct {
304 optsCommonName string
305 providedCommonName string
306 expectVerifySuccess bool
307 }
308
309 tests := []test{
310 {
311 optsCommonName: "Sigstore TSA",
312 providedCommonName: "Sigstore TSA",
313 expectVerifySuccess: true,
314 },
315 {
316 optsCommonName: "Sigstore TSA",
317 providedCommonName: "SomeOtherStore",
318 expectVerifySuccess: false,
319 },
320 }
321 for _, tc := range tests {
322 opts := VerifyOpts{
323 CommonName: tc.optsCommonName,
324 }
325
326 cert := x509.Certificate{
327 Subject: pkix.Name{
328 CommonName: tc.providedCommonName,
329 Organization: []string{"Sigstore"},
330 },
331 }
332 err := verifySubjectCommonName(&cert, opts)
333 if err != nil && tc.expectVerifySuccess {
334 t.Errorf("expected verification to pass \n provided common name %s should match opts common name %s", tc.providedCommonName, tc.optsCommonName)
335 }
336 if err == nil && !tc.expectVerifySuccess {
337 t.Errorf("expected verification to fail \n provided common name %s should not match opts common name %s", tc.providedCommonName, tc.optsCommonName)
338 }
339 }
340 }
341
342 func TestVerifyESSCertID(t *testing.T) {
343 type test struct {
344 optsIssuer pkix.Name
345 optsSerialNumber string
346 providedIssuer pkix.Name
347 providedSerialNumber string
348 expectVerifySuccess bool
349 }
350
351 tests := []test{
352 {
353 optsIssuer: pkix.Name{
354 CommonName: "Sigstore CA",
355 Organization: []string{"Sigstore"},
356 },
357 optsSerialNumber: "312432523523431424141",
358 providedIssuer: pkix.Name{
359 CommonName: "Sigstore CA",
360 Organization: []string{"Sigstore"},
361 },
362 providedSerialNumber: "312432523523431424141",
363 expectVerifySuccess: true,
364 },
365 {
366 optsIssuer: pkix.Name{
367 CommonName: "Sigstore CA",
368 Organization: []string{"Sigstore"},
369 },
370 optsSerialNumber: "312432523523431424141",
371 providedIssuer: pkix.Name{
372 CommonName: "Sigstore CA",
373 Organization: []string{"Sigstore"},
374 },
375 providedSerialNumber: "4567523523431424141",
376 expectVerifySuccess: false,
377 },
378 {
379 optsIssuer: pkix.Name{
380 CommonName: "Sigstore CA",
381 Organization: []string{"Sigstore"},
382 },
383 optsSerialNumber: "312432523523431424141",
384 providedIssuer: pkix.Name{
385 CommonName: "Another CA",
386 Organization: []string{"Sigstore"},
387 },
388 providedSerialNumber: "312432523523431424141",
389 expectVerifySuccess: false,
390 },
391 }
392
393 for _, tc := range tests {
394 optsSerialNumber, ok := new(big.Int).SetString(tc.optsSerialNumber, 10)
395 if !ok {
396 t.Fatalf("unexpected failure to create big int from string: %s", tc.optsSerialNumber)
397 }
398
399 optsRawIssuer, err := json.Marshal(tc.optsIssuer)
400 if err != nil {
401 t.Fatalf("unexpected failure while marshalling issuer object")
402 }
403 opts := VerifyOpts{
404 TSACertificate: &x509.Certificate{
405 Issuer: tc.optsIssuer,
406 RawIssuer: optsRawIssuer,
407 SerialNumber: optsSerialNumber,
408 },
409 }
410
411 providedSerialNumber, ok := new(big.Int).SetString(tc.providedSerialNumber, 10)
412 if !ok {
413 t.Fatalf("unexpected failure to create big int from string: %s", tc.providedSerialNumber)
414 }
415
416 providedRawIssuer, err := json.Marshal(tc.providedIssuer)
417 if err != nil {
418 t.Fatalf("unexpected failure while marshalling issuer object")
419 }
420 cert := x509.Certificate{
421 Issuer: tc.providedIssuer,
422 RawIssuer: providedRawIssuer,
423 SerialNumber: providedSerialNumber,
424 }
425 err = verifyESSCertID(&cert, opts)
426 if err != nil && tc.expectVerifySuccess {
427 t.Errorf("expected verifcation to pass: %s", err.Error())
428 }
429 if err == nil && !tc.expectVerifySuccess {
430 t.Errorf("expected verifcation to fail")
431 }
432 }
433 }
434
435 func TestVerifyExtendedKeyUsage(t *testing.T) {
436 type test struct {
437 eku []x509.ExtKeyUsage
438 expectVerifySuccess bool
439 }
440
441 tests := []test{
442 {
443 eku: []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping},
444 expectVerifySuccess: true,
445 },
446 {
447 eku: []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping, x509.ExtKeyUsageIPSECTunnel},
448 expectVerifySuccess: false,
449 },
450 {
451 eku: []x509.ExtKeyUsage{x509.ExtKeyUsageIPSECTunnel},
452 expectVerifySuccess: false,
453 },
454 }
455
456 for _, tc := range tests {
457 cert := x509.Certificate{
458 ExtKeyUsage: tc.eku,
459 }
460
461 err := verifyExtendedKeyUsage(&cert)
462 if err != nil && tc.expectVerifySuccess {
463 t.Errorf("expected verifyExtendedKeyUsage to return nil error")
464 }
465 if err == nil && !tc.expectVerifySuccess {
466 t.Errorf("expected verification to fail")
467 }
468 }
469 }
470
471 func createCertChainAndSigner() ([]*x509.Certificate, *signature.ECDSASignerVerifier, error) {
472 sv, _, err := signature.NewECDSASignerVerifier(elliptic.P256(), rand.Reader, crypto.SHA256)
473 if err != nil {
474 return nil, nil, fmt.Errorf("expected NewECDSASignerVerifier to return a signer verifier: %v", err)
475 }
476
477 certChain, err := signer.NewTimestampingCertWithChain(sv)
478 if err != nil {
479 return nil, nil, fmt.Errorf("expected NewTimestampingCertWithChain to return a certificate chain: %v", err)
480 }
481 if len(certChain) != 3 {
482 return nil, nil, fmt.Errorf("expected the certificate chain to have three certificates: %v", err)
483 }
484
485 return certChain, sv, nil
486 }
487
488 func createSignedTimestamp(certChain []*x509.Certificate, sv *signature.ECDSASignerVerifier, tsHasCerts bool) (*timestamp.Timestamp, error) {
489 tsq, err := timestamp.CreateRequest(strings.NewReader("TestRequest"), ×tamp.RequestOptions{
490 Hash: crypto.SHA256,
491 Certificates: tsHasCerts,
492 })
493 if err != nil {
494 return nil, fmt.Errorf("unexpectedly failed to create timestamp request: %v", err)
495 }
496
497 req, err := timestamp.ParseRequest([]byte(tsq))
498 if err != nil {
499 return nil, fmt.Errorf("unexpectedly failed to parse timestamp request: %v", err)
500 }
501
502 tsTemplate := timestamp.Timestamp{
503 HashAlgorithm: req.HashAlgorithm,
504 HashedMessage: req.HashedMessage,
505 Time: time.Now(),
506 Policy: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 2},
507 Ordering: false,
508 Qualified: false,
509 AddTSACertificate: req.Certificates,
510 ExtraExtensions: req.Extensions,
511 }
512
513 resp, err := tsTemplate.CreateResponseWithOpts(certChain[0], sv, crypto.SHA256)
514 if err != nil {
515 return nil, fmt.Errorf("unexpectedly failed to create timestamp response: %v", err)
516 }
517
518 ts, err := timestamp.ParseResponse(resp)
519 if err != nil {
520 return nil, fmt.Errorf("unexpectedly failed to parse timestamp response: %v", err)
521 }
522
523 return ts, nil
524 }
525
526 func TestVerifyTSRWithChain(t *testing.T) {
527 certChain, sv, err := createCertChainAndSigner()
528 if err != nil {
529 t.Errorf("failed to create certificate chain: %v", err)
530 }
531
532 tsWithCerts, err := createSignedTimestamp(certChain, sv, true)
533 if err != nil {
534 t.Errorf("failed to create signed certificate: %v", err)
535 }
536
537 tsWithoutCerts, err := createSignedTimestamp(certChain, sv, false)
538 if err != nil {
539 t.Errorf("failed to create signed certificate: %v", err)
540 }
541
542
543 leaf := certChain[0]
544 intermediate := certChain[1]
545 root := certChain[2]
546
547
548 var invalidIntermediate = *certChain[1]
549 invalidIntermediate.RawIssuer = nil
550 invalidIntermediate.Issuer = pkix.Name{}
551
552 type test struct {
553 name string
554 ts *timestamp.Timestamp
555 opts VerifyOpts
556 expectVerifySuccess bool
557 }
558
559 tests := []test{
560 {
561 name: "Verification is successful with included leaf certificate in timestamp",
562 ts: tsWithCerts,
563 opts: VerifyOpts{
564 Roots: []*x509.Certificate{root},
565 Intermediates: []*x509.Certificate{intermediate},
566 },
567 expectVerifySuccess: true,
568 },
569 {
570 name: "Verification fails due to invalid intermediate certificate",
571 ts: tsWithCerts,
572 opts: VerifyOpts{
573 Roots: []*x509.Certificate{root},
574 Intermediates: []*x509.Certificate{&invalidIntermediate},
575 },
576 expectVerifySuccess: false,
577 },
578 {
579 name: "Verification fails due to missing intermediate certificate",
580 ts: tsWithCerts,
581 opts: VerifyOpts{
582 Roots: []*x509.Certificate{root},
583 },
584 expectVerifySuccess: false,
585 },
586 {
587 name: "Verification fails due to missing root certificate",
588 ts: tsWithCerts,
589 opts: VerifyOpts{
590 Intermediates: []*x509.Certificate{intermediate},
591 },
592 expectVerifySuccess: false,
593 },
594 {
595 name: "Verification fails due to missing root and intermediate certificates",
596 ts: tsWithCerts,
597 opts: VerifyOpts{},
598 expectVerifySuccess: false,
599 },
600 {
601 name: "Verification fails due to missing leaf certificate",
602 ts: tsWithoutCerts,
603 opts: VerifyOpts{
604 Roots: []*x509.Certificate{root},
605 Intermediates: []*x509.Certificate{intermediate},
606 },
607 expectVerifySuccess: false,
608 },
609 {
610 name: "Verification is successful with out of band leaf certificate",
611 ts: tsWithoutCerts,
612 opts: VerifyOpts{
613 Roots: []*x509.Certificate{root},
614 Intermediates: []*x509.Certificate{intermediate},
615 TSACertificate: leaf,
616 },
617 expectVerifySuccess: true,
618 },
619 }
620
621 for _, tc := range tests {
622 err = verifyTSRWithChain(tc.ts, tc.opts)
623 if tc.expectVerifySuccess && err != nil {
624 t.Errorf("test '%s' unexpectedly failed \nExpected verifyTSRWithChain to successfully verify certificate chain, err: %v", tc.name, err)
625 } else if !tc.expectVerifySuccess && err == nil {
626 t.Errorf("testg '%s' unexpectedly passed \nExpected verifyTSRWithChain to fail verification", tc.name)
627 }
628 }
629 }
630
View as plain text