...

Source file src/github.com/sigstore/cosign/v2/pkg/cosign/verify_test.go

Documentation: github.com/sigstore/cosign/v2/pkg/cosign

     1  // Copyright 2021 The Sigstore Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    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) { //nolint: revive
    69  	return nil, nil
    70  }
    71  
    72  func (m *mockVerifier) VerifySignature(signature, message io.Reader, opts ...signature.VerifyOption) error { //nolint: revive
    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  	// Should Verify
   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  	// Should Not Verify
   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  	// TODO: Create fake bundle and test verification
   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  	// TODO: Create fake bundle and test verification
   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  	// generate log ID according to rekor public key
   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  	// Sign with root.
   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  	// Create a fake bundle
   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  	// Create a fake bundle
   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  	// Add one valid key here.
   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  	// Then try to validate with keys that are not ecdsa.PublicKey and should
   354  	// fail.
   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  	// TODO: Create fake bundle and test verification
   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  	// TODO: Create fake bundle and test verification
   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  	// Load in different sub cert so the chain doesn't verify
   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  	// TODO: Create fake bundle and test verification
   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  // uuid generates the UUID for the given LogEntry.
   514  // This is effectively a reimplementation of
   515  // pkg/cosign/tlog.go -> verifyUUID / ComputeLeafHash, but separated
   516  // to avoid a circular dependency.
   517  // TODO?: Perhaps we should refactor the tlog libraries into a separate
   518  // package?
   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  // This test ensures that image signature validation fails properly if we are
   528  // using a SigVerifier with Rekor.
   529  // In other words, we require checking against RekorPubKeys when verifying
   530  // image signature.
   531  // This could be made more robust with supplying a mismatched trusted RekorPubKeys
   532  // rather than none.
   533  // See https://github.com/sigstore/cosign/v2/issues/1816 for more details.
   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  	// Add a fake rekor client - this makes it look like there's a matching
   546  	// tlog entry for the signature during validation (even though it does not
   547  	// match the underlying data / key)
   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  		// This is failing to validate the Rekor public key itself.
   559  		// At the very least this ensures
   560  		// that we're hitting tlog validation during signature checking.
   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 { // bundle is not verified since there's no Rekor bundle
   600  		t.Fatalf("unexpected error while verifying signature, got %v", err)
   601  	}
   602  }
   603  
   604  func TestVerifyImageSignatureWithSigVerifierAndRekorTSA(t *testing.T) {
   605  	// Add a fake rekor client - this makes it look like there's a matching
   606  	// tlog entry for the signature during validation (even though it does not
   607  	// match the underlying data / key)
   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  		// TODO(wlynch): This is a weak test, since this is really failing because
   647  		// there is no inclusion proof for the Rekor entry rather than failing to
   648  		// validate the Rekor public key itself. At the very least this ensures
   649  		// that we're hitting tlog validation during signature checking,
   650  		// but we should look into improving this once there is an in-memory
   651  		// Rekor client that is capable of performing inclusion proof validation
   652  		// in unit tests.
   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  		// explicitly set to false
   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}, /* dnsNames */
   737  		nil,               /* emailAddresses */
   738  		nil,               /* ipAddresses */
   739  		nil,               /* uris */
   740  		oidcIssuer,        /* 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,               /* dnsNames */
   770  		[]string{subject}, /* emailAddresses */
   771  		nil,               /* ipAddresses */
   772  		nil,               /* uris */
   773  		oidcIssuer,        /* 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,                            /* dnsNames */
   803  		nil,                            /* emailAddresses */
   804  		[]net.IP{net.ParseIP(subject)}, /* ipAddresses */
   805  		nil,                            /* uris */
   806  		oidcIssuer,                     /* 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,                 /* dnsNames */
   836  		nil,                 /* emailAddresses */
   837  		nil,                 /* ipAddresses */
   838  		[]*url.URL{subject}, /* uris */
   839  		oidcIssuer,          /* 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  	// generate with OtherName, which will override other SANs
   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 /* No matches required, checks out */},
  1177  		{identities: []Identity{ // Strict match on both
  1178  			{Subject: emailSubject, Issuer: oidcIssuer}},
  1179  			emailAddresses: []string{emailSubject}},
  1180  		{identities: []Identity{ // just issuer
  1181  			{Issuer: oidcIssuer}},
  1182  			emailAddresses: []string{emailSubject}},
  1183  		{identities: []Identity{ // just subject
  1184  			{Subject: emailSubject}},
  1185  			emailAddresses: []string{emailSubject}},
  1186  		{identities: []Identity{ // mis-match
  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{ // one good identity, other does not match
  1192  			{Subject: "wrongsubject", Issuer: "wrongissuer"},
  1193  			{Subject: emailSubject, Issuer: oidcIssuer}},
  1194  			emailAddresses: []string{emailSubject}},
  1195  		{identities: []Identity{ // illegal regex for subject
  1196  			{SubjectRegExp: "****", Issuer: oidcIssuer}},
  1197  			emailAddresses:   []string{emailSubject},
  1198  			wantErrSubstring: "malformed subject in identity"},
  1199  		{identities: []Identity{ // illegal regex for issuer
  1200  			{Subject: emailSubject, IssuerRegExp: "****"}},
  1201  			wantErrSubstring: "malformed issuer in identity"},
  1202  		{identities: []Identity{ // regex matches
  1203  			{SubjectRegExp: ".*example.com", IssuerRegExp: ".*accounts.google.*"}},
  1204  			emailAddresses:   []string{emailSubject},
  1205  			wantErrSubstring: ""},
  1206  		{identities: []Identity{ // regex matches dnsNames
  1207  			{SubjectRegExp: ".*ubject.example.com", IssuerRegExp: ".*accounts.google.*"}},
  1208  			dnsNames:         dnsSubjects,
  1209  			wantErrSubstring: ""},
  1210  		{identities: []Identity{ // regex matches ip
  1211  			{SubjectRegExp: "1.2.3.*", IssuerRegExp: ".*accounts.google.*"}},
  1212  			ipAddresses:      ipSubjects,
  1213  			wantErrSubstring: ""},
  1214  		{identities: []Identity{ // regex matches urls
  1215  			{SubjectRegExp: ".*url.examp.*", IssuerRegExp: ".*accounts.google.*"}},
  1216  			uris:             uriSubjects,
  1217  			wantErrSubstring: ""},
  1218  		{identities: []Identity{ // regex matches otherName
  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  			// generate with OtherName, which will override other SANs
  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  		// Test CheckCertificatePolicy
  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  	// TODO(nsmith5): Add test cases for invalid signature, missing signature etc
  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  // Tests that verification succeeds if both a root and subordinate pool are
  1373  // present, but a chain is built with only the leaf and root certificates.
  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  	// generate signed artifact
  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  	// success, signing over signature
  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  	// success, signing over payload
  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  		"", /*signature*/
  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  	// failure with non-base64 encoded signature
  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  	// failure with mismatched signature
  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  	// regenerate signature
  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  	// failure without root certificate
  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