diff --git a/x509/cert_validations.go b/x509/cert_validations.go index 9e87c681..7946ef16 100644 --- a/x509/cert_validations.go +++ b/x509/cert_validations.go @@ -48,8 +48,8 @@ func validateCertChain(certChain []*x509.Certificate, expectedLeafEku x509.ExtKe // For self-signed signing certificate (not a CA) if len(certChain) == 1 { cert := certChain[0] - if signingTime != nil && (signingTime.Before(cert.NotBefore) || signingTime.After(cert.NotAfter)) { - return fmt.Errorf("certificate with subject %q was not valid at signing time of %s", cert.Subject, signingTime.UTC()) + if signedTimeError := validateSigningTime(cert, signingTime); signedTimeError != nil { + return signedTimeError } if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil { return fmt.Errorf("invalid self-signed certificate. subject: %q. Error: %w", cert.Subject, err) @@ -61,8 +61,8 @@ func validateCertChain(certChain []*x509.Certificate, expectedLeafEku x509.ExtKe } for i, cert := range certChain { - if signingTime != nil && (signingTime.Before(cert.NotBefore) || signingTime.After(cert.NotAfter)) { - return fmt.Errorf("certificate with subject %q was not valid at signing time of %s", cert.Subject, signingTime.UTC()) + if signedTimeError := validateSigningTime(cert, signingTime); signedTimeError != nil { + return signedTimeError } if i == len(certChain)-1 { selfSigned, selfSignedError := isSelfSigned(cert) @@ -120,6 +120,14 @@ func isIssuedBy(subject *x509.Certificate, issuer *x509.Certificate) (bool, erro return bytes.Equal(issuer.RawSubject, subject.RawIssuer), nil } +func validateSigningTime(cert *x509.Certificate, signingTime *time.Time) error { + if signingTime != nil && (signingTime.Before(cert.NotBefore) || signingTime.After(cert.NotAfter)) { + return fmt.Errorf("certificate with subject %q was invalid at signing time of %s. Certificate is valid from [%s] to [%s]", + cert.Subject, signingTime.UTC(), cert.NotBefore.UTC(), cert.NotAfter.UTC()) + } + return nil +} + func validateCACertificate(cert *x509.Certificate, expectedPathLen int) error { if err := validateCABasicConstraints(cert, expectedPathLen); err != nil { return err diff --git a/x509/cert_validations_test.go b/x509/cert_validations_test.go index f0eb563a..b781dcb8 100644 --- a/x509/cert_validations_test.go +++ b/x509/cert_validations_test.go @@ -232,7 +232,37 @@ func TestFailInvalidSigningTime(t *testing.T) { st := time.Unix(1625690922, 0) err := ValidateCodeSigningCertChain(certChain, &st) - assertErrorEqual("certificate with subject \"CN=CodeSigningLeaf\" was not valid at signing time of 2021-07-07 20:48:42 +0000 UTC", err, t) + assertErrorEqual("certificate with subject \"CN=CodeSigningLeaf\" was invalid at signing time of 2021-07-07 20:48:42 +0000 UTC. Certificate is valid from [2022-06-30 19:20:03 +0000 UTC] to [3021-10-31 19:20:03 +0000 UTC]", err, t) +} + +func TestValidateSigningTime(t *testing.T) { + // codeSigningCert is valid from 2022-06-30 19:20:03 +0000 UTC to 3021-10-31 19:20:03 +0000 UTC + testCases := []struct { + name string + certChain *x509.Certificate + signingTime time.Time + expectErr string + }{ + {"invalid before certificate period", + codeSigningCert, + time.Date(2022, 6, 29, 0, 0, 0, 0, time.UTC), + "certificate with subject \"CN=CodeSigningLeaf\" was invalid at signing time of 2022-06-29 00:00:00 +0000 UTC. Certificate is valid from [2022-06-30 19:20:03 +0000 UTC] to [3021-10-31 19:20:03 +0000 UTC]"}, + {"invalid after certificate period", + codeSigningCert, + time.Date(3021, 11, 1, 0, 0, 0, 0, time.UTC), + "certificate with subject \"CN=CodeSigningLeaf\" was invalid at signing time of 3021-11-01 00:00:00 +0000 UTC. Certificate is valid from [2022-06-30 19:20:03 +0000 UTC] to [3021-10-31 19:20:03 +0000 UTC]"}, + {"valid in certificate period", + codeSigningCert, + time.Date(2023, 10, 10, 0, 0, 0, 0, time.UTC), + ""}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if err := validateSigningTime(tc.certChain, &tc.signingTime); err != nil { + assertErrorEqual(tc.expectErr, err, t) + } + }) + } } func TestFailChainNotEndingInRoot(t *testing.T) {