pkcs7: reduce duplicated code

This commit is contained in:
Sun Yimin 2023-03-14 08:36:15 +08:00 committed by GitHub
parent 052f6ed2cf
commit 652e6da354
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 64 deletions

View File

@ -31,7 +31,7 @@ func (p7 *PKCS7) VerifyWithChain(truststore *smx509.CertPool) (err error) {
return errors.New("pkcs7: Message has no signers") return errors.New("pkcs7: Message has no signers")
} }
for _, signer := range p7.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 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 // the end-entity signer cert to a root in the truststore at
// currentTime. It does not use the signing time authenticated // currentTime. It does not use the signing time authenticated
// attribute. // 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 { if len(p7.Signers) == 0 {
return errors.New("pkcs7: Message has no signers") return errors.New("pkcs7: Message has no signers")
} }
for _, signer := range p7.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 err
} }
} }
return nil return nil
} }
func verifySignatureAtTime(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool, currentTime time.Time) (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 {
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) {
signedData := p7.Content signedData := p7.Content
ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber) ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
if ee == nil { if ee == nil {
@ -156,6 +99,9 @@ func verifySignature(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool)
} }
} }
if truststore != nil { if truststore != nil {
if currentTime != nil {
signingTime = *currentTime
}
_, err = verifyCertChain(ee, p7.Certificates, truststore, signingTime) _, err = verifyCertChain(ee, p7.Certificates, truststore, signingTime)
if err != nil { if err != nil {
return err return err

View File

@ -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 // 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 // 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) 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) t.Errorf("Verify at UTC now failed with error: %v", err)
} }
expiredTime := time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) 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) t.Errorf("Verify at expired time %s did not error", expiredTime)
} }
notYetValidTime := time.Date(1999, time.July, 5, 0, 13, 0, 0, time.UTC) 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, &notYetValidTime); err == nil {
t.Errorf("Verify at not yet valid time %s did not error", notYetValidTime) t.Errorf("Verify at not yet valid time %s did not error", notYetValidTime)
} }