1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cosign
16
17 import (
18 "bytes"
19 "context"
20 "crypto"
21 "crypto/elliptic"
22 "crypto/rand"
23 "crypto/rsa"
24 "crypto/sha256"
25 "crypto/x509"
26 "crypto/x509/pkix"
27 "encoding/base64"
28 "encoding/hex"
29 "encoding/json"
30 "encoding/pem"
31 "errors"
32 "io"
33 "net"
34 "net/url"
35 "strings"
36 "testing"
37 "time"
38
39 "github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
40 "github.com/go-openapi/strfmt"
41 v1 "github.com/google/go-containerregistry/pkg/v1"
42 "github.com/in-toto/in-toto-golang/in_toto"
43 "github.com/secure-systems-lab/go-securesystemslib/dsse"
44 "github.com/sigstore/cosign/v2/internal/pkg/cosign/payload"
45 "github.com/sigstore/cosign/v2/internal/pkg/cosign/rekor/mock"
46 "github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa"
47 tsaMock "github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa/mock"
48 "github.com/sigstore/cosign/v2/pkg/cosign/bundle"
49 "github.com/sigstore/cosign/v2/pkg/oci"
50 "github.com/sigstore/cosign/v2/pkg/oci/static"
51 "github.com/sigstore/cosign/v2/pkg/types"
52 "github.com/sigstore/cosign/v2/test"
53 "github.com/sigstore/rekor/pkg/generated/client"
54 "github.com/sigstore/rekor/pkg/generated/models"
55 rtypes "github.com/sigstore/rekor/pkg/types"
56 "github.com/sigstore/sigstore/pkg/cryptoutils"
57 "github.com/sigstore/sigstore/pkg/signature"
58 "github.com/sigstore/sigstore/pkg/signature/options"
59 "github.com/sigstore/sigstore/pkg/tuf"
60 "github.com/stretchr/testify/require"
61 "github.com/transparency-dev/merkle/rfc6962"
62 )
63
64 type mockVerifier struct {
65 shouldErr bool
66 }
67
68 func (m *mockVerifier) PublicKey(opts ...signature.PublicKeyOption) (crypto.PublicKey, error) {
69 return nil, nil
70 }
71
72 func (m *mockVerifier) VerifySignature(signature, message io.Reader, opts ...signature.VerifyOption) error {
73 if m.shouldErr {
74 return errors.New("failure")
75 }
76 return nil
77 }
78
79 var _ signature.Verifier = (*mockVerifier)(nil)
80
81 type mockAttestation struct {
82 payload interface{}
83 }
84
85 var _ payloader = (*mockAttestation)(nil)
86
87 func (m *mockAttestation) Annotations() (map[string]string, error) {
88 return nil, nil
89 }
90
91 func (m *mockAttestation) Payload() ([]byte, error) {
92 return json.Marshal(m.payload)
93 }
94
95 func (m *mockAttestation) Base64Signature() (string, error) {
96 b, err := json.Marshal(m.payload)
97 return string(b), err
98 }
99
100 func appendSlices(slices [][]byte) []byte {
101 var tmp []byte
102 for _, s := range slices {
103 tmp = append(tmp, s...)
104 }
105 return tmp
106 }
107
108 func Test_verifyOCIAttestation(t *testing.T) {
109 stmt, err := json.Marshal(in_toto.ProvenanceStatementSLSA02{})
110 if err != nil {
111 t.Fatal(err)
112 }
113 valid := map[string]interface{}{
114 "payloadType": types.IntotoPayloadType,
115 "payload": stmt,
116 "signatures": []dsse.Signature{{Sig: base64.StdEncoding.EncodeToString([]byte("foobar"))}},
117 }
118
119 if err := verifyOCIAttestation(context.TODO(), &mockVerifier{}, &mockAttestation{payload: valid}); err != nil {
120 t.Errorf("verifyOCIAttestation() error = %v", err)
121 }
122
123 invalid := map[string]interface{}{
124 "payloadType": "not valid type",
125 "payload": stmt,
126 "signatures": []dsse.Signature{{Sig: base64.StdEncoding.EncodeToString([]byte("foobar"))}},
127 }
128
129
130 if err := verifyOCIAttestation(context.TODO(), &mockVerifier{}, &mockAttestation{payload: invalid}); err == nil {
131 t.Error("verifyOCIAttestation() expected invalid payload type error, got nil")
132 }
133
134 if err := verifyOCIAttestation(context.TODO(), &mockVerifier{shouldErr: true}, &mockAttestation{payload: valid}); err == nil {
135 t.Error("verifyOCIAttestation() expected invalid payload type error, got nil")
136 }
137 }
138
139 func TestVerifyImageSignature(t *testing.T) {
140 rootCert, rootKey, _ := test.GenerateRootCa()
141 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
142 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey)
143 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
144 pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw})
145 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
146
147 rootPool := x509.NewCertPool()
148 rootPool.AddCert(rootCert)
149
150 payload := []byte{1, 2, 3, 4}
151 h := sha256.Sum256(payload)
152 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
153
154 ociSig, _ := static.NewSignature(payload,
155 base64.StdEncoding.EncodeToString(signature),
156 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemSub, pemRoot})))
157 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{},
158 &CheckOpts{
159 RootCerts: rootPool,
160 IgnoreSCT: true,
161 IgnoreTlog: true,
162 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}}})
163 if err != nil {
164 t.Fatalf("unexpected error while verifying signature, expected no error, got %v", err)
165 }
166
167 if verified == true {
168 t.Fatalf("expected verified=false, got verified=true")
169 }
170 }
171
172 func TestVerifyImageSignatureMultipleSubs(t *testing.T) {
173 rootCert, rootKey, _ := test.GenerateRootCa()
174 subCert1, subKey1, _ := test.GenerateSubordinateCa(rootCert, rootKey)
175 subCert2, subKey2, _ := test.GenerateSubordinateCa(subCert1, subKey1)
176 subCert3, subKey3, _ := test.GenerateSubordinateCa(subCert2, subKey2)
177 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert3, subKey3)
178 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
179 pemSub1 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert1.Raw})
180 pemSub2 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert2.Raw})
181 pemSub3 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert3.Raw})
182 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
183
184 rootPool := x509.NewCertPool()
185 rootPool.AddCert(rootCert)
186
187 payload := []byte{1, 2, 3, 4}
188 h := sha256.Sum256(payload)
189 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
190
191 ociSig, _ := static.NewSignature(payload,
192 base64.StdEncoding.EncodeToString(signature), static.WithCertChain(pemLeaf, appendSlices([][]byte{pemSub3, pemSub2, pemSub1, pemRoot})))
193 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{}, &CheckOpts{
194 RootCerts: rootPool,
195 IgnoreSCT: true, IgnoreTlog: true,
196 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}}})
197 if err != nil {
198 t.Fatalf("unexpected error while verifying signature, expected no error, got %v", err)
199 }
200
201 if verified == true {
202 t.Fatalf("expected verified=false, got verified=true")
203 }
204 }
205
206 func signEntry(ctx context.Context, t *testing.T, signer signature.Signer, entry bundle.RekorPayload) []byte {
207 payload, err := json.Marshal(entry)
208 if err != nil {
209 t.Fatalf("marshalling error: %v", err)
210 }
211 canonicalized, err := jsoncanonicalizer.Transform(payload)
212 if err != nil {
213 t.Fatalf("canonicalizing error: %v", err)
214 }
215 signature, err := signer.SignMessage(bytes.NewReader(canonicalized), options.WithContext(ctx))
216 if err != nil {
217 t.Fatalf("signing error: %v", err)
218 }
219 return signature
220 }
221
222 func CreateTestBundle(ctx context.Context, t *testing.T, rekor signature.Signer, leaf []byte) *bundle.RekorBundle {
223
224 pk, _ := rekor.PublicKey(nil)
225 keyID, _ := GetTransparencyLogID(pk)
226 pyld := bundle.RekorPayload{
227 Body: base64.StdEncoding.EncodeToString(leaf),
228 IntegratedTime: time.Now().Unix(),
229 LogIndex: 693591,
230 LogID: keyID,
231 }
232
233 signature := signEntry(ctx, t, rekor, pyld)
234 b := &bundle.RekorBundle{
235 SignedEntryTimestamp: strfmt.Base64(signature),
236 Payload: pyld,
237 }
238 return b
239 }
240
241 func Test_verifySignaturesErrNoSignaturesFound(t *testing.T) {
242 _, _, err := verifySignatures(context.Background(), &fakeOCISignatures{}, v1.Hash{}, nil)
243 var e *ErrNoSignaturesFound
244 if !errors.As(err, &e) {
245 t.Fatalf("%T{%q} is not a %T", err, err, &ErrNoSignaturesFound{})
246 }
247 }
248
249 func Test_verifySignaturesErrNoMatchingSignatures(t *testing.T) {
250 rootCert, rootKey, _ := test.GenerateRootCa()
251 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
252 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey)
253 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
254 pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw})
255 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
256
257 rootPool := x509.NewCertPool()
258 rootPool.AddCert(rootCert)
259
260 payload := []byte{1, 2, 3, 4}
261 h := sha256.Sum256(payload)
262 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
263
264 ociSig, _ := static.NewSignature(payload,
265 base64.StdEncoding.EncodeToString(signature),
266 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemSub, pemRoot})))
267 _, _, err := verifySignatures(context.Background(), &fakeOCISignatures{signatures: []oci.Signature{ociSig}}, v1.Hash{}, &CheckOpts{
268 RootCerts: rootPool,
269 IgnoreSCT: true,
270 IgnoreTlog: true,
271 Identities: []Identity{{Subject: "another-subject@mail.com", Issuer: "oidc-issuer"}}})
272
273 var e *ErrNoMatchingSignatures
274 if !errors.As(err, &e) {
275 t.Fatalf("%T{%q} is not a %T", err, err, &ErrNoMatchingSignatures{})
276 }
277 }
278
279 func TestVerifyImageSignatureWithNoChain(t *testing.T) {
280 ctx := context.Background()
281 rootCert, rootKey, _ := test.GenerateRootCa()
282 sv, _, err := signature.NewECDSASignerVerifier(elliptic.P256(), rand.Reader, crypto.SHA256)
283 if err != nil {
284 t.Fatalf("creating signer: %v", err)
285 }
286
287 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", rootCert, rootKey)
288 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
289
290 rootPool := x509.NewCertPool()
291 rootPool.AddCert(rootCert)
292
293 payload := []byte{1, 2, 3, 4}
294 h := sha256.Sum256(payload)
295 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
296
297
298 pe, _ := proposedEntries(base64.StdEncoding.EncodeToString(signature), payload, pemLeaf)
299 entry, _ := rtypes.UnmarshalEntry(pe[0])
300 leaf, _ := entry.Canonicalize(ctx)
301 rekorBundle := CreateTestBundle(ctx, t, sv, leaf)
302 pemBytes, _ := cryptoutils.MarshalPublicKeyToPEM(sv.Public())
303 rekorPubKeys := NewTrustedTransparencyLogPubKeys()
304 rekorPubKeys.AddTransparencyLogPubKey(pemBytes, tuf.Active)
305
306 opts := []static.Option{static.WithCertChain(pemLeaf, []byte{}), static.WithBundle(rekorBundle)}
307 ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), opts...)
308
309 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{},
310 &CheckOpts{
311 RootCerts: rootPool,
312 IgnoreSCT: true,
313 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}},
314 RekorPubKeys: &rekorPubKeys})
315 if err != nil {
316 t.Fatalf("unexpected error %v", err)
317 }
318 if verified == false {
319 t.Fatalf("expected verified=true, got verified=false")
320 }
321 }
322 func TestVerifyImageSignatureWithInvalidPublicKeyType(t *testing.T) {
323 ctx := context.Background()
324 rootCert, rootKey, _ := test.GenerateRootCa()
325 sv, _, err := signature.NewECDSASignerVerifier(elliptic.P256(), rand.Reader, crypto.SHA256)
326 if err != nil {
327 t.Fatalf("creating signer: %v", err)
328 }
329
330 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", rootCert, rootKey)
331 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
332
333 rootPool := x509.NewCertPool()
334 rootPool.AddCert(rootCert)
335
336 payload := []byte{1, 2, 3, 4}
337 h := sha256.Sum256(payload)
338 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
339
340
341 pe, _ := proposedEntries(base64.StdEncoding.EncodeToString(signature), payload, pemLeaf)
342 entry, _ := rtypes.UnmarshalEntry(pe[0])
343 leaf, _ := entry.Canonicalize(ctx)
344 rekorBundle := CreateTestBundle(ctx, t, sv, leaf)
345 pemBytes, _ := cryptoutils.MarshalPublicKeyToPEM(sv.Public())
346 rekorPubKeys := NewTrustedTransparencyLogPubKeys()
347
348 rekorPubKeys.AddTransparencyLogPubKey(pemBytes, tuf.Active)
349
350 opts := []static.Option{static.WithCertChain(pemLeaf, []byte{}), static.WithBundle(rekorBundle)}
351 ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), opts...)
352
353
354
355 var rsaPrivKey crypto.PrivateKey
356 rsaPrivKey, err = rsa.GenerateKey(rand.Reader, 4096)
357 if err != nil {
358 t.Fatalf("Unable to create RSA test key: %v", err)
359 }
360 var signer crypto.Signer
361 var ok bool
362 if signer, ok = rsaPrivKey.(crypto.Signer); !ok {
363 t.Fatalf("Unable to create signer out of RSA test key: %v", err)
364 }
365 rsaPEM, err := cryptoutils.MarshalPublicKeyToPEM(signer.Public())
366 if err != nil {
367 t.Fatalf("Unable to marshal RSA test key: %v", err)
368 }
369 if err = rekorPubKeys.AddTransparencyLogPubKey(rsaPEM, tuf.Active); err != nil {
370 t.Fatalf("failed to add RSA key to transparency log public keys: %v", err)
371 }
372 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{},
373 &CheckOpts{
374 RootCerts: rootPool,
375 IgnoreSCT: true,
376 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}},
377 RekorPubKeys: &rekorPubKeys})
378 if err == nil {
379 t.Fatal("expected error got none")
380 }
381 if !strings.Contains(err.Error(), "is not type ecdsa.PublicKey") {
382 t.Errorf("did not get expected failure message, wanted 'is not type ecdsa.PublicKey' got: %v", err)
383 }
384 if verified == true {
385 t.Fatalf("expected verified=false, got verified=true")
386 }
387 }
388
389 func TestVerifyImageSignatureWithOnlyRoot(t *testing.T) {
390 rootCert, rootKey, _ := test.GenerateRootCa()
391 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", rootCert, rootKey)
392 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
393 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
394
395 rootPool := x509.NewCertPool()
396 rootPool.AddCert(rootCert)
397
398 payload := []byte{1, 2, 3, 4}
399 h := sha256.Sum256(payload)
400 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
401
402 ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), static.WithCertChain(pemLeaf, pemRoot))
403 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{},
404 &CheckOpts{
405 RootCerts: rootPool,
406 IgnoreSCT: true,
407 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}},
408 IgnoreTlog: true})
409 if err != nil {
410 t.Fatalf("unexpected error while verifying signature, expected no error, got %v", err)
411 }
412
413 if verified == true {
414 t.Fatalf("expected verified=false, got verified=true")
415 }
416 }
417
418 func TestVerifyImageSignatureWithMissingSub(t *testing.T) {
419 rootCert, rootKey, _ := test.GenerateRootCa()
420 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
421 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey)
422 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
423 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
424
425 rootPool := x509.NewCertPool()
426 rootPool.AddCert(rootCert)
427
428 payload := []byte{1, 2, 3, 4}
429 h := sha256.Sum256(payload)
430 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
431
432 ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), static.WithCertChain(pemLeaf, pemRoot))
433 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{},
434 &CheckOpts{
435 RootCerts: rootPool,
436 IgnoreSCT: true,
437 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}},
438 IgnoreTlog: true})
439 if err == nil {
440 t.Fatal("expected error while verifying signature")
441 }
442 if !strings.Contains(err.Error(), "certificate signed by unknown authority") {
443 t.Fatal("expected error while verifying signature")
444 }
445
446 if verified == true {
447 t.Fatalf("expected verified=false, got verified=true")
448 }
449 }
450
451 func TestVerifyImageSignatureWithExistingSub(t *testing.T) {
452 rootCert, rootKey, _ := test.GenerateRootCa()
453 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
454 leafCert, privKey, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey)
455 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
456 pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw})
457 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
458
459 otherSubCert, _, _ := test.GenerateSubordinateCa(rootCert, rootKey)
460
461 rootPool := x509.NewCertPool()
462 rootPool.AddCert(rootCert)
463 subPool := x509.NewCertPool()
464
465 rootPool.AddCert(otherSubCert)
466
467 payload := []byte{1, 2, 3, 4}
468 h := sha256.Sum256(payload)
469 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
470
471 ociSig, _ := static.NewSignature(payload,
472 base64.StdEncoding.EncodeToString(signature),
473 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemSub, pemRoot})))
474 verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{},
475 &CheckOpts{
476 RootCerts: rootPool,
477 IntermediateCerts: subPool,
478 IgnoreSCT: true,
479 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}},
480 IgnoreTlog: true})
481 if err == nil {
482 t.Fatal("expected error while verifying signature")
483 }
484 if !strings.Contains(err.Error(), "certificate signed by unknown authority") {
485 t.Fatal("expected error while verifying signature")
486 }
487
488 if verified == true {
489 t.Fatalf("expected verified=false, got verified=true")
490 }
491 }
492
493 var (
494 lea = models.LogEntryAnon{
495 Attestation: &models.LogEntryAnonAttestation{},
496 Body: base64.StdEncoding.EncodeToString([]byte("asdf")),
497 IntegratedTime: new(int64),
498 LogID: new(string),
499 LogIndex: new(int64),
500 Verification: &models.LogEntryAnonVerification{
501 InclusionProof: &models.InclusionProof{
502 RootHash: new(string),
503 TreeSize: new(int64),
504 LogIndex: new(int64),
505 },
506 },
507 }
508 data = models.LogEntry{
509 uuid(lea): lea,
510 }
511 )
512
513
514
515
516
517
518
519 func uuid(e models.LogEntryAnon) string {
520 entryBytes, err := base64.StdEncoding.DecodeString(e.Body.(string))
521 if err != nil {
522 panic(err)
523 }
524 return hex.EncodeToString(rfc6962.DefaultHasher.HashLeaf(entryBytes))
525 }
526
527
528
529
530
531
532
533
534 func TestVerifyImageSignatureWithSigVerifierAndRekor(t *testing.T) {
535 sv, privKey, err := signature.NewDefaultECDSASignerVerifier()
536 if err != nil {
537 t.Fatalf("error generating verifier: %v", err)
538 }
539
540 payload := []byte{1, 2, 3, 4}
541 h := sha256.Sum256(payload)
542 sig, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
543 ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(sig))
544
545
546
547
548 mClient := new(client.Rekor)
549 mClient.Entries = &mock.EntriesClient{
550 Entries: []*models.LogEntry{&data},
551 }
552
553 if _, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{}, &CheckOpts{
554 SigVerifier: sv,
555 RekorClient: mClient,
556 Identities: []Identity{{Subject: "subject@mail.com", Issuer: "oidc-issuer"}},
557 }); err == nil || !strings.Contains(err.Error(), "no valid tlog entries found no trusted rekor public keys provided") {
558
559
560
561 t.Fatalf("expected error while verifying signature, got %s", err)
562 }
563 }
564
565 func TestVerifyImageSignatureWithSigVerifierAndTSA(t *testing.T) {
566 client, err := tsaMock.NewTSAClient((tsaMock.TSAClientOptions{Time: time.Now()}))
567 if err != nil {
568 t.Fatal(err)
569 }
570
571 sv, _, err := signature.NewDefaultECDSASignerVerifier()
572 if err != nil {
573 t.Fatalf("error generating verifier: %v", err)
574 }
575 payloadSigner := payload.NewSigner(sv)
576 testSigner := tsa.NewSigner(payloadSigner, client)
577
578 certChainPEM, err := cryptoutils.MarshalCertificatesToPEM(client.CertChain)
579 if err != nil {
580 t.Fatalf("unexpected error marshalling cert chain: %v", err)
581 }
582
583 leaves, intermediates, roots, err := tsa.SplitPEMCertificateChain(certChainPEM)
584 if err != nil {
585 t.Fatal("error splitting response into certificate chain")
586 }
587
588 payload := []byte{1, 2, 3, 4}
589 sig, _, err := testSigner.Sign(context.Background(), bytes.NewReader(payload))
590 if err != nil {
591 t.Fatalf("error signing the payload with the tsa client server: %v", err)
592 }
593 if bundleVerified, err := VerifyImageSignature(context.TODO(), sig, v1.Hash{}, &CheckOpts{
594 SigVerifier: sv,
595 TSACertificate: leaves[0],
596 TSAIntermediateCertificates: intermediates,
597 TSARootCertificates: roots,
598 IgnoreTlog: true,
599 }); err != nil || bundleVerified {
600 t.Fatalf("unexpected error while verifying signature, got %v", err)
601 }
602 }
603
604 func TestVerifyImageSignatureWithSigVerifierAndRekorTSA(t *testing.T) {
605
606
607
608 mClient := new(client.Rekor)
609 mClient.Entries = &mock.EntriesClient{
610 Entries: []*models.LogEntry{&data},
611 }
612
613 client, err := tsaMock.NewTSAClient((tsaMock.TSAClientOptions{Time: time.Now()}))
614 if err != nil {
615 t.Fatal(err)
616 }
617 sv, _, err := signature.NewDefaultECDSASignerVerifier()
618 if err != nil {
619 t.Fatalf("error generating verifier: %v", err)
620 }
621 payloadSigner := payload.NewSigner(sv)
622 tsaSigner := tsa.NewSigner(payloadSigner, client)
623
624 certChainPEM, err := cryptoutils.MarshalCertificatesToPEM(client.CertChain)
625 if err != nil {
626 t.Fatalf("unexpected error marshalling cert chain: %v", err)
627 }
628
629 leaves, intermediates, roots, err := tsa.SplitPEMCertificateChain(certChainPEM)
630 if err != nil {
631 t.Fatal("error splitting response into certificate chain")
632 }
633
634 payload := []byte{1, 2, 3, 4}
635 sig, _, err := tsaSigner.Sign(context.Background(), bytes.NewReader(payload))
636 if err != nil {
637 t.Fatalf("error signing the payload with the rekor and tsa clients: %v", err)
638 }
639 if _, err := VerifyImageSignature(context.TODO(), sig, v1.Hash{}, &CheckOpts{
640 SigVerifier: sv,
641 TSACertificate: leaves[0],
642 TSAIntermediateCertificates: intermediates,
643 TSARootCertificates: roots,
644 RekorClient: mClient,
645 }); err == nil || !strings.Contains(err.Error(), "no trusted rekor public keys provided") {
646
647
648
649
650
651
652
653 t.Fatalf("expected error while verifying signature, got %s", err)
654 }
655 }
656
657 func TestValidateAndUnpackCertSuccess(t *testing.T) {
658 subject := "email@email"
659 oidcIssuer := "https://accounts.google.com"
660
661 rootCert, rootKey, _ := test.GenerateRootCa()
662 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
663
664 rootPool := x509.NewCertPool()
665 rootPool.AddCert(rootCert)
666
667 co := &CheckOpts{
668 RootCerts: rootPool,
669 IgnoreSCT: true,
670 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
671 }
672
673 _, err := ValidateAndUnpackCert(leafCert, co)
674 if err != nil {
675 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
676 }
677 err = CheckCertificatePolicy(leafCert, co)
678 if err != nil {
679 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
680 }
681 }
682
683 func TestValidateAndUnpackCertSuccessAllowAllValues(t *testing.T) {
684 subject := "email@email"
685 oidcIssuer := "https://accounts.google.com"
686
687 rootCert, rootKey, _ := test.GenerateRootCa()
688 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
689
690 rootPool := x509.NewCertPool()
691 rootPool.AddCert(rootCert)
692
693 co := &CheckOpts{
694 RootCerts: rootPool,
695 IgnoreSCT: true,
696 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
697 }
698
699 _, err := ValidateAndUnpackCert(leafCert, co)
700 if err != nil {
701 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
702 }
703 err = CheckCertificatePolicy(leafCert, co)
704 if err != nil {
705 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
706 }
707 }
708
709 func TestValidateAndUnpackCertWithoutRequiredSCT(t *testing.T) {
710 subject := "email@email"
711 oidcIssuer := "https://accounts.google.com"
712
713 rootCert, rootKey, _ := test.GenerateRootCa()
714 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
715
716 rootPool := x509.NewCertPool()
717 rootPool.AddCert(rootCert)
718
719 co := &CheckOpts{
720 RootCerts: rootPool,
721 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
722
723 IgnoreSCT: false,
724 }
725
726 _, err := ValidateAndUnpackCert(leafCert, co)
727 require.Contains(t, err.Error(), "certificate does not include required embedded SCT")
728 }
729
730 func TestValidateAndUnpackCertSuccessWithDnsSan(t *testing.T) {
731 subject := "example.com"
732 oidcIssuer := "https://accounts.google.com"
733
734 rootCert, rootKey, _ := test.GenerateRootCa()
735 leafCert, _, _ := test.GenerateLeafCertWithSubjectAlternateNames(
736 []string{subject},
737 nil,
738 nil,
739 nil,
740 oidcIssuer,
741 rootCert,
742 rootKey)
743
744 rootPool := x509.NewCertPool()
745 rootPool.AddCert(rootCert)
746
747 co := &CheckOpts{
748 RootCerts: rootPool,
749 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
750 IgnoreSCT: true,
751 }
752
753 _, err := ValidateAndUnpackCert(leafCert, co)
754 if err != nil {
755 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
756 }
757 err = CheckCertificatePolicy(leafCert, co)
758 if err != nil {
759 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
760 }
761 }
762
763 func TestValidateAndUnpackCertSuccessWithEmailSan(t *testing.T) {
764 subject := "email@email"
765 oidcIssuer := "https://accounts.google.com"
766
767 rootCert, rootKey, _ := test.GenerateRootCa()
768 leafCert, _, _ := test.GenerateLeafCertWithSubjectAlternateNames(
769 nil,
770 []string{subject},
771 nil,
772 nil,
773 oidcIssuer,
774 rootCert,
775 rootKey)
776
777 rootPool := x509.NewCertPool()
778 rootPool.AddCert(rootCert)
779
780 co := &CheckOpts{
781 RootCerts: rootPool,
782 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
783 IgnoreSCT: true,
784 }
785
786 _, err := ValidateAndUnpackCert(leafCert, co)
787 if err != nil {
788 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
789 }
790 err = CheckCertificatePolicy(leafCert, co)
791 if err != nil {
792 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
793 }
794 }
795
796 func TestValidateAndUnpackCertSuccessWithIpAddressSan(t *testing.T) {
797 subject := "127.0.0.1"
798 oidcIssuer := "https://accounts.google.com"
799
800 rootCert, rootKey, _ := test.GenerateRootCa()
801 leafCert, _, _ := test.GenerateLeafCertWithSubjectAlternateNames(
802 nil,
803 nil,
804 []net.IP{net.ParseIP(subject)},
805 nil,
806 oidcIssuer,
807 rootCert,
808 rootKey)
809
810 rootPool := x509.NewCertPool()
811 rootPool.AddCert(rootCert)
812
813 co := &CheckOpts{
814 RootCerts: rootPool,
815 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
816 IgnoreSCT: true,
817 }
818
819 _, err := ValidateAndUnpackCert(leafCert, co)
820 if err != nil {
821 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
822 }
823 err = CheckCertificatePolicy(leafCert, co)
824 if err != nil {
825 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
826 }
827 }
828
829 func TestValidateAndUnpackCertSuccessWithUriSan(t *testing.T) {
830 subject, _ := url.Parse("scheme://userinfo@host")
831 oidcIssuer := "https://accounts.google.com"
832
833 rootCert, rootKey, _ := test.GenerateRootCa()
834 leafCert, _, _ := test.GenerateLeafCertWithSubjectAlternateNames(
835 nil,
836 nil,
837 nil,
838 []*url.URL{subject},
839 oidcIssuer,
840 rootCert,
841 rootKey)
842
843 rootPool := x509.NewCertPool()
844 rootPool.AddCert(rootCert)
845
846 co := &CheckOpts{
847 RootCerts: rootPool,
848 Identities: []Identity{{Subject: "scheme://userinfo@host", Issuer: oidcIssuer}},
849 IgnoreSCT: true,
850 }
851
852 _, err := ValidateAndUnpackCert(leafCert, co)
853 if err != nil {
854 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
855 }
856 err = CheckCertificatePolicy(leafCert, co)
857 if err != nil {
858 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
859 }
860 }
861
862 func TestValidateAndUnpackCertSuccessWithOtherNameSan(t *testing.T) {
863
864 subject := "subject-othername"
865 ext, err := cryptoutils.MarshalOtherNameSAN(subject, true)
866 if err != nil {
867 t.Fatalf("error marshalling SANs: %v", err)
868 }
869 exts := []pkix.Extension{*ext}
870
871 oidcIssuer := "https://accounts.google.com"
872
873 rootCert, rootKey, _ := test.GenerateRootCa()
874 leafCert, _, _ := test.GenerateLeafCert("unused", oidcIssuer, rootCert, rootKey, exts...)
875
876 rootPool := x509.NewCertPool()
877 rootPool.AddCert(rootCert)
878
879 co := &CheckOpts{
880 RootCerts: rootPool,
881 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
882 IgnoreSCT: true,
883 }
884
885 _, err = ValidateAndUnpackCert(leafCert, co)
886 if err != nil {
887 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
888 }
889 err = CheckCertificatePolicy(leafCert, co)
890 if err != nil {
891 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
892 }
893 }
894
895 func TestValidateAndUnpackCertInvalidRoot(t *testing.T) {
896 subject := "email@email"
897 oidcIssuer := "https://accounts.google.com"
898
899 rootCert, rootKey, _ := test.GenerateRootCa()
900 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
901
902 otherRoot, _, _ := test.GenerateRootCa()
903
904 rootPool := x509.NewCertPool()
905 rootPool.AddCert(otherRoot)
906
907 co := &CheckOpts{
908 RootCerts: rootPool,
909 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
910 IgnoreSCT: true,
911 }
912
913 _, err := ValidateAndUnpackCert(leafCert, co)
914 require.Contains(t, err.Error(), "certificate signed by unknown authority")
915 }
916
917 func TestValidateAndUnpackCertInvalidOidcIssuer(t *testing.T) {
918 subject := "email@email"
919 oidcIssuer := "https://accounts.google.com"
920
921 rootCert, rootKey, _ := test.GenerateRootCa()
922 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
923
924 rootPool := x509.NewCertPool()
925 rootPool.AddCert(rootCert)
926
927 co := &CheckOpts{
928 RootCerts: rootPool,
929 Identities: []Identity{{Subject: subject, Issuer: "other"}},
930 IgnoreSCT: true,
931 }
932
933 _, err := ValidateAndUnpackCert(leafCert, co)
934 require.Contains(t, err.Error(), "none of the expected identities matched what was in the certificate")
935 err = CheckCertificatePolicy(leafCert, co)
936 require.Contains(t, err.Error(), "none of the expected identities matched what was in the certificate")
937 }
938
939 func TestValidateAndUnpackCertInvalidEmail(t *testing.T) {
940 subject := "email@email"
941 oidcIssuer := "https://accounts.google.com"
942
943 rootCert, rootKey, _ := test.GenerateRootCa()
944 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
945
946 rootPool := x509.NewCertPool()
947 rootPool.AddCert(rootCert)
948
949 co := &CheckOpts{
950 RootCerts: rootPool,
951 Identities: []Identity{{Subject: "other", Issuer: oidcIssuer}},
952 IgnoreSCT: true,
953 }
954
955 _, err := ValidateAndUnpackCert(leafCert, co)
956 require.Contains(t, err.Error(), "none of the expected identities matched what was in the certificate")
957 err = CheckCertificatePolicy(leafCert, co)
958 require.Contains(t, err.Error(), "none of the expected identities matched what was in the certificate")
959 }
960
961 func TestValidateAndUnpackCertInvalidGithubWorkflowTrigger(t *testing.T) {
962 subject := "email@email"
963 oidcIssuer := "https://accounts.google.com"
964 githubWorkFlowTrigger := "myTrigger"
965
966 rootCert, rootKey, _ := test.GenerateRootCa()
967 leafCert, _, _ := test.GenerateLeafCertWithGitHubOIDs(subject, oidcIssuer, githubWorkFlowTrigger, "", "", "", "", rootCert, rootKey)
968
969 rootPool := x509.NewCertPool()
970 rootPool.AddCert(rootCert)
971
972 co := &CheckOpts{
973 RootCerts: rootPool,
974 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
975 CertGithubWorkflowTrigger: "otherTrigger",
976 IgnoreSCT: true,
977 }
978
979 _, err := ValidateAndUnpackCert(leafCert, co)
980 require.Contains(t, err.Error(), "expected GitHub Workflow Trigger not found in certificate")
981 err = CheckCertificatePolicy(leafCert, co)
982 require.Contains(t, err.Error(), "expected GitHub Workflow Trigger not found in certificate")
983 }
984
985 func TestValidateAndUnpackCertInvalidGithubWorkflowSHA(t *testing.T) {
986 subject := "email@email"
987 oidcIssuer := "https://accounts.google.com"
988 githubWorkFlowSha := "mySHA"
989
990 rootCert, rootKey, _ := test.GenerateRootCa()
991 leafCert, _, _ := test.GenerateLeafCertWithGitHubOIDs(subject, oidcIssuer, "", githubWorkFlowSha, "", "", "", rootCert, rootKey)
992
993 rootPool := x509.NewCertPool()
994 rootPool.AddCert(rootCert)
995
996 co := &CheckOpts{
997 RootCerts: rootPool,
998 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
999 CertGithubWorkflowSha: "otherSHA",
1000 IgnoreSCT: true,
1001 }
1002
1003 _, err := ValidateAndUnpackCert(leafCert, co)
1004 require.Contains(t, err.Error(), "expected GitHub Workflow SHA not found in certificate")
1005 err = CheckCertificatePolicy(leafCert, co)
1006 require.Contains(t, err.Error(), "expected GitHub Workflow SHA not found in certificate")
1007 }
1008
1009 func TestValidateAndUnpackCertInvalidGithubWorkflowName(t *testing.T) {
1010 subject := "email@email"
1011 oidcIssuer := "https://accounts.google.com"
1012 githubWorkFlowName := "myName"
1013
1014 rootCert, rootKey, _ := test.GenerateRootCa()
1015 leafCert, _, _ := test.GenerateLeafCertWithGitHubOIDs(subject, oidcIssuer, "", "", githubWorkFlowName, "", "", rootCert, rootKey)
1016
1017 rootPool := x509.NewCertPool()
1018 rootPool.AddCert(rootCert)
1019
1020 co := &CheckOpts{
1021 RootCerts: rootPool,
1022 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1023 CertGithubWorkflowName: "otherName",
1024 IgnoreSCT: true,
1025 }
1026
1027 _, err := ValidateAndUnpackCert(leafCert, co)
1028 require.Contains(t, err.Error(), "expected GitHub Workflow Name not found in certificate")
1029 err = CheckCertificatePolicy(leafCert, co)
1030 require.Contains(t, err.Error(), "expected GitHub Workflow Name not found in certificate")
1031 }
1032
1033 func TestValidateAndUnpackCertInvalidGithubWorkflowRepository(t *testing.T) {
1034 subject := "email@email"
1035 oidcIssuer := "https://accounts.google.com"
1036 githubWorkFlowRepository := "myRepository"
1037
1038 rootCert, rootKey, _ := test.GenerateRootCa()
1039 leafCert, _, _ := test.GenerateLeafCertWithGitHubOIDs(subject, oidcIssuer, "", "", "", githubWorkFlowRepository, "", rootCert, rootKey)
1040
1041 rootPool := x509.NewCertPool()
1042 rootPool.AddCert(rootCert)
1043
1044 co := &CheckOpts{
1045 RootCerts: rootPool,
1046 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1047 CertGithubWorkflowRepository: "otherRepository",
1048 IgnoreSCT: true,
1049 }
1050
1051 _, err := ValidateAndUnpackCert(leafCert, co)
1052 require.Contains(t, err.Error(), "expected GitHub Workflow Repository not found in certificate")
1053 err = CheckCertificatePolicy(leafCert, co)
1054 require.Contains(t, err.Error(), "expected GitHub Workflow Repository not found in certificate")
1055 }
1056
1057 func TestValidateAndUnpackCertInvalidGithubWorkflowRef(t *testing.T) {
1058 subject := "email@email"
1059 oidcIssuer := "https://accounts.google.com"
1060 githubWorkFlowRef := "myRef"
1061
1062 rootCert, rootKey, _ := test.GenerateRootCa()
1063 leafCert, _, _ := test.GenerateLeafCertWithGitHubOIDs(subject, oidcIssuer, "", "", "", "", githubWorkFlowRef, rootCert, rootKey)
1064
1065 rootPool := x509.NewCertPool()
1066 rootPool.AddCert(rootCert)
1067
1068 co := &CheckOpts{
1069 RootCerts: rootPool,
1070 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1071 CertGithubWorkflowRef: "otherRef",
1072 IgnoreSCT: true,
1073 }
1074
1075 _, err := ValidateAndUnpackCert(leafCert, co)
1076 require.Contains(t, err.Error(), "expected GitHub Workflow Ref not found in certificate")
1077 err = CheckCertificatePolicy(leafCert, co)
1078 require.Contains(t, err.Error(), "expected GitHub Workflow Ref not found in certificate")
1079 }
1080
1081 func TestValidateAndUnpackCertWithChainSuccess(t *testing.T) {
1082 subject := "email@email"
1083 oidcIssuer := "https://accounts.google.com"
1084
1085 rootCert, rootKey, _ := test.GenerateRootCa()
1086 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
1087 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, subCert, subKey)
1088
1089 co := &CheckOpts{
1090 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1091 IgnoreSCT: true,
1092 }
1093
1094 _, err := ValidateAndUnpackCertWithChain(leafCert, []*x509.Certificate{subCert, leafCert}, co)
1095 if err != nil {
1096 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
1097 }
1098 }
1099
1100 func TestValidateAndUnpackCertWithChainSuccessWithRoot(t *testing.T) {
1101 subject := "email@email"
1102 oidcIssuer := "https://accounts.google.com"
1103
1104 rootCert, rootKey, _ := test.GenerateRootCa()
1105 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
1106
1107 co := &CheckOpts{
1108 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1109 IgnoreSCT: true,
1110 }
1111
1112 _, err := ValidateAndUnpackCertWithChain(leafCert, []*x509.Certificate{rootCert}, co)
1113 if err != nil {
1114 t.Errorf("ValidateAndUnpackCert expected no error, got err = %v", err)
1115 }
1116 }
1117
1118 func TestValidateAndUnpackCertWithChainFailsWithoutChain(t *testing.T) {
1119 subject := "email@email"
1120 oidcIssuer := "https://accounts.google.com"
1121
1122 rootCert, rootKey, _ := test.GenerateRootCa()
1123 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
1124
1125 co := &CheckOpts{
1126 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1127 IgnoreSCT: true,
1128 }
1129
1130 _, err := ValidateAndUnpackCertWithChain(leafCert, []*x509.Certificate{}, co)
1131 if err == nil || err.Error() != "no chain provided to validate certificate" {
1132 t.Errorf("expected error without chain, got %v", err)
1133 }
1134 }
1135
1136 func TestValidateAndUnpackCertWithChainFailsWithInvalidChain(t *testing.T) {
1137 subject := "email@email"
1138 oidcIssuer := "https://accounts.google.com"
1139
1140 rootCert, rootKey, _ := test.GenerateRootCa()
1141 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, rootCert, rootKey)
1142 rootCertOther, _, _ := test.GenerateRootCa()
1143
1144 co := &CheckOpts{
1145 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1146 IgnoreSCT: true,
1147 }
1148
1149 _, err := ValidateAndUnpackCertWithChain(leafCert, []*x509.Certificate{rootCertOther}, co)
1150 if err == nil || !strings.Contains(err.Error(), "certificate signed by unknown authority") {
1151 t.Errorf("expected error without valid chain, got %v", err)
1152 }
1153 }
1154
1155 func TestValidateAndUnpackCertWithIdentities(t *testing.T) {
1156 u, err := url.Parse("http://url.example.com")
1157 if err != nil {
1158 t.Fatal("failed to parse url", err)
1159 }
1160 emailSubject := "email@example.com"
1161 dnsSubjects := []string{"dnssubject.example.com"}
1162 ipSubjects := []net.IP{net.ParseIP("1.2.3.4")}
1163 uriSubjects := []*url.URL{u}
1164 otherName := "email!example.com"
1165 oidcIssuer := "https://accounts.google.com"
1166
1167 tests := []struct {
1168 identities []Identity
1169 wantErrSubstring string
1170 dnsNames []string
1171 emailAddresses []string
1172 ipAddresses []net.IP
1173 uris []*url.URL
1174 otherName string
1175 }{
1176 {identities: nil },
1177 {identities: []Identity{
1178 {Subject: emailSubject, Issuer: oidcIssuer}},
1179 emailAddresses: []string{emailSubject}},
1180 {identities: []Identity{
1181 {Issuer: oidcIssuer}},
1182 emailAddresses: []string{emailSubject}},
1183 {identities: []Identity{
1184 {Subject: emailSubject}},
1185 emailAddresses: []string{emailSubject}},
1186 {identities: []Identity{
1187 {Subject: "wrongsubject", Issuer: oidcIssuer},
1188 {Subject: emailSubject, Issuer: "wrongissuer"}},
1189 emailAddresses: []string{emailSubject},
1190 wantErrSubstring: "none of the expected identities matched"},
1191 {identities: []Identity{
1192 {Subject: "wrongsubject", Issuer: "wrongissuer"},
1193 {Subject: emailSubject, Issuer: oidcIssuer}},
1194 emailAddresses: []string{emailSubject}},
1195 {identities: []Identity{
1196 {SubjectRegExp: "****", Issuer: oidcIssuer}},
1197 emailAddresses: []string{emailSubject},
1198 wantErrSubstring: "malformed subject in identity"},
1199 {identities: []Identity{
1200 {Subject: emailSubject, IssuerRegExp: "****"}},
1201 wantErrSubstring: "malformed issuer in identity"},
1202 {identities: []Identity{
1203 {SubjectRegExp: ".*example.com", IssuerRegExp: ".*accounts.google.*"}},
1204 emailAddresses: []string{emailSubject},
1205 wantErrSubstring: ""},
1206 {identities: []Identity{
1207 {SubjectRegExp: ".*ubject.example.com", IssuerRegExp: ".*accounts.google.*"}},
1208 dnsNames: dnsSubjects,
1209 wantErrSubstring: ""},
1210 {identities: []Identity{
1211 {SubjectRegExp: "1.2.3.*", IssuerRegExp: ".*accounts.google.*"}},
1212 ipAddresses: ipSubjects,
1213 wantErrSubstring: ""},
1214 {identities: []Identity{
1215 {SubjectRegExp: ".*url.examp.*", IssuerRegExp: ".*accounts.google.*"}},
1216 uris: uriSubjects,
1217 wantErrSubstring: ""},
1218 {identities: []Identity{
1219 {SubjectRegExp: ".*example.com", IssuerRegExp: ".*accounts.google.*"}},
1220 otherName: otherName,
1221 wantErrSubstring: ""},
1222 }
1223 for _, tc := range tests {
1224 rootCert, rootKey, _ := test.GenerateRootCa()
1225 var leafCert *x509.Certificate
1226 if len(tc.otherName) == 0 {
1227 leafCert, _, _ = test.GenerateLeafCertWithSubjectAlternateNames(tc.dnsNames, tc.emailAddresses, tc.ipAddresses, tc.uris, oidcIssuer, rootCert, rootKey)
1228 } else {
1229
1230 ext, err := cryptoutils.MarshalOtherNameSAN(tc.otherName, true)
1231 if err != nil {
1232 t.Fatalf("error marshalling SANs: %v", err)
1233 }
1234 exts := []pkix.Extension{*ext}
1235 leafCert, _, _ = test.GenerateLeafCert("unused", oidcIssuer, rootCert, rootKey, exts...)
1236 }
1237
1238 rootPool := x509.NewCertPool()
1239 rootPool.AddCert(rootCert)
1240
1241 co := &CheckOpts{
1242 RootCerts: rootPool,
1243 Identities: tc.identities,
1244 IgnoreSCT: true,
1245 }
1246
1247 _, err := ValidateAndUnpackCert(leafCert, co)
1248 if err == nil && tc.wantErrSubstring != "" {
1249 t.Errorf("Expected error %s got none", tc.wantErrSubstring)
1250 } else if err != nil {
1251 if tc.wantErrSubstring == "" {
1252 t.Errorf("Did not expect an error, got err = %v", err)
1253 } else if !strings.Contains(err.Error(), tc.wantErrSubstring) {
1254 t.Errorf("Did not get the expected error %s, got err = %v", tc.wantErrSubstring, err)
1255 }
1256 }
1257
1258 err = CheckCertificatePolicy(leafCert, co)
1259 if err == nil && tc.wantErrSubstring != "" {
1260 t.Errorf("Expected error %s got none", tc.wantErrSubstring)
1261 } else if err != nil {
1262 if tc.wantErrSubstring == "" {
1263 t.Errorf("Did not expect an error, got err = %v", err)
1264 } else if !strings.Contains(err.Error(), tc.wantErrSubstring) {
1265 t.Errorf("Did not get the expected error %s, got err = %v", tc.wantErrSubstring, err)
1266 }
1267 }
1268 }
1269 }
1270
1271 func TestValidateAndUnpackCertWithIntermediatesSuccess(t *testing.T) {
1272 subject := "email@email"
1273 oidcIssuer := "https://accounts.google.com"
1274
1275 rootCert, rootKey, _ := test.GenerateRootCa()
1276 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
1277 leafCert, _, _ := test.GenerateLeafCert(subject, oidcIssuer, subCert, subKey)
1278
1279 rootPool := x509.NewCertPool()
1280 rootPool.AddCert(rootCert)
1281 subPool := x509.NewCertPool()
1282 rootPool.AddCert(subCert)
1283
1284 co := &CheckOpts{
1285 RootCerts: rootPool,
1286 IgnoreSCT: true,
1287 Identities: []Identity{{Subject: subject, Issuer: oidcIssuer}},
1288 }
1289
1290 _, err := ValidateAndUnpackCertWithIntermediates(leafCert, co, subPool)
1291 if err != nil {
1292 t.Errorf("ValidateAndUnpackCertWithIntermediates expected no error, got err = %v", err)
1293 }
1294 err = CheckCertificatePolicy(leafCert, co)
1295 if err != nil {
1296 t.Errorf("CheckCertificatePolicy expected no error, got err = %v", err)
1297 }
1298 }
1299
1300 func TestCompareSigs(t *testing.T) {
1301
1302 tests := []struct {
1303 description string
1304 b64sig string
1305 bundleBody string
1306 shouldErr bool
1307 }{
1308 {
1309 description: "sigs match",
1310 b64sig: "MEQCIDO3XHbLovPWK+bk8ItCig2cwlr/8MXbLvz3UFzxMGIMAiA1lqdM9IqqUvCUqzOjufTq3sKU3qSn7R5tPqPz0ddNwQ==",
1311 bundleBody: `eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIzODE1MmQxZGQzMjZhZjQwNWY4OTlkYmNjMmNlMzUwYjVmMTZkNDVkZjdmMjNjNDg4ZjQ4NTBhZmExY2Q4NmQxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRE8zWEhiTG92UFdLK2JrOEl0Q2lnMmN3bHIvOE1YYkx2ejNVRnp4TUdJTUFpQTFscWRNOUlxcVV2Q1Vxek9qdWZUcTNzS1UzcVNuN1I1dFBxUHowZGROd1E9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGVUN0RVIyb3ZXWFV4VG5vd01XVjVSV2hVZDNRMlQya3hXV3BGWXdwSloxRldjRlZTTjB0bUwwSm1hVk16Y1ZReFVHd3dkbGh3ZUZwNVMyWkpSMHMyZWxoQ04ybE5aV3RFVTA1M1dHWldPSEpKYUdaMmRrOW5QVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=`,
1312 },
1313 {
1314 description: "sigs don't match",
1315 b64sig: "bm9wZQo=",
1316 bundleBody: `eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIzODE1MmQxZGQzMjZhZjQwNWY4OTlkYmNjMmNlMzUwYjVmMTZkNDVkZjdmMjNjNDg4ZjQ4NTBhZmExY2Q4NmQxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRE8zWEhiTG92UFdLK2JrOEl0Q2lnMmN3bHIvOE1YYkx2ejNVRnp4TUdJTUFpQTFscWRNOUlxcVV2Q1Vxek9qdWZUcTNzS1UzcVNuN1I1dFBxUHowZGROd1E9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGVUN0RVIyb3ZXWFV4VG5vd01XVjVSV2hVZDNRMlQya3hXV3BGWXdwSloxRldjRlZTTjB0bUwwSm1hVk16Y1ZReFVHd3dkbGh3ZUZwNVMyWkpSMHMyZWxoQ04ybE5aV3RFVTA1M1dHWldPSEpKYUdaMmRrOW5QVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=`,
1317 shouldErr: true,
1318 },
1319 }
1320 for _, test := range tests {
1321 t.Run(test.description, func(t *testing.T) {
1322 sig, err := static.NewSignature([]byte("payload"), test.b64sig)
1323 if err != nil {
1324 t.Fatalf("failed to create static signature: %v", err)
1325 }
1326 err = compareSigs(test.bundleBody, sig)
1327 if err == nil && test.shouldErr {
1328 t.Fatal("test should have errored")
1329 }
1330 if err != nil && !test.shouldErr {
1331 t.Fatal(err)
1332 }
1333 })
1334 }
1335 }
1336
1337 func TestTrustedCertSuccess(t *testing.T) {
1338 rootCert, rootKey, _ := test.GenerateRootCa()
1339 subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
1340 leafCert, _, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey)
1341
1342 rootPool := x509.NewCertPool()
1343 rootPool.AddCert(rootCert)
1344 subPool := x509.NewCertPool()
1345 subPool.AddCert(subCert)
1346
1347 chains, err := TrustedCert(leafCert, rootPool, subPool)
1348 if err != nil {
1349 t.Fatalf("expected no error verifying certificate, got %v", err)
1350 }
1351 if len(chains) != 1 {
1352 t.Fatalf("unexpected number of chains found, expected 1, got %v", len(chains))
1353 }
1354 if len(chains[0]) != 3 {
1355 t.Fatalf("unexpected number of certs in chain, expected 3, got %v", len(chains[0]))
1356 }
1357 }
1358
1359 func TestTrustedCertSuccessNoIntermediates(t *testing.T) {
1360 rootCert, rootKey, _ := test.GenerateRootCa()
1361 leafCert, _, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", rootCert, rootKey)
1362
1363 rootPool := x509.NewCertPool()
1364 rootPool.AddCert(rootCert)
1365
1366 _, err := TrustedCert(leafCert, rootPool, nil)
1367 if err != nil {
1368 t.Fatalf("expected no error verifying certificate, got %v", err)
1369 }
1370 }
1371
1372
1373
1374 func TestTrustedCertSuccessChainFromRoot(t *testing.T) {
1375 rootCert, rootKey, _ := test.GenerateRootCa()
1376 leafCert, _, _ := test.GenerateLeafCert("subject@mail.com", "oidc-issuer", rootCert, rootKey)
1377 subCert, _, _ := test.GenerateSubordinateCa(rootCert, rootKey)
1378
1379 rootPool := x509.NewCertPool()
1380 rootPool.AddCert(rootCert)
1381 subPool := x509.NewCertPool()
1382 subPool.AddCert(subCert)
1383
1384 _, err := TrustedCert(leafCert, rootPool, subPool)
1385 if err != nil {
1386 t.Fatalf("expected no error verifying certificate, got %v", err)
1387 }
1388 }
1389
1390 func TestVerifyRFC3161Timestamp(t *testing.T) {
1391
1392 rootCert, rootKey, _ := test.GenerateRootCa()
1393 leafCert, privKey, _ := test.GenerateLeafCert("subject", "oidc-issuer", rootCert, rootKey)
1394 pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
1395 pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
1396 payload := []byte{1, 2, 3, 4}
1397 h := sha256.Sum256(payload)
1398 signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
1399
1400 client, err := tsaMock.NewTSAClient((tsaMock.TSAClientOptions{Time: time.Now()}))
1401 if err != nil {
1402 t.Fatal(err)
1403 }
1404
1405 tsBytes, err := tsa.GetTimestampedSignature(signature, client)
1406 if err != nil {
1407 t.Fatalf("unexpected error creating timestamp: %v", err)
1408 }
1409 rfc3161TS := bundle.RFC3161Timestamp{SignedRFC3161Timestamp: tsBytes}
1410
1411 certChainPEM, err := cryptoutils.MarshalCertificatesToPEM(client.CertChain)
1412 if err != nil {
1413 t.Fatalf("unexpected error marshalling cert chain: %v", err)
1414 }
1415
1416 leaves, intermediates, roots, err := tsa.SplitPEMCertificateChain(certChainPEM)
1417 if err != nil {
1418 t.Fatal("error splitting response into certificate chain")
1419 }
1420
1421 ociSig, _ := static.NewSignature(payload,
1422 base64.StdEncoding.EncodeToString(signature),
1423 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemRoot})),
1424 static.WithRFC3161Timestamp(&rfc3161TS))
1425
1426
1427 ts, err := VerifyRFC3161Timestamp(ociSig, &CheckOpts{
1428 TSACertificate: leaves[0],
1429 TSAIntermediateCertificates: intermediates,
1430 TSARootCertificates: roots,
1431 })
1432 if err != nil {
1433 t.Fatalf("unexpected error verifying timestamp with signature: %v", err)
1434 }
1435 if err := CheckExpiry(leafCert, ts.Time); err != nil {
1436 t.Fatalf("unexpected error using time from timestamp to verify certificate: %v", err)
1437 }
1438
1439
1440 tsBytes, err = tsa.GetTimestampedSignature(payload, client)
1441 if err != nil {
1442 t.Fatalf("unexpected error creating timestamp: %v", err)
1443 }
1444 rfc3161TS = bundle.RFC3161Timestamp{SignedRFC3161Timestamp: tsBytes}
1445 ociSig, _ = static.NewSignature(payload,
1446 "",
1447 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemRoot})),
1448 static.WithRFC3161Timestamp(&rfc3161TS))
1449 _, err = VerifyRFC3161Timestamp(ociSig, &CheckOpts{
1450 TSACertificate: leaves[0],
1451 TSAIntermediateCertificates: intermediates,
1452 TSARootCertificates: roots,
1453 })
1454 if err != nil {
1455 t.Fatalf("unexpected error verifying timestamp with payload: %v", err)
1456 }
1457
1458
1459 ociSig, _ = static.NewSignature(payload,
1460 string(signature),
1461 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemRoot})),
1462 static.WithRFC3161Timestamp(&rfc3161TS))
1463 _, err = VerifyRFC3161Timestamp(ociSig, &CheckOpts{
1464 TSACertificate: leaves[0],
1465 TSAIntermediateCertificates: intermediates,
1466 TSARootCertificates: roots,
1467 })
1468 if err == nil || !strings.Contains(err.Error(), "base64 data") {
1469 t.Fatalf("expected error verifying timestamp with raw signature, got: %v", err)
1470 }
1471
1472
1473 tsBytes, err = tsa.GetTimestampedSignature(signature, client)
1474 if err != nil {
1475 t.Fatalf("unexpected error creating timestamp: %v", err)
1476 }
1477 rfc3161TS = bundle.RFC3161Timestamp{SignedRFC3161Timestamp: tsBytes}
1478
1479 signature, _ = privKey.Sign(rand.Reader, h[:], crypto.SHA256)
1480 ociSig, _ = static.NewSignature(payload,
1481 base64.StdEncoding.EncodeToString(signature),
1482 static.WithCertChain(pemLeaf, appendSlices([][]byte{pemRoot})),
1483 static.WithRFC3161Timestamp(&rfc3161TS))
1484 _, err = VerifyRFC3161Timestamp(ociSig, &CheckOpts{
1485 TSACertificate: leaves[0],
1486 TSAIntermediateCertificates: intermediates,
1487 TSARootCertificates: roots,
1488 })
1489 if err == nil || !strings.Contains(err.Error(), "hashed messages don't match") {
1490 t.Fatalf("expected error verifying mismatched signatures, got: %v", err)
1491 }
1492
1493
1494 _, err = VerifyRFC3161Timestamp(ociSig, &CheckOpts{
1495 TSACertificate: leaves[0],
1496 TSAIntermediateCertificates: intermediates,
1497 })
1498 if err == nil || !strings.Contains(err.Error(), "no TSA root certificate(s) provided to verify timestamp") {
1499 t.Fatalf("expected error verifying without a root certificate, got: %v", err)
1500 }
1501 }
1502
View as plain text