diff options
author | Roland Shoemaker <rolandshoemaker@gmail.com> | 2020-09-28 08:59:13 -0700 |
---|---|---|
committer | Roland Shoemaker <roland@golang.org> | 2020-09-28 18:46:39 +0000 |
commit | f33263d11aa0f5e2668bfc6a0805e4edee17b03c (patch) | |
tree | 81c13c9693a2b9365c146607c1e6db9f0c4755bc /src/crypto | |
parent | a424f6e45e29960c933a7ccc1cd8fc9bb2766f15 (diff) | |
download | go-f33263d11aa0f5e2668bfc6a0805e4edee17b03c.tar.gz go-f33263d11aa0f5e2668bfc6a0805e4edee17b03c.zip |
crypto/x509: hardcode RSA PSS parameters rather than generating them
Rather than generating the three possible RSA PSS parameters each time
they are needed just hardcode them and pick the required one based on
the hash function.
Fixes #41407
Change-Id: Id43bdaf40b3ca82c4c04c6588e3b643f63107657
Reviewed-on: https://go-review.googlesource.com/c/go/+/258037
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/x509/x509.go | 60 | ||||
-rw-r--r-- | src/crypto/x509/x509_test.go | 52 |
2 files changed, 66 insertions, 46 deletions
diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 49ac059a0e..16655a3c70 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -351,6 +351,19 @@ var signatureAlgorithmDetails = []struct { {PureEd25519, "Ed25519", oidSignatureEd25519, Ed25519, crypto.Hash(0) /* no pre-hashing */}, } +// hashToPSSParameters contains the 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}}, +} + // pssParameters reflects the parameters in an AlgorithmIdentifier that // specifies RSA PSS. See RFC 3447, Appendix A.2.3. type pssParameters struct { @@ -363,51 +376,6 @@ type pssParameters struct { TrailerField int `asn1:"optional,explicit,tag:3,default:1"` } -// rsaPSSParameters returns an asn1.RawValue suitable for use as the Parameters -// in an AlgorithmIdentifier that specifies RSA PSS. -func rsaPSSParameters(hashFunc crypto.Hash) asn1.RawValue { - var hashOID asn1.ObjectIdentifier - - switch hashFunc { - case crypto.SHA256: - hashOID = oidSHA256 - case crypto.SHA384: - hashOID = oidSHA384 - case crypto.SHA512: - hashOID = oidSHA512 - } - - params := pssParameters{ - Hash: pkix.AlgorithmIdentifier{ - Algorithm: hashOID, - Parameters: asn1.NullRawValue, - }, - MGF: pkix.AlgorithmIdentifier{ - Algorithm: oidMGF1, - }, - SaltLength: hashFunc.Size(), - TrailerField: 1, - } - - mgf1Params := pkix.AlgorithmIdentifier{ - Algorithm: hashOID, - Parameters: asn1.NullRawValue, - } - - var err error - params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params) - if err != nil { - panic(err) - } - - serialized, err := asn1.Marshal(params) - if err != nil { - panic(err) - } - - return asn1.RawValue{FullBytes: serialized} -} - func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm { if ai.Algorithm.Equal(oidSignatureEd25519) { // RFC 8410, Section 3 @@ -2015,7 +1983,7 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori return } if requestedSigAlgo.isRSAPSS() { - sigAlgo.Parameters = rsaPSSParameters(hashFunc) + sigAlgo.Parameters = hashToPSSParameters[hashFunc] } found = true break diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 840f535e55..d0315900e4 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -2702,3 +2702,55 @@ func TestCreateRevocationList(t *testing.T) { }) } } + +func TestRSAPSAParameters(t *testing.T) { + generateParams := func(hashFunc crypto.Hash) []byte { + var hashOID asn1.ObjectIdentifier + + switch hashFunc { + case crypto.SHA256: + hashOID = oidSHA256 + case crypto.SHA384: + hashOID = oidSHA384 + case crypto.SHA512: + hashOID = oidSHA512 + } + + params := pssParameters{ + Hash: pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.NullRawValue, + }, + MGF: pkix.AlgorithmIdentifier{ + Algorithm: oidMGF1, + }, + SaltLength: hashFunc.Size(), + TrailerField: 1, + } + + mgf1Params := pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.NullRawValue, + } + + var err error + params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params) + if err != nil { + t.Fatalf("failed to marshal MGF parameters: %s", err) + } + + serialized, err := asn1.Marshal(params) + if err != nil { + t.Fatalf("failed to marshal parameters: %s", err) + } + + 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) + } + } +} |