From 1ec36d8e5aa53fcf2af0920df2b6798d397098a1 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Thu, 15 Feb 2024 17:06:12 +0900 Subject: [PATCH] Offload TLS PRF to OpenSSL backend For FIPS compliance, this offloads the PRF computation in TLS to OpenSSL, based on the work by Quim Muntal in: https://github.com/microsoft/go/pull/1036 Note that, on RHEL-9, this may cause interoperability issue against the peers which do not use extended master secret, yielding a connection close with internal_error alert. The way to mitigate that behavior is described at: https://www.redhat.com/en/blog/tls-extended-master-secret-and-fips-rhel --- patches/000-initial-setup.patch | 124 ++++++++---------- patches/010-tls1prf.patch | 223 ++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+), 68 deletions(-) create mode 100644 patches/010-tls1prf.patch diff --git a/patches/000-initial-setup.patch b/patches/000-initial-setup.patch index 31a7d73a39..6175af1fd4 100644 --- a/patches/000-initial-setup.patch +++ b/patches/000-initial-setup.patch @@ -135,6 +135,27 @@ index f933f2800a..223ce04340 100644 testenv.MustHaveExternalNetwork(t) // Create a temp dir and modcache subdir. +diff --git a/src/crypto/internal/backend/bbig/big.go b/src/crypto/internal/backend/bbig/big.go +new file mode 100644 +index 0000000000..5652398605 +--- /dev/null ++++ b/src/crypto/internal/backend/bbig/big.go +@@ -0,0 +1,15 @@ ++// Copyright 2022 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// This is a mirror of ++// https://github.com/golang/go/blob/36b87f273cc43e21685179dc1664ebb5493d26ae/src/crypto/internal/boring/bbig/big.go. ++ ++package bbig ++ ++import ( ++ "github.com/golang-fips/openssl/v2/bbig" ++) ++ ++var Enc = bbig.Enc ++var Dec = bbig.Dec diff --git a/src/crypto/internal/backend/boringtest/config.go b/src/crypto/internal/backend/boringtest/config.go new file mode 100644 index 0000000000..6c8c00d11e @@ -192,10 +213,10 @@ new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/crypto/internal/backend/nobackend.go b/src/crypto/internal/backend/nobackend.go new file mode 100644 -index 0000000000..15c1ee8cbe +index 0000000000..528ded04d7 --- /dev/null +++ b/src/crypto/internal/backend/nobackend.go -@@ -0,0 +1,163 @@ +@@ -0,0 +1,170 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -359,12 +380,19 @@ index 0000000000..15c1ee8cbe +func HashSignECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) (*big.Int, *big.Int, error) { + panic("boringcrypto: not available") +} ++ ++func SupportsTLS1PRF() bool { ++ panic("boringcrypto: not available") ++} ++func TLS1PRF(result, secret, label, seed []byte, h func() hash.Hash) error { ++ panic("boringcrypto: not available") ++} diff --git a/src/crypto/internal/backend/openssl.go b/src/crypto/internal/backend/openssl.go new file mode 100644 -index 0000000000..2087c555a4 +index 0000000000..6ec71c625d --- /dev/null +++ b/src/crypto/internal/backend/openssl.go -@@ -0,0 +1,122 @@ +@@ -0,0 +1,125 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -487,27 +515,9 @@ index 0000000000..2087c555a4 +var ExtractHKDF = openssl.ExtractHKDF +var ExpandHKDF = openssl.ExpandHKDF +var SupportsHKDF = openssl.SupportsHKDF -diff --git a/src/crypto/internal/backend/bbig/big.go b/src/crypto/internal/backend/bbig/big.go -new file mode 100644 -index 0000000000..7fac1ec7e1 ---- /dev/null -+++ b/src/crypto/internal/backend/bbig/big.go -@@ -0,0 +1,15 @@ -+// Copyright 2022 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This is a mirror of -+// https://github.com/golang/go/blob/36b87f273cc43e21685179dc1664ebb5493d26ae/src/crypto/internal/boring/bbig/big.go. -+ -+package bbig -+ -+import ( -+ "github.com/golang-fips/openssl/v2/bbig" -+) + -+var Enc = bbig.Enc -+var Dec = bbig.Dec ++var SupportsTLS1PRF = openssl.SupportsTLS1PRF ++var TLS1PRF = openssl.TLS1PRF diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go index dfa1eddc88..39a4fc184a 100644 --- a/src/crypto/rsa/pkcs1v15_test.go @@ -734,28 +744,6 @@ index cf03e3cb7e..1226149321 100644 t.Fatalf("SignPSS unexpected error: got %v, want %v", err, InvalidSaltLenErr) } -diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go -index 63bc8dad1a..ab56ccd1ed 100644 ---- a/src/crypto/rsa/rsa.go -+++ b/src/crypto/rsa/rsa.go -@@ -509,7 +509,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l - if err != nil { - return nil, err - } -- return boring.EncryptRSAOAEP(hash, hash, bkey, msg, label) -+ return boring.EncryptRSAOAEP(hash, hash, bkey, msg, label) - } - boring.UnreachableExceptTests() - -@@ -680,7 +680,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, random io.Reader, priv *PrivateKey, ci - if err != nil { - return nil, err - } -- out, err := boring.DecryptRSAOAEP(hash, mgfHash, bkey, ciphertext, label) -+ out, err := boring.DecryptRSAOAEP(hash, mgfHash, bkey, ciphertext, label) - if err != nil { - return nil, ErrDecryption - } diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go index 3278a7ff30..b994daec19 100644 --- a/src/crypto/rsa/rsa_test.go @@ -1128,7 +1116,7 @@ index ba68f355eb..7bfe3f9417 100644 // A self-signed test certificate with an RSA key of size 2048, for testing diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go -index 04e6dfe018..b6ed936cd1 100644 +index 589e8b6faf..669208bb86 100644 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@ -354,6 +354,11 @@ var defaultCipherSuitesTLS13NoAES = []uint16{ @@ -1144,7 +1132,7 @@ index 04e6dfe018..b6ed936cd1 100644 hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go -index 5394d64ac6..db4e2dbf60 100644 +index e0885a0da9..5edbd19995 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -12,6 +12,7 @@ import ( @@ -1155,7 +1143,7 @@ index 5394d64ac6..db4e2dbf60 100644 "crypto/rand" "crypto/rsa" "crypto/sha512" -@@ -994,6 +995,9 @@ const roleServer = false +@@ -1031,6 +1032,9 @@ const roleServer = false func (c *Config) supportedVersions(isClient bool) []uint16 { versions := make([]uint16, 0, len(supportedVersions)) for _, v := range supportedVersions { @@ -1166,10 +1154,10 @@ index 5394d64ac6..db4e2dbf60 100644 continue } diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go -index 63d86b9f3a..a8ee915041 100644 +index 4649f36dea..5e1976caf3 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go -@@ -127,7 +127,9 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { +@@ -139,7 +139,9 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { if len(hello.supportedVersions) == 1 { hello.cipherSuites = nil } @@ -1181,10 +1169,10 @@ index 63d86b9f3a..a8ee915041 100644 } else { hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go -index 22be38faff..d460eeb880 100644 +index a2052ceb70..1666b58ef3 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go -@@ -2156,6 +2156,7 @@ func testBuffering(t *testing.T, version uint16) { +@@ -2198,6 +2198,7 @@ func testBuffering(t *testing.T, version uint16) { } func TestAlertFlushing(t *testing.T) { @@ -1193,7 +1181,7 @@ index 22be38faff..d460eeb880 100644 done := make(chan bool) diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go -index 4a8661085e..87fe11de5c 100644 +index 2f59f6888c..a84cede1b0 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -41,10 +41,6 @@ type clientHandshakeStateTLS13 struct { @@ -1208,10 +1196,10 @@ index 4a8661085e..87fe11de5c 100644 // sections 4.1.2 and 4.1.3. if c.handshakes > 0 { diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go -index b7b568cd84..af75e7dbe0 100644 +index 07b1a3851e..938a329668 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go -@@ -44,10 +44,6 @@ type serverHandshakeStateTLS13 struct { +@@ -45,10 +45,6 @@ type serverHandshakeStateTLS13 struct { func (hs *serverHandshakeStateTLS13) handshake() error { c := hs.c @@ -1223,7 +1211,7 @@ index b7b568cd84..af75e7dbe0 100644 if err := hs.processClientHello(); err != nil { return err diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go -index ae8f80a7cf..30a8450f40 100644 +index d7f082c9ee..e7a360fdd4 100644 --- a/src/crypto/tls/key_schedule.go +++ b/src/crypto/tls/key_schedule.go @@ -7,6 +7,7 @@ package tls @@ -1234,7 +1222,7 @@ index ae8f80a7cf..30a8450f40 100644 "errors" "fmt" "hash" -@@ -58,9 +59,20 @@ func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []by +@@ -59,9 +60,20 @@ func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []by panic(fmt.Errorf("failed to construct HKDF label: %s", err)) } out := make([]byte, length) @@ -1258,7 +1246,7 @@ index ae8f80a7cf..30a8450f40 100644 } return out } -@@ -78,7 +90,15 @@ func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { +@@ -79,7 +91,15 @@ func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { if newSecret == nil { newSecret = make([]byte, c.hash.Size()) } @@ -1305,7 +1293,7 @@ index 33fd0ed52b..102acda578 100644 I_R1 := testBoringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK) testBoringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK) diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go -index 8846b00312..8734dd03c1 100644 +index 19deeab54d..0c2cbf3182 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -12,6 +12,8 @@ import ( @@ -1424,7 +1412,7 @@ index 8846b00312..8734dd03c1 100644 commonName := "test.example.com" template := Certificate{ SerialNumber: big.NewInt(1), -@@ -3607,11 +3638,19 @@ func TestParseRevocationList(t *testing.T) { +@@ -3682,11 +3713,19 @@ func TestParseRevocationList(t *testing.T) { } func TestRevocationListCheckSignatureFrom(t *testing.T) { @@ -1447,10 +1435,10 @@ index 8846b00312..8734dd03c1 100644 t.Fatalf("failed to generate test key: %s", err) } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index 08452c7b1d..0732db0662 100644 +index 592f2fd72a..1c1caa6897 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go -@@ -396,9 +396,11 @@ var depsRules = ` +@@ -423,9 +423,11 @@ var depsRules = ` < crypto/internal/alias < crypto/cipher; @@ -1463,7 +1451,7 @@ index 08452c7b1d..0732db0662 100644 < crypto/boring; crypto/internal/alias -@@ -427,11 +429,13 @@ var depsRules = ` +@@ -454,11 +456,13 @@ var depsRules = ` crypto/sha512 < CRYPTO; @@ -1478,7 +1466,7 @@ index 08452c7b1d..0732db0662 100644 < crypto/rand < crypto/ed25519 < encoding/asn1 -@@ -629,6 +633,7 @@ func listStdPkgs(goroot string) ([]string, error) { +@@ -663,6 +667,7 @@ func listStdPkgs(goroot string) ([]string, error) { } func TestDependencies(t *testing.T) { @@ -1486,7 +1474,7 @@ index 08452c7b1d..0732db0662 100644 if !testenv.HasSrc() { // Tests run in a limited file system and we do not // provide access to every source file. -@@ -671,7 +676,7 @@ var buildIgnore = []byte("\n//go:build ignore") +@@ -705,7 +710,7 @@ var buildIgnore = []byte("\n//go:build ignore") func findImports(pkg string) ([]string, error) { vpkg := pkg @@ -1495,7 +1483,7 @@ index 08452c7b1d..0732db0662 100644 vpkg = "vendor/" + pkg } dir := filepath.Join(Default.GOROOT, "src", vpkg) -@@ -681,7 +686,7 @@ func findImports(pkg string) ([]string, error) { +@@ -715,7 +720,7 @@ func findImports(pkg string) ([]string, error) { } var imports []string var haveImport = map[string]bool{} @@ -1505,7 +1493,7 @@ index 08452c7b1d..0732db0662 100644 } fset := token.NewFileSet() diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go -index 780b481de8..63db9e9ed7 100644 +index 8ec9c9109a..d7f287261f 100644 --- a/src/runtime/pprof/proto_test.go +++ b/src/runtime/pprof/proto_test.go @@ -15,6 +15,7 @@ import ( diff --git a/patches/010-tls1prf.patch b/patches/010-tls1prf.patch new file mode 100644 index 0000000000..abea7de179 --- /dev/null +++ b/patches/010-tls1prf.patch @@ -0,0 +1,223 @@ +From 3e63a60fc6c59be87346e4c847b6baf41726126c Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Thu, 15 Feb 2024 17:17:18 +0900 +Subject: [PATCH] 010-tls1prf.patch + +--- + src/crypto/tls/prf.go | 77 ++++++++++++++++++++++++++------------ + src/crypto/tls/prf_test.go | 12 +++++- + 2 files changed, 64 insertions(+), 25 deletions(-) + +diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go +index 20bac96e86..c47391f684 100644 +--- a/src/crypto/tls/prf.go ++++ b/src/crypto/tls/prf.go +@@ -7,6 +7,7 @@ package tls + import ( + "crypto" + "crypto/hmac" ++ boring "crypto/internal/backend" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" +@@ -45,7 +46,13 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) { + } + + // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. +-func prf10(result, secret, label, seed []byte) { ++func prf10(result, secret, label, seed []byte) error { ++ if boring.Enabled && boring.SupportsTLS1PRF() && boring.SupportsHash(crypto.MD5SHA1) { ++ if err := boring.TLS1PRF(result, secret, label, seed, nil); err != nil { ++ return fmt.Errorf("crypto/tls: prf10: %v", err) ++ } ++ return nil ++ } + hashSHA1 := sha1.New + hashMD5 := md5.New + +@@ -61,16 +68,24 @@ func prf10(result, secret, label, seed []byte) { + for i, b := range result2 { + result[i] ^= b + } ++ return nil + } + + // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. +-func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { +- return func(result, secret, label, seed []byte) { ++func prf12(h crypto.Hash, hashFunc func() hash.Hash) func(result, secret, label, seed []byte) error { ++ return func(result, secret, label, seed []byte) error { ++ if boring.Enabled && boring.SupportsTLS1PRF() && boring.SupportsHash(h) { ++ if err := boring.TLS1PRF(result, secret, label, seed, hashFunc); err != nil { ++ return fmt.Errorf("crypto/tls: prf12: %v", err) ++ } ++ return nil ++ } + labelAndSeed := make([]byte, len(label)+len(seed)) + copy(labelAndSeed, label) + copy(labelAndSeed[len(label):], seed) + + pHash(result, secret, labelAndSeed, hashFunc) ++ return nil + } + } + +@@ -85,56 +100,64 @@ var keyExpansionLabel = []byte("key expansion") + var clientFinishedLabel = []byte("client finished") + var serverFinishedLabel = []byte("server finished") + +-func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { ++func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte) error, crypto.Hash) { + switch version { + case VersionTLS10, VersionTLS11: + return prf10, crypto.Hash(0) + case VersionTLS12: + if suite.flags&suiteSHA384 != 0 { +- return prf12(sha512.New384), crypto.SHA384 ++ h := crypto.SHA384 ++ return prf12(h, sha512.New384), h + } +- return prf12(sha256.New), crypto.SHA256 ++ h := crypto.SHA256 ++ return prf12(h, sha256.New), h + default: + panic("unknown version") + } + } + +-func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { ++func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) error { + prf, _ := prfAndHashForVersion(version, suite) + return prf + } + + // masterFromPreMasterSecret generates the master secret from the pre-master + // secret. See RFC 5246, Section 8.1. +-func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { ++func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) ([]byte, error) { + seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) + seed = append(seed, clientRandom...) + seed = append(seed, serverRandom...) + + masterSecret := make([]byte, masterSecretLength) +- prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) +- return masterSecret ++ if err := prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed); err != nil { ++ return nil, err ++ } ++ return masterSecret, nil + } + + // extMasterFromPreMasterSecret generates the extended master secret from the + // pre-master secret. See RFC 7627. +-func extMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, transcript []byte) []byte { ++func extMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, transcript []byte) ([]byte, error) { + masterSecret := make([]byte, masterSecretLength) +- prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, transcript) +- return masterSecret ++ if err := prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, transcript); err != nil { ++ return nil, err ++ } ++ return masterSecret, nil + } + + // keysFromMasterSecret generates the connection keys from the master + // secret, given the lengths of the MAC key, cipher key and IV, as defined in + // RFC 2246, Section 6.3. +-func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { ++func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte, err error) { + seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) + seed = append(seed, serverRandom...) + seed = append(seed, clientRandom...) + + n := 2*macLen + 2*keyLen + 2*ivLen + keyMaterial := make([]byte, n) +- prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) ++ if err = prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed); err != nil { ++ return ++ } + clientMAC = keyMaterial[:macLen] + keyMaterial = keyMaterial[macLen:] + serverMAC = keyMaterial[:macLen] +@@ -177,7 +200,7 @@ type finishedHash struct { + buffer []byte + + version uint16 +- prf func(result, secret, label, seed []byte) ++ prf func(result, secret, label, seed []byte) error + } + + func (h *finishedHash) Write(msg []byte) (n int, err error) { +@@ -208,18 +231,22 @@ func (h finishedHash) Sum() []byte { + + // clientSum returns the contents of the verify_data member of a client's + // Finished message. +-func (h finishedHash) clientSum(masterSecret []byte) []byte { ++func (h finishedHash) clientSum(masterSecret []byte) ([]byte, error) { + out := make([]byte, finishedVerifyLength) +- h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) +- return out ++ if err := h.prf(out, masterSecret, clientFinishedLabel, h.Sum()); err != nil { ++ return nil, err ++ } ++ return out, nil + } + + // serverSum returns the contents of the verify_data member of a server's + // Finished message. +-func (h finishedHash) serverSum(masterSecret []byte) []byte { ++func (h finishedHash) serverSum(masterSecret []byte) ([]byte, error) { + out := make([]byte, finishedVerifyLength) +- h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) +- return out ++ if err := h.prf(out, masterSecret, serverFinishedLabel, h.Sum()); err != nil { ++ return nil, err ++ } ++ return out, nil + } + + // hashForClientCertificate returns the handshake messages so far, pre-hashed if +@@ -286,7 +313,11 @@ func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clien + } + + keyMaterial := make([]byte, length) +- prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) ++ if err := prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed); err != nil { ++ // Could happen if the seed is too large. The Go implementation doesn't limit the seed size, ++ // as RFC 5705 doesn't specify a limit, but stock OpenSSL restrict it to 1024 and CNG to 256. ++ return nil, err ++ } + return keyMaterial, nil + } + } +diff --git a/src/crypto/tls/prf_test.go b/src/crypto/tls/prf_test.go +index 8233985a62..f46d463655 100644 +--- a/src/crypto/tls/prf_test.go ++++ b/src/crypto/tls/prf_test.go +@@ -51,13 +51,21 @@ func TestKeysFromPreMasterSecret(t *testing.T) { + clientRandom, _ := hex.DecodeString(test.clientRandom) + serverRandom, _ := hex.DecodeString(test.serverRandom) + +- masterSecret := masterFromPreMasterSecret(test.version, test.suite, in, clientRandom, serverRandom) ++ masterSecret, err := masterFromPreMasterSecret(test.version, test.suite, in, clientRandom, serverRandom) ++ if err != nil { ++ t.Errorf("#%d: masterFromPreMasterSecret failed: %s", i, err) ++ continue ++ } + if s := hex.EncodeToString(masterSecret); s != test.masterSecret { + t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret) + continue + } + +- clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0) ++ clientMAC, serverMAC, clientKey, serverKey, _, _, err := keysFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0) ++ if err != nil { ++ t.Errorf("#%d: keysFromMasterSecret failed: %s", i, err) ++ continue ++ } + clientMACString := hex.EncodeToString(clientMAC) + serverMACString := hex.EncodeToString(serverMAC) + clientKeyString := hex.EncodeToString(clientKey) +-- +2.43.0 +