From c96159c25217c84a252be5d74d48861af715ecf8 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 16 May 2024 12:40:31 +0200 Subject: [PATCH] crypto/x509: cleanup signature generation Centralizing some repetitive code, which would have prevented #45990. This also fixes the deprecated Certificate.CreateCRL for RSA-PSS, not that anyone cared, probably. This has two other minor observable behavior changes: MD2 is now treated as a completely unknown algorithm (why did we even have that!? removing lets us treat hash == 0 as always meaning no prehash); and we now do the signature verification self-check for all signing operations. Change-Id: I3b34fe0c3b6eb6181d2145b0704834225cd45a27 Reviewed-on: https://go-review.googlesource.com/c/go/+/586015 Reviewed-by: Dmitri Shuralyov Reviewed-by: Roland Shoemaker Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI --- .../6-stdlib/99-minor/crypto/x509/45990.md | 3 + src/crypto/x509/x509.go | 293 ++++++++---------- src/crypto/x509/x509_test.go | 25 +- 3 files changed, 138 insertions(+), 183 deletions(-) create mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/45990.md diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/45990.md b/doc/next/6-stdlib/99-minor/crypto/x509/45990.md new file mode 100644 index 0000000000..2eda8476a9 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/crypto/x509/45990.md @@ -0,0 +1,3 @@ +[CreateCertificateRequest] now correct supports RSA-PSS signature algorithms. + +[CreateCertificateRequest] and [CreateRevocationList] now verify the generated signature using the signer’s public key. If the signature is invalid, an error is returned. This has been the behavior of [CreateCertificate] since Go 1.16. diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 47bb428110..50433058f7 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -233,12 +233,21 @@ const ( ) func (algo SignatureAlgorithm) isRSAPSS() bool { - switch algo { - case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS: - return true - default: - return false + for _, details := range signatureAlgorithmDetails { + if details.algo == algo { + return details.isRSAPSS + } } + return false +} + +func (algo SignatureAlgorithm) hashFunc() crypto.Hash { + for _, details := range signatureAlgorithmDetails { + if details.algo == algo { + return details.hash + } + } + return crypto.Hash(0) } func (algo SignatureAlgorithm) String() string { @@ -281,8 +290,6 @@ func (algo PublicKeyAlgorithm) String() string { // // RFC 3279 2.2.1 RSA Signature Algorithms // -// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } -// // md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } // // sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } @@ -325,7 +332,6 @@ func (algo PublicKeyAlgorithm) String() string { // // id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } var ( - oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} @@ -356,40 +362,43 @@ var signatureAlgorithmDetails = []struct { algo SignatureAlgorithm name string oid asn1.ObjectIdentifier + params asn1.RawValue pubKeyAlgo PublicKeyAlgorithm hash crypto.Hash + isRSAPSS bool }{ - {MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */}, - {MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, RSA, crypto.MD5}, - {SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, RSA, crypto.SHA1}, - {SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1}, - {SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, RSA, crypto.SHA256}, - {SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, RSA, crypto.SHA384}, - {SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, RSA, crypto.SHA512}, - {SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA256}, - {SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA384}, - {SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA512}, - {DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, DSA, crypto.SHA1}, - {DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, DSA, crypto.SHA256}, - {ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1}, - {ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256}, - {ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384}, - {ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512}, - {PureEd25519, "Ed25519", oidSignatureEd25519, Ed25519, crypto.Hash(0) /* no pre-hashing */}, -} - -// hashToPSSParameters contains the DER encoded RSA PSS parameters for the + {MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, asn1.NullRawValue, RSA, crypto.MD5, false}, + {SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, asn1.NullRawValue, RSA, crypto.SHA1, false}, + {SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, asn1.NullRawValue, RSA, crypto.SHA1, false}, + {SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, asn1.NullRawValue, RSA, crypto.SHA256, false}, + {SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, asn1.NullRawValue, RSA, crypto.SHA384, false}, + {SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, asn1.NullRawValue, RSA, crypto.SHA512, false}, + {SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, pssParametersSHA256, RSA, crypto.SHA256, true}, + {SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, pssParametersSHA384, RSA, crypto.SHA384, true}, + {SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, pssParametersSHA512, RSA, crypto.SHA512, true}, + {DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, emptyRawValue, DSA, crypto.SHA1, false}, + {DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, emptyRawValue, DSA, crypto.SHA256, false}, + {ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, emptyRawValue, ECDSA, crypto.SHA1, false}, + {ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, emptyRawValue, ECDSA, crypto.SHA256, false}, + {ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, emptyRawValue, ECDSA, crypto.SHA384, false}, + {ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, emptyRawValue, ECDSA, crypto.SHA512, false}, + {PureEd25519, "Ed25519", oidSignatureEd25519, emptyRawValue, Ed25519, crypto.Hash(0) /* no pre-hashing */, false}, +} + +var emptyRawValue = asn1.RawValue{} + +// DER encoded RSA PSS parameters for the // SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3. // The parameters contain the following values: // - hashAlgorithm contains the associated hash identifier with NULL parameters // - maskGenAlgorithm always contains the default mgf1SHA1 identifier // - saltLength contains the length of the associated hash // - trailerField always contains the default trailerFieldBC value -var hashToPSSParameters = map[crypto.Hash]asn1.RawValue{ - crypto.SHA256: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 162, 3, 2, 1, 32}}, - crypto.SHA384: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 162, 3, 2, 1, 48}}, - crypto.SHA512: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 162, 3, 2, 1, 64}}, -} +var ( + pssParametersSHA256 = asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 162, 3, 2, 1, 32}} + pssParametersSHA384 = asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 162, 3, 2, 1, 48}} + pssParametersSHA512 = asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 162, 3, 2, 1, 64}} +) // pssParameters reflects the parameters in an AlgorithmIdentifier that // specifies RSA PSS. See RFC 3447, Appendix A.2.3. @@ -1436,81 +1445,91 @@ func subjectBytes(cert *Certificate) ([]byte, error) { return asn1.Marshal(cert.Subject.ToRDNSequence()) } -// signingParamsForPublicKey returns the parameters to use for signing with -// priv. If requestedSigAlgo is not zero then it overrides the default -// signature algorithm. -func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { +// signingParamsForKey returns the signature algorithm and its Algorithm +// Identifier to use for signing, based on the key type. If sigAlgo is not zero +// then it overrides the default. +func signingParamsForKey(key crypto.Signer, sigAlgo SignatureAlgorithm) (SignatureAlgorithm, pkix.AlgorithmIdentifier, error) { + var ai pkix.AlgorithmIdentifier var pubType PublicKeyAlgorithm + var defaultAlgo SignatureAlgorithm - switch pub := pub.(type) { + switch pub := key.Public().(type) { case *rsa.PublicKey: pubType = RSA - hashFunc = crypto.SHA256 - sigAlgo.Algorithm = oidSignatureSHA256WithRSA - sigAlgo.Parameters = asn1.NullRawValue + defaultAlgo = SHA256WithRSA case *ecdsa.PublicKey: pubType = ECDSA - switch pub.Curve { case elliptic.P224(), elliptic.P256(): - hashFunc = crypto.SHA256 - sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 + defaultAlgo = ECDSAWithSHA256 case elliptic.P384(): - hashFunc = crypto.SHA384 - sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 + defaultAlgo = ECDSAWithSHA384 case elliptic.P521(): - hashFunc = crypto.SHA512 - sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 + defaultAlgo = ECDSAWithSHA512 default: - err = errors.New("x509: unknown elliptic curve") + return 0, ai, errors.New("x509: unsupported elliptic curve") } case ed25519.PublicKey: pubType = Ed25519 - sigAlgo.Algorithm = oidSignatureEd25519 + defaultAlgo = PureEd25519 default: - err = errors.New("x509: only RSA, ECDSA and Ed25519 keys supported") + return 0, ai, errors.New("x509: only RSA, ECDSA and Ed25519 keys supported") } - if err != nil { - return - } - - if requestedSigAlgo == 0 { - return + if sigAlgo == 0 { + sigAlgo = defaultAlgo } - found := false for _, details := range signatureAlgorithmDetails { - if details.algo == requestedSigAlgo { + if details.algo == sigAlgo { if details.pubKeyAlgo != pubType { - err = errors.New("x509: requested SignatureAlgorithm does not match private key type") - return - } - sigAlgo.Algorithm, hashFunc = details.oid, details.hash - if hashFunc == 0 && pubType != Ed25519 { - err = errors.New("x509: cannot sign with hash function requested") - return + return 0, ai, errors.New("x509: requested SignatureAlgorithm does not match private key type") } - if hashFunc == crypto.MD5 { - err = errors.New("x509: signing with MD5 is not supported") - return + if details.hash == crypto.MD5 { + return 0, ai, errors.New("x509: signing with MD5 is not supported") } - if requestedSigAlgo.isRSAPSS() { - sigAlgo.Parameters = hashToPSSParameters[hashFunc] - } - found = true - break + + return sigAlgo, pkix.AlgorithmIdentifier{ + Algorithm: details.oid, + Parameters: details.params, + }, nil } } - if !found { - err = errors.New("x509: unknown SignatureAlgorithm") + return 0, ai, errors.New("x509: unknown SignatureAlgorithm") +} + +func signTBS(tbs []byte, key crypto.Signer, sigAlg SignatureAlgorithm, rand io.Reader) ([]byte, error) { + signed := tbs + hashFunc := sigAlg.hashFunc() + if hashFunc != 0 { + h := hashFunc.New() + h.Write(signed) + signed = h.Sum(nil) } - return + var signerOpts crypto.SignerOpts = hashFunc + if sigAlg.isRSAPSS() { + signerOpts = &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: hashFunc, + } + } + + signature, err := key.Sign(rand, signed, signerOpts) + if err != nil { + return nil, err + } + + // Check the signature to ensure the crypto.Signer behaved correctly. + if err := checkSignature(sigAlg, tbs, signature, key.Public(), true); err != nil { + return nil, fmt.Errorf("x509: signature returned by signer is invalid: %w", err) + } + + return signature, nil } // emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is @@ -1600,7 +1619,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen") } - hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) + signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, template.SignatureAlgorithm) if err != nil { return nil, err } @@ -1657,7 +1676,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv c := tbsCertificate{ Version: 2, SerialNumber: template.SerialNumber, - SignatureAlgorithm: signatureAlgorithm, + SignatureAlgorithm: algorithmIdentifier, Issuer: asn1.RawValue{FullBytes: asn1Issuer}, Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, Subject: asn1.RawValue{FullBytes: asn1Subject}, @@ -1671,42 +1690,16 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv } c.Raw = tbsCertContents - signed := tbsCertContents - if hashFunc != 0 { - h := hashFunc.New() - h.Write(signed) - signed = h.Sum(nil) - } - - var signerOpts crypto.SignerOpts = hashFunc - if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() { - signerOpts = &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - Hash: hashFunc, - } - } - - var signature []byte - signature, err = key.Sign(rand, signed, signerOpts) + signature, err := signTBS(tbsCertContents, key, signatureAlgorithm, rand) if err != nil { return nil, err } - signedCert, err := asn1.Marshal(certificate{ - c, - signatureAlgorithm, - asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, + return asn1.Marshal(certificate{ + TBSCertificate: c, + SignatureAlgorithm: algorithmIdentifier, + SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) - if err != nil { - return nil, err - } - - // Check the signature to ensure the crypto.Signer behaved correctly. - if err := checkSignature(getSignatureAlgorithmFromAI(signatureAlgorithm), c.Raw, signature, key.Public(), true); err != nil { - return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) - } - - return signedCert, nil } // pemCRLPrefix is the magic string that indicates that we have a PEM encoded @@ -1756,7 +1749,7 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.Re return nil, errors.New("x509: certificate private key does not implement crypto.Signer") } - hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0) + signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, 0) if err != nil { return nil, err } @@ -1770,7 +1763,7 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.Re tbsCertList := pkix.TBSCertificateList{ Version: 1, - Signature: signatureAlgorithm, + Signature: algorithmIdentifier, Issuer: c.Subject.ToRDNSequence(), ThisUpdate: now.UTC(), NextUpdate: expiry.UTC(), @@ -1783,32 +1776,25 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.Re aki.Id = oidExtensionAuthorityKeyId aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId}) if err != nil { - return + return nil, err } tbsCertList.Extensions = append(tbsCertList.Extensions, aki) } tbsCertListContents, err := asn1.Marshal(tbsCertList) if err != nil { - return - } - - signed := tbsCertListContents - if hashFunc != 0 { - h := hashFunc.New() - h.Write(signed) - signed = h.Sum(nil) + return nil, err } + tbsCertList.Raw = tbsCertListContents - var signature []byte - signature, err = key.Sign(rand, signed, hashFunc) + signature, err := signTBS(tbsCertListContents, key, signatureAlgorithm, rand) if err != nil { - return + return nil, err } return asn1.Marshal(pkix.CertificateList{ TBSCertList: tbsCertList, - SignatureAlgorithm: signatureAlgorithm, + SignatureAlgorithm: algorithmIdentifier, SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) } @@ -1976,9 +1962,7 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv return nil, errors.New("x509: certificate private key does not implement crypto.Signer") } - var hashFunc crypto.Hash - var sigAlgo pkix.AlgorithmIdentifier - hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) + signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, template.SignatureAlgorithm) if err != nil { return nil, err } @@ -2050,7 +2034,7 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv rawAttributes, err := newRawAttributes(attributes) if err != nil { - return + return nil, err } // If not included in attributes, add a new attribute for the @@ -2100,38 +2084,19 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv tbsCSRContents, err := asn1.Marshal(tbsCSR) if err != nil { - return + return nil, err } tbsCSR.Raw = tbsCSRContents - signed := tbsCSRContents - if hashFunc != 0 { - h := hashFunc.New() - h.Write(signed) - signed = h.Sum(nil) - } - - var signerOpts crypto.SignerOpts = hashFunc - if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() { - signerOpts = &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - Hash: hashFunc, - } - } - - var signature []byte - signature, err = key.Sign(rand, signed, signerOpts) + signature, err := signTBS(tbsCSRContents, key, signatureAlgorithm, rand) if err != nil { - return + return nil, err } return asn1.Marshal(certificateRequest{ TBSCSR: tbsCSR, - SignatureAlgorithm: sigAlgo, - SignatureValue: asn1.BitString{ - Bytes: signature, - BitLength: len(signature) * 8, - }, + SignatureAlgorithm: algorithmIdentifier, + SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) } @@ -2359,7 +2324,7 @@ func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Cert return nil, errors.New("x509: template contains nil Number field") } - hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) + signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(priv, template.SignatureAlgorithm) if err != nil { return nil, err } @@ -2443,7 +2408,7 @@ func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Cert tbsCertList := tbsCertificateList{ Version: 1, // v2 - Signature: signatureAlgorithm, + Signature: algorithmIdentifier, Issuer: asn1.RawValue{FullBytes: issuerSubject}, ThisUpdate: template.ThisUpdate.UTC(), NextUpdate: template.NextUpdate.UTC(), @@ -2475,28 +2440,14 @@ func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Cert // then embedding in certificateList below. tbsCertList.Raw = tbsCertListContents - input := tbsCertListContents - if hashFunc != 0 { - h := hashFunc.New() - h.Write(tbsCertListContents) - input = h.Sum(nil) - } - var signerOpts crypto.SignerOpts = hashFunc - if template.SignatureAlgorithm.isRSAPSS() { - signerOpts = &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - Hash: hashFunc, - } - } - - signature, err := priv.Sign(rand, input, signerOpts) + signature, err := signTBS(tbsCertListContents, priv, signatureAlgorithm, rand) if err != nil { return nil, err } return asn1.Marshal(certificateList{ TBSCertList: tbsCertList, - SignatureAlgorithm: signatureAlgorithm, + SignatureAlgorithm: algorithmIdentifier, SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 026367b167..90c7ce9076 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1301,11 +1301,13 @@ func TestCRLCreation(t *testing.T) { crlBytes, err := test.cert.CreateCRL(rand.Reader, test.priv, revokedCerts, now, expiry) if err != nil { t.Errorf("%s: error creating CRL: %s", test.name, err) + continue } parsedCRL, err := ParseDERCRL(crlBytes) if err != nil { t.Errorf("%s: error reparsing CRL: %s", test.name, err) + continue } if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) { t.Errorf("%s: RevokedCertificates mismatch: got %v; want %v.", test.name, @@ -1815,7 +1817,7 @@ func TestInsecureAlgorithmErrorString(t *testing.T) { {MD5WithRSA, "x509: cannot verify signature: insecure algorithm MD5-RSA"}, {SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA (temporarily override with GODEBUG=x509sha1=1)"}, {ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1 (temporarily override with GODEBUG=x509sha1=1)"}, - {MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"}, + {MD2WithRSA, "x509: cannot verify signature: insecure algorithm 1"}, {-1, "x509: cannot verify signature: insecure algorithm -1"}, {0, "x509: cannot verify signature: insecure algorithm 0"}, {9999, "x509: cannot verify signature: insecure algorithm 9999"}, @@ -2959,10 +2961,13 @@ func TestRSAPSAParameters(t *testing.T) { return serialized } - for h, params := range hashToPSSParameters { - generated := generateParams(h) - if !bytes.Equal(params.FullBytes, generated) { - t.Errorf("hardcoded parameters for %s didn't match generated parameters: got (generated) %x, wanted (hardcoded) %x", h, generated, params.FullBytes) + for _, detail := range signatureAlgorithmDetails { + if !detail.isRSAPSS { + continue + } + generated := generateParams(detail.hash) + if !bytes.Equal(detail.params.FullBytes, generated) { + t.Errorf("hardcoded parameters for %s didn't match generated parameters: got (generated) %x, wanted (hardcoded) %x", detail.hash, generated, detail.params.FullBytes) } } } @@ -3138,15 +3143,11 @@ func TestCreateCertificateBrokenSigner(t *testing.T) { SerialNumber: big.NewInt(10), DNSNames: []string{"example.com"}, } - k, err := rsa.GenerateKey(rand.Reader, 1024) - if err != nil { - t.Fatalf("failed to generate test key: %s", err) - } - expectedErr := "x509: signature over certificate returned by signer is invalid: crypto/rsa: verification error" - _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) + expectedErr := "signature returned by signer is invalid" + _, err := CreateCertificate(rand.Reader, template, template, testPrivateKey.Public(), &brokenSigner{testPrivateKey.Public()}) if err == nil { t.Fatal("expected CreateCertificate to fail with a broken signer") - } else if err.Error() != expectedErr { + } else if !strings.Contains(err.Error(), expectedErr) { t.Fatalf("CreateCertificate returned an unexpected error: got %q, want %q", err, expectedErr) } } -- 2.48.1