From 51ab92daceebb4ee3427c551de9743b4eefcdd11 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Tue, 8 Apr 2025 09:01:51 +0000 Subject: [PATCH 1/3] move entryFromChain to x509util # Conflicts: # internal/hammer/loadtest/workers.go # Conflicts: # internal/scti/handlers.go --- internal/hammer/loadtest/workers.go | 79 +---------------------------- internal/scti/handlers.go | 78 +--------------------------- internal/scti/handlers_test.go | 2 +- internal/scti/signatures_test.go | 4 +- internal/x509util/ct.go | 77 ++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 158 deletions(-) diff --git a/internal/hammer/loadtest/workers.go b/internal/hammer/loadtest/workers.go index 90144699..8a8ccca2 100644 --- a/internal/hammer/loadtest/workers.go +++ b/internal/hammer/loadtest/workers.go @@ -16,7 +16,6 @@ package loadtest import ( "context" - "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/json" @@ -32,7 +31,6 @@ import ( "github.com/transparency-dev/static-ct/internal/types/rfc6962" "github.com/transparency-dev/static-ct/internal/x509util" "github.com/transparency-dev/trillian-tessera/api/layout" - "github.com/transparency-dev/trillian-tessera/ctonly" "k8s.io/klog/v2" ) @@ -360,7 +358,7 @@ func (v *MMDVerifier) Run(ctx context.Context) { if err != nil { panic(fmt.Sprintf("Failed to parse certificates: %v", err)) } - entry, err := entryFromChain(certs, false, leafMMD.timestamp) + entry, err := x509util.EntryFromChain(certs, false, leafMMD.timestamp) if err != nil { panic(fmt.Sprintf("Failed to create entry from chain: %v", err)) } @@ -380,78 +378,3 @@ func (v *MMDVerifier) Kill() { v.cancel() } } - -// entryFromChain generates an Entry from a chain and timestamp. -// Copied from certificate-transparency-go/serialization.go and internal/scti/handlers.go. -// TODO(phboneff): move in a different file maybe? -func entryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64) (*ctonly.Entry, error) { - leaf := ctonly.Entry{ - IsPrecert: isPrecert, - Timestamp: timestamp, - } - - if len(chain) > 1 { - issuersChain := make([][32]byte, len(chain)-1) - for i, c := range chain[1:] { - issuersChain[i] = sha256.Sum256(c.Raw) - } - leaf.FingerprintsChain = issuersChain - } - - if !isPrecert { - leaf.Certificate = chain[0].Raw - return &leaf, nil - } - - // Pre-certs are more complicated. First, parse the leaf pre-cert and its - // putative issuer. - if len(chain) < 2 { - return nil, fmt.Errorf("no issuer cert available for precert leaf building") - } - issuer := chain[1] - cert := chain[0] - - var preIssuer *x509.Certificate - if isPreIssuer(issuer) { - // Replace the cert's issuance information with details from the pre-issuer. - preIssuer = issuer - - // The issuer of the pre-cert is not going to be the issuer of the final - // cert. Change to use the final issuer's key hash. - if len(chain) < 3 { - return nil, fmt.Errorf("no issuer cert available for pre-issuer") - } - issuer = chain[2] - } - - // Next, post-process the DER-encoded TBSCertificate, to remove the CT poison - // extension and possibly update the issuer field. - defangedTBS, err := x509util.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer) - if err != nil { - return nil, fmt.Errorf("failed to remove poison extension: %v", err) - } - - leaf.Precertificate = cert.Raw - // TODO(phboneff): do we need this? - // leaf.PrecertSigningCert = issuer.Raw - leaf.Certificate = defangedTBS - - issuerKeyHash := sha256.Sum256(issuer.RawSubjectPublicKeyInfo) - leaf.IssuerKeyHash = issuerKeyHash[:] - return &leaf, nil -} - -// isPreIssuer indicates whether a certificate is a pre-cert issuer with the specific -// certificate transparency extended key usage. -// Copied from certificate-transparency-go/serialization.go and internal/scti/handlers.go. -// TODO(phboneff): unify these. -func isPreIssuer(cert *x509.Certificate) bool { - // Look for the extension in the Extensions field and not ExtKeyUsage - // since crypto/x509 does not recognize this extension as an ExtKeyUsage. - for _, ext := range cert.Extensions { - if rfc6962.OIDExtKeyUsageCertificateTransparency.Equal(ext.Id) { - return true - } - } - return false -} diff --git a/internal/scti/handlers.go b/internal/scti/handlers.go index 3e4fe2fd..c1dda531 100644 --- a/internal/scti/handlers.go +++ b/internal/scti/handlers.go @@ -16,7 +16,6 @@ package scti import ( "context" - "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/json" @@ -34,7 +33,6 @@ import ( "github.com/transparency-dev/static-ct/internal/x509util" "github.com/transparency-dev/static-ct/modules/dedup" tessera "github.com/transparency-dev/trillian-tessera" - "github.com/transparency-dev/trillian-tessera/ctonly" "go.opentelemetry.io/otel/metric" "k8s.io/klog/v2" ) @@ -267,7 +265,7 @@ func addChainInternal(ctx context.Context, opts *HandlerOptions, log *log, w htt nanosPerMilli := int64(time.Millisecond / time.Nanosecond) timeMillis := uint64(opts.TimeSource.Now().UnixNano() / nanosPerMilli) - entry, err := entryFromChain(chain, isPrecert, timeMillis) + entry, err := x509util.EntryFromChain(chain, isPrecert, timeMillis) if err != nil { return http.StatusBadRequest, fmt.Errorf("failed to build MerkleTreeLeaf: %s", err) } @@ -446,77 +444,3 @@ func marshalAndWriteAddChainResponse(sct *rfc6962.SignedCertificateTimestamp, w return nil } - -// entryFromChain generates an Entry from a chain and timestamp. -// copied from certificate-transparency-go/serialization.go -// TODO(phboneff): move to ct.go -// TODO(phboneff): add tests -func entryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64) (*ctonly.Entry, error) { - leaf := ctonly.Entry{ - IsPrecert: isPrecert, - Timestamp: timestamp, - } - - if len(chain) > 1 { - issuersChain := make([][32]byte, len(chain)-1) - for i, c := range chain[1:] { - issuersChain[i] = sha256.Sum256(c.Raw) - } - leaf.FingerprintsChain = issuersChain - } - - if !isPrecert { - leaf.Certificate = chain[0].Raw - return &leaf, nil - } - - // Pre-certs are more complicated. First, parse the leaf pre-cert and its - // putative issuer. - if len(chain) < 2 { - return nil, fmt.Errorf("no issuer cert available for precert leaf building") - } - issuer := chain[1] - cert := chain[0] - - var preIssuer *x509.Certificate - if isPreIssuer(issuer) { - // Replace the cert's issuance information with details from the pre-issuer. - preIssuer = issuer - - // The issuer of the pre-cert is not going to be the issuer of the final - // cert. Change to use the final issuer's key hash. - if len(chain) < 3 { - return nil, fmt.Errorf("no issuer cert available for pre-issuer") - } - issuer = chain[2] - } - - // Next, post-process the DER-encoded TBSCertificate, to remove the CT poison - // extension and possibly update the issuer field. - defangedTBS, err := x509util.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer) - if err != nil { - return nil, fmt.Errorf("failed to remove poison extension: %v", err) - } - - leaf.Precertificate = cert.Raw - // TODO(phboneff): do we need this? - // leaf.PrecertSigningCert = issuer.Raw - leaf.Certificate = defangedTBS - - issuerKeyHash := sha256.Sum256(issuer.RawSubjectPublicKeyInfo) - leaf.IssuerKeyHash = issuerKeyHash[:] - return &leaf, nil -} - -// isPreIssuer indicates whether a certificate is a pre-cert issuer with the specific -// certificate transparency extended key usage. -func isPreIssuer(cert *x509.Certificate) bool { - // Look for the extension in the Extensions field and not ExtKeyUsage - // since crypto/x509 does not recognize this extension as an ExtKeyUsage. - for _, ext := range cert.Extensions { - if rfc6962.OIDExtKeyUsageCertificateTransparency.Equal(ext.Id) { - return true - } - } - return false -} diff --git a/internal/scti/handlers_test.go b/internal/scti/handlers_test.go index 0b70479c..e76f7d5f 100644 --- a/internal/scti/handlers_test.go +++ b/internal/scti/handlers_test.go @@ -326,7 +326,7 @@ func parseChain(t *testing.T, isPrecert bool, pemChain []string, root *x509.Cert fullChain[len(leafChain)] = root leafChain = fullChain } - entry, err := entryFromChain(leafChain, isPrecert, fakeTimeMillis) + entry, err := x509util.EntryFromChain(leafChain, isPrecert, fakeTimeMillis) if err != nil { t.Fatalf("Failed to create entry") } diff --git a/internal/scti/signatures_test.go b/internal/scti/signatures_test.go index 111af408..abbf857d 100644 --- a/internal/scti/signatures_test.go +++ b/internal/scti/signatures_test.go @@ -255,7 +255,7 @@ func TestBuildV1MerkleTreeLeafForCert(t *testing.T) { } // Use the same cert as the issuer for convenience. - entry, err := entryFromChain([]*x509.Certificate{cert, cert}, false, fixedTimeMillis) + entry, err := x509util.EntryFromChain([]*x509.Certificate{cert, cert}, false, fixedTimeMillis) if err != nil { t.Fatalf("buildV1MerkleTreeLeafForCert()=nil,%v; want _,nil", err) } @@ -318,7 +318,7 @@ func TestSignV1SCTForPrecertificate(t *testing.T) { } // Use the same cert as the issuer for convenience. - entry, err := entryFromChain([]*x509.Certificate{cert, cert}, true, fixedTimeMillis) + entry, err := x509util.EntryFromChain([]*x509.Certificate{cert, cert}, true, fixedTimeMillis) if err != nil { t.Fatalf("buildV1MerkleTreeLeafForCert()=nil,%v; want _,nil", err) } diff --git a/internal/x509util/ct.go b/internal/x509util/ct.go index 83f0d0da..5d63b8ff 100644 --- a/internal/x509util/ct.go +++ b/internal/x509util/ct.go @@ -14,6 +14,7 @@ package x509util import ( + "crypto/sha256" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" @@ -21,6 +22,9 @@ import ( "fmt" "math/big" "time" + + "github.com/transparency-dev/static-ct/internal/types/rfc6962" + "github.com/transparency-dev/trillian-tessera/ctonly" ) var ( @@ -191,3 +195,76 @@ func BuildPrecertTBS(tbsData []byte, preIssuer *x509.Certificate) ([]byte, error func RemoveCTPoison(tbsData []byte) ([]byte, error) { return BuildPrecertTBS(tbsData, nil) } + +// EntryFromChain generates an Entry from a chain and timestamp. +// copied from certificate-transparency-go/serialization.go +// TODO(phboneff): add tests +func EntryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64) (*ctonly.Entry, error) { + leaf := ctonly.Entry{ + IsPrecert: isPrecert, + Timestamp: timestamp, + } + + if len(chain) > 1 { + issuersChain := make([][32]byte, len(chain)-1) + for i, c := range chain[1:] { + issuersChain[i] = sha256.Sum256(c.Raw) + } + leaf.FingerprintsChain = issuersChain + } + + if !isPrecert { + leaf.Certificate = chain[0].Raw + return &leaf, nil + } + + // Pre-certs are more complicated. First, parse the leaf pre-cert and its + // putative issuer. + if len(chain) < 2 { + return nil, fmt.Errorf("no issuer cert available for precert leaf building") + } + issuer := chain[1] + cert := chain[0] + + var preIssuer *x509.Certificate + if isPreIssuer(issuer) { + // Replace the cert's issuance information with details from the pre-issuer. + preIssuer = issuer + + // The issuer of the pre-cert is not going to be the issuer of the final + // cert. Change to use the final issuer's key hash. + if len(chain) < 3 { + return nil, fmt.Errorf("no issuer cert available for pre-issuer") + } + issuer = chain[2] + } + + // Next, post-process the DER-encoded TBSCertificate, to remove the CT poison + // extension and possibly update the issuer field. + defangedTBS, err := BuildPrecertTBS(cert.RawTBSCertificate, preIssuer) + if err != nil { + return nil, fmt.Errorf("failed to remove poison extension: %v", err) + } + + leaf.Precertificate = cert.Raw + // TODO(phboneff): do we need this? + // leaf.PrecertSigningCert = issuer.Raw + leaf.Certificate = defangedTBS + + issuerKeyHash := sha256.Sum256(issuer.RawSubjectPublicKeyInfo) + leaf.IssuerKeyHash = issuerKeyHash[:] + return &leaf, nil +} + +// isPreIssuer indicates whether a certificate is a pre-cert issuer with the specific +// certificate transparency extended key usage. +func isPreIssuer(cert *x509.Certificate) bool { + // Look for the extension in the Extensions field and not ExtKeyUsage + // since crypto/x509 does not recognize this extension as an ExtKeyUsage. + for _, ext := range cert.Extensions { + if rfc6962.OIDExtKeyUsageCertificateTransparency.Equal(ext.Id) { + return true + } + } + return false +} From deee81b361426da171b15d19d7917a051d884798 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Tue, 8 Apr 2025 09:02:09 +0000 Subject: [PATCH 2/3] move verifyAddChain --- internal/scti/chain_validation.go | 30 +++++++++++++++++++++++++++++ internal/scti/handlers.go | 32 ------------------------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/internal/scti/chain_validation.go b/internal/scti/chain_validation.go index e3b76ea3..c4c1fe96 100644 --- a/internal/scti/chain_validation.go +++ b/internal/scti/chain_validation.go @@ -263,6 +263,36 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 return nil, errors.New("no RFC compliant path to root found when trying to validate chain") } +// verifyAddChain is used by add-chain and add-pre-chain. It does the checks that the supplied +// cert is of the correct type and chains to a trusted root. +// TODO(phbnf): add tests +func verifyAddChain(log *log, req rfc6962.AddChainRequest, expectingPrecert bool) ([]*x509.Certificate, error) { + // We already checked that the chain is not empty so can move on to verification + validPath, err := validateChain(req.Chain, log.chainValidationOpts) + if err != nil { + // We rejected it because the cert failed checks or we could not find a path to a root etc. + // Lots of possible causes for errors + return nil, fmt.Errorf("chain failed to verify: %s", err) + } + + isPrecert, err := isPrecertificate(validPath[0]) + if err != nil { + return nil, fmt.Errorf("precert test failed: %s", err) + } + + // The type of the leaf must match the one the handler expects + if isPrecert != expectingPrecert { + if expectingPrecert { + klog.Warningf("%s: Cert (or precert with invalid CT ext) submitted as precert chain: %q", log.origin, req.Chain) + } else { + klog.Warningf("%s: Precert (or cert with invalid CT ext) submitted as cert chain: %q", log.origin, req.Chain) + } + return nil, fmt.Errorf("cert / precert mismatch: %T", expectingPrecert) + } + + return validPath, nil +} + func chainsEquivalent(inChain []*x509.Certificate, verifiedChain []*x509.Certificate) bool { // The verified chain includes a root, but the input chain may or may not include a // root (RFC 6962 s4.1/ s4.2 "the last [certificate] is either the root certificate diff --git a/internal/scti/handlers.go b/internal/scti/handlers.go index c1dda531..bcce1676 100644 --- a/internal/scti/handlers.go +++ b/internal/scti/handlers.go @@ -16,7 +16,6 @@ package scti import ( "context" - "crypto/x509" "encoding/base64" "encoding/json" "errors" @@ -384,37 +383,6 @@ func deadlineTime(opts *HandlerOptions) time.Time { return opts.TimeSource.Now().Add(opts.Deadline) } -// verifyAddChain is used by add-chain and add-pre-chain. It does the checks that the supplied -// cert is of the correct type and chains to a trusted root. -// TODO(phbnf): add tests -// TODO(phbnf): move to chain_validation.go -func verifyAddChain(log *log, req rfc6962.AddChainRequest, expectingPrecert bool) ([]*x509.Certificate, error) { - // We already checked that the chain is not empty so can move on to verification - validPath, err := validateChain(req.Chain, log.chainValidationOpts) - if err != nil { - // We rejected it because the cert failed checks or we could not find a path to a root etc. - // Lots of possible causes for errors - return nil, fmt.Errorf("chain failed to verify: %s", err) - } - - isPrecert, err := isPrecertificate(validPath[0]) - if err != nil { - return nil, fmt.Errorf("precert test failed: %s", err) - } - - // The type of the leaf must match the one the handler expects - if isPrecert != expectingPrecert { - if expectingPrecert { - klog.Warningf("%s: Cert (or precert with invalid CT ext) submitted as precert chain: %q", log.origin, req.Chain) - } else { - klog.Warningf("%s: Precert (or cert with invalid CT ext) submitted as cert chain: %q", log.origin, req.Chain) - } - return nil, fmt.Errorf("cert / precert mismatch: %T", expectingPrecert) - } - - return validPath, nil -} - // marshalAndWriteAddChainResponse is used by add-chain and add-pre-chain to create and write // the JSON response to the client func marshalAndWriteAddChainResponse(sct *rfc6962.SignedCertificateTimestamp, w http.ResponseWriter) error { From 6392bf0f1f8777c79fdfdda51e6eff6cd8ebcb1e Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Tue, 8 Apr 2025 09:02:24 +0000 Subject: [PATCH 3/3] convert functions to methods --- internal/scti/chain_validation.go | 34 +++++++++++++------------- internal/scti/chain_validation_test.go | 28 ++++++++++----------- internal/scti/handlers.go | 2 +- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/internal/scti/chain_validation.go b/internal/scti/chain_validation.go index c4c1fe96..b0d140bb 100644 --- a/internal/scti/chain_validation.go +++ b/internal/scti/chain_validation.go @@ -149,7 +149,7 @@ func isPrecertificate(cert *x509.Certificate) (bool, error) { // supplied in the chain. Then applies the RFC requirement that the path must involve all // the submitted chain in the order of submission. // TODO(phboneff): make this a method func([][]byte) ([]*x509.Certificate, error) -func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x509.Certificate, error) { +func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certificate, error) { if len(rawChain) == 0 { return nil, errors.New("empty certificate chain") } @@ -172,8 +172,8 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 } } - naStart := validationOpts.notAfterStart - naLimit := validationOpts.notAfterLimit + naStart := opts.notAfterStart + naLimit := opts.notAfterLimit cert := chain[0] // Check whether the expiry date of the cert is within the acceptable range. @@ -184,24 +184,24 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 return nil, fmt.Errorf("certificate NotAfter (%v) >= %v", cert.NotAfter, *naLimit) } - now := validationOpts.currentTime + now := opts.currentTime if now.IsZero() { now = time.Now() } expired := now.After(cert.NotAfter) - if validationOpts.rejectExpired && expired { + if opts.rejectExpired && expired { return nil, errors.New("rejecting expired certificate") } - if validationOpts.rejectUnexpired && !expired { + if opts.rejectUnexpired && !expired { return nil, errors.New("rejecting unexpired certificate") } // Check for unwanted extension types, if required. // TODO(al): Refactor CertValidationOpts c'tor to a builder pattern and // pre-calc this in there - if len(validationOpts.rejectExtIds) != 0 { + if len(opts.rejectExtIds) != 0 { badIDs := make(map[string]bool) - for _, id := range validationOpts.rejectExtIds { + for _, id := range opts.rejectExtIds { badIDs[id.String()] = true } for idx, ext := range cert.Extensions { @@ -214,9 +214,9 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 // TODO(al): Refactor CertValidationOpts c'tor to a builder pattern and // pre-calc this in there too. - if len(validationOpts.extKeyUsages) > 0 { + if len(opts.extKeyUsages) > 0 { acceptEKUs := make(map[x509.ExtKeyUsage]bool) - for _, eku := range validationOpts.extKeyUsages { + for _, eku := range opts.extKeyUsages { acceptEKUs[eku] = true } good := false @@ -227,7 +227,7 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 } } if !good { - return nil, fmt.Errorf("rejecting certificate without EKU in %v", validationOpts.extKeyUsages) + return nil, fmt.Errorf("rejecting certificate without EKU in %v", opts.extKeyUsages) } } @@ -237,9 +237,9 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 // - allow certificate without policing them since this is not CT's responsibility // See /internal/lax509/README.md for further information. verifyOpts := lax509.VerifyOptions{ - Roots: validationOpts.trustedRoots.CertPool(), + Roots: opts.trustedRoots.CertPool(), Intermediates: intermediatePool.CertPool(), - KeyUsages: validationOpts.extKeyUsages, + KeyUsages: opts.extKeyUsages, } verifiedChains, err := lax509.Verify(cert, verifyOpts) @@ -266,9 +266,9 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5 // verifyAddChain is used by add-chain and add-pre-chain. It does the checks that the supplied // cert is of the correct type and chains to a trusted root. // TODO(phbnf): add tests -func verifyAddChain(log *log, req rfc6962.AddChainRequest, expectingPrecert bool) ([]*x509.Certificate, error) { +func (opts ChainValidationOpts) verifyAddChain(req rfc6962.AddChainRequest, expectingPrecert bool) ([]*x509.Certificate, error) { // We already checked that the chain is not empty so can move on to verification - validPath, err := validateChain(req.Chain, log.chainValidationOpts) + validPath, err := opts.validateChain(req.Chain) if err != nil { // We rejected it because the cert failed checks or we could not find a path to a root etc. // Lots of possible causes for errors @@ -283,9 +283,9 @@ func verifyAddChain(log *log, req rfc6962.AddChainRequest, expectingPrecert bool // The type of the leaf must match the one the handler expects if isPrecert != expectingPrecert { if expectingPrecert { - klog.Warningf("%s: Cert (or precert with invalid CT ext) submitted as precert chain: %q", log.origin, req.Chain) + klog.Warningf("Cert (or precert with invalid CT ext) submitted as precert chain: %q", req.Chain) } else { - klog.Warningf("%s: Precert (or cert with invalid CT ext) submitted as cert chain: %q", log.origin, req.Chain) + klog.Warningf("Precert (or cert with invalid CT ext) submitted as cert chain: %q", req.Chain) } return nil, fmt.Errorf("cert / precert mismatch: %T", expectingPrecert) } diff --git a/internal/scti/chain_validation_test.go b/internal/scti/chain_validation_test.go index 2b5356bf..a60f47da 100644 --- a/internal/scti/chain_validation_test.go +++ b/internal/scti/chain_validation_test.go @@ -254,7 +254,7 @@ func TestValidateChain(t *testing.T) { if !fakeCARoots.AppendCertsFromPEM([]byte(testdata.RealPrecertIntermediatePEM)) { t.Fatal("failed to load real intermediate") } - validateOpts := ChainValidationOpts{ + opts := ChainValidationOpts{ trustedRoots: fakeCARoots, } @@ -403,11 +403,11 @@ func TestValidateChain(t *testing.T) { } for _, test := range tests { t.Run(test.desc, func(t *testing.T) { - validateOpts := validateOpts + opts := opts if test.modifyOpts != nil { - test.modifyOpts(&validateOpts) + test.modifyOpts(&opts) } - gotPath, err := validateChain(test.chain, validateOpts) + gotPath, err := opts.validateChain(test.chain) if err != nil { if !test.wantErr { t.Errorf("ValidateChain()=%v,%v; want _,nil", gotPath, err) @@ -433,7 +433,7 @@ func TestNotAfterRange(t *testing.T) { if !fakeCARoots.AppendCertsFromPEM([]byte(testdata.FakeCACertPEM)) { t.Fatal("failed to load fake root") } - validateOpts := ChainValidationOpts{ + opts := ChainValidationOpts{ trustedRoots: fakeCARoots, rejectExpired: false, } @@ -473,12 +473,12 @@ func TestNotAfterRange(t *testing.T) { for _, test := range tests { t.Run(test.desc, func(t *testing.T) { if !test.notAfterStart.IsZero() { - validateOpts.notAfterStart = &test.notAfterStart + opts.notAfterStart = &test.notAfterStart } if !test.notAfterLimit.IsZero() { - validateOpts.notAfterLimit = &test.notAfterLimit + opts.notAfterLimit = &test.notAfterLimit } - gotPath, err := validateChain(test.chain, validateOpts) + gotPath, err := opts.validateChain(test.chain) if err != nil { if !test.wantErr { t.Errorf("ValidateChain()=%v,%v; want _,nil", gotPath, err) @@ -500,7 +500,7 @@ func TestRejectExpiredUnexpired(t *testing.T) { } // Validity period: May 13, 2016 - Jul 12, 2019. chain := pemsToDERChain(t, []string{testdata.LeafSignedByFakeIntermediateCertPEM, testdata.FakeIntermediateCertPEM}) - validateOpts := ChainValidationOpts{ + opts := ChainValidationOpts{ trustedRoots: fakeCARoots, extKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, } @@ -587,10 +587,10 @@ func TestRejectExpiredUnexpired(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - validateOpts.currentTime = tc.now - validateOpts.rejectExpired = tc.rejectExpired - validateOpts.rejectUnexpired = tc.rejectUnexpired - _, err := validateChain(chain, validateOpts) + opts.currentTime = tc.now + opts.rejectExpired = tc.rejectExpired + opts.rejectUnexpired = tc.rejectUnexpired + _, err := opts.validateChain(chain) if err != nil { if len(tc.wantErr) == 0 { t.Errorf("ValidateChain()=_,%v; want _,nil", err) @@ -692,7 +692,7 @@ func TestPreIssuedCert(t *testing.T) { trustedRoots: roots, extKeyUsages: tc.eku, } - chain, err := validateChain(rawChain, opts) + chain, err := opts.validateChain(rawChain) if err != nil { t.Fatalf("failed to ValidateChain: %v", err) } diff --git a/internal/scti/handlers.go b/internal/scti/handlers.go index bcce1676..c7d2a07b 100644 --- a/internal/scti/handlers.go +++ b/internal/scti/handlers.go @@ -252,7 +252,7 @@ func addChainInternal(ctx context.Context, opts *HandlerOptions, log *log, w htt for _, der := range addChainReq.Chain { opts.RequestLog.addDERToChain(ctx, der) } - chain, err := verifyAddChain(log, addChainReq, isPrecert) + chain, err := log.chainValidationOpts.verifyAddChain(addChainReq, isPrecert) if err != nil { return http.StatusBadRequest, fmt.Errorf("failed to verify add-chain contents: %s", err) }