diff --git a/pkcs7/verify.go b/pkcs7/verify.go index b17b6bf..a53ffdf 100644 --- a/pkcs7/verify.go +++ b/pkcs7/verify.go @@ -31,7 +31,7 @@ func (p7 *PKCS7) VerifyWithChain(truststore *smx509.CertPool) (err error) { return errors.New("pkcs7: Message has no signers") } for _, signer := range p7.Signers { - if err := verifySignature(p7, signer, truststore); err != nil { + if err := verifySignature(p7, signer, truststore, nil); err != nil { return err } } @@ -44,76 +44,19 @@ func (p7 *PKCS7) VerifyWithChain(truststore *smx509.CertPool) (err error) { // the end-entity signer cert to a root in the truststore at // currentTime. It does not use the signing time authenticated // attribute. -func (p7 *PKCS7) VerifyWithChainAtTime(truststore *smx509.CertPool, currentTime time.Time) (err error) { +func (p7 *PKCS7) VerifyWithChainAtTime(truststore *smx509.CertPool, currentTime *time.Time) (err error) { if len(p7.Signers) == 0 { return errors.New("pkcs7: Message has no signers") } for _, signer := range p7.Signers { - if err := verifySignatureAtTime(p7, signer, truststore, currentTime); err != nil { + if err := verifySignature(p7, signer, truststore, currentTime); err != nil { return err } } return nil } -func verifySignatureAtTime(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool, currentTime time.Time) (err error) { - signedData := p7.Content - ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber) - if ee == nil { - return errors.New("pkcs7: No certificate for signer") - } - if len(signer.AuthenticatedAttributes) > 0 { - // TODO(fullsailor): First check the content type match - var ( - digest []byte - signingTime time.Time - ) - err := unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeMessageDigest, &digest) - if err != nil { - return err - } - hasher, err := getHashForOID(signer.DigestAlgorithm.Algorithm) - if err != nil { - return err - } - h := newHash(hasher, signer.DigestAlgorithm.Algorithm) - h.Write(p7.Content) - computed := h.Sum(nil) - if subtle.ConstantTimeCompare(digest, computed) != 1 { - return &MessageDigestMismatchError{ - ExpectedDigest: digest, - ActualDigest: computed, - } - } - signedData, err = marshalAttributes(signer.AuthenticatedAttributes) - if err != nil { - return err - } - err = unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeSigningTime, &signingTime) - if err == nil { - // signing time found, performing validity check - if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) { - return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q", - signingTime.Format(time.RFC3339), - ee.NotBefore.Format(time.RFC3339), - ee.NotAfter.Format(time.RFC3339)) - } - } - } - if truststore != nil { - _, err = verifyCertChain(ee, p7.Certificates, truststore, currentTime) - if err != nil { - return err - } - } - sigalg, err := getSignatureAlgorithm(signer.DigestEncryptionAlgorithm, signer.DigestAlgorithm) - if err != nil { - return err - } - return ee.CheckSignature(sigalg, signedData, signer.EncryptedDigest) -} - -func verifySignature(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool) (err error) { +func verifySignature(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool, currentTime *time.Time) (err error) { signedData := p7.Content ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber) if ee == nil { @@ -156,6 +99,9 @@ func verifySignature(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool) } } if truststore != nil { + if currentTime != nil { + signingTime = *currentTime + } _, err = verifyCertChain(ee, p7.Certificates, truststore, signingTime) if err != nil { return err diff --git a/pkcs7/verify_test.go b/pkcs7/verify_test.go index 5247118..a16930c 100644 --- a/pkcs7/verify_test.go +++ b/pkcs7/verify_test.go @@ -260,16 +260,16 @@ func TestVerifyFirefoxAddon(t *testing.T) { // Intermediate: 2015-03-17 23:52:42 +0000 UTC 2025-03-14 23:52:42 +0000 UTC // Root: 2015-03-17 22:53:57 +0000 UTC 2025-03-14 22:53:57 +0000 UTC validTime := time.Date(2021, 8, 16, 20, 0, 0, 0, time.UTC) - if err = p7.VerifyWithChainAtTime(certPool, validTime); err != nil { + if err = p7.VerifyWithChainAtTime(certPool, &validTime); err != nil { t.Errorf("Verify at UTC now failed with error: %v", err) } expiredTime := time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) - if err = p7.VerifyWithChainAtTime(certPool, expiredTime); err == nil { + if err = p7.VerifyWithChainAtTime(certPool, &expiredTime); err == nil { t.Errorf("Verify at expired time %s did not error", expiredTime) } notYetValidTime := time.Date(1999, time.July, 5, 0, 13, 0, 0, time.UTC) - if err = p7.VerifyWithChainAtTime(certPool, notYetValidTime); err == nil { + if err = p7.VerifyWithChainAtTime(certPool, ¬YetValidTime); err == nil { t.Errorf("Verify at not yet valid time %s did not error", notYetValidTime) }