crypto/tls: use mlkem.GenerateKey for ML-KEM hybrids

We were using mlkem.NewDecapsulationKey on a random slice to support
Config.Rand, but Encapsulate was already bypassing Config.Rand anyway.

Config.Rand is deprecated anyway in favor of
cryptotest.SetDefaultRandom, so switch to mlkem.GenerateKey which has
better FIPS 140-3 compliance.

Updates #79367

Change-Id: I62a5099bd69a1ee2941d5ae1c9c2bf4b6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/777320
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Filippo Valsorda 2026-05-12 14:03:58 -04:00 committed by Gopher Robot
parent 27532dc35c
commit 97a57b481f

View file

@ -74,16 +74,16 @@ type keyExchange interface {
}
func keyExchangeForCurveID(id CurveID) (keyExchange, error) {
newMLKEMPrivateKey768 := func(b []byte) (crypto.Decapsulator, error) {
return mlkem.NewDecapsulationKey768(b)
mlkemGenerateKey768 := func() (crypto.Decapsulator, error) {
return mlkem.GenerateKey768()
}
newMLKEMPrivateKey1024 := func(b []byte) (crypto.Decapsulator, error) {
return mlkem.NewDecapsulationKey1024(b)
mlkemGenerateKey1024 := func() (crypto.Decapsulator, error) {
return mlkem.GenerateKey1024()
}
newMLKEMPublicKey768 := func(b []byte) (crypto.Encapsulator, error) {
mlkemNewPublicKey768 := func(b []byte) (crypto.Encapsulator, error) {
return mlkem.NewEncapsulationKey768(b)
}
newMLKEMPublicKey1024 := func(b []byte) (crypto.Encapsulator, error) {
mlkemNewPublicKey1024 := func(b []byte) (crypto.Encapsulator, error) {
return mlkem.NewEncapsulationKey1024(b)
}
switch id {
@ -98,15 +98,15 @@ func keyExchangeForCurveID(id CurveID) (keyExchange, error) {
case X25519MLKEM768:
return &hybridKeyExchange{id, ecdhKeyExchange{X25519, ecdh.X25519()},
32, mlkem.EncapsulationKeySize768, mlkem.CiphertextSize768,
newMLKEMPrivateKey768, newMLKEMPublicKey768}, nil
mlkemGenerateKey768, mlkemNewPublicKey768}, nil
case SecP256r1MLKEM768:
return &hybridKeyExchange{id, ecdhKeyExchange{CurveP256, ecdh.P256()},
65, mlkem.EncapsulationKeySize768, mlkem.CiphertextSize768,
newMLKEMPrivateKey768, newMLKEMPublicKey768}, nil
mlkemGenerateKey768, mlkemNewPublicKey768}, nil
case SecP384r1MLKEM1024:
return &hybridKeyExchange{id, ecdhKeyExchange{CurveP384, ecdh.P384()},
97, mlkem.EncapsulationKeySize1024, mlkem.CiphertextSize1024,
newMLKEMPrivateKey1024, newMLKEMPublicKey1024}, nil
mlkemGenerateKey1024, mlkemNewPublicKey1024}, nil
default:
return nil, errors.New("tls: unsupported key exchange")
}
@ -161,8 +161,8 @@ type hybridKeyExchange struct {
mlkemPublicKeySize int
mlkemCiphertextSize int
newMLKEMPrivateKey func([]byte) (crypto.Decapsulator, error)
newMLKEMPublicKey func([]byte) (crypto.Encapsulator, error)
mlkemGenerateKey func() (crypto.Decapsulator, error)
mlkemNewPublicKey func([]byte) (crypto.Encapsulator, error)
}
func (ke *hybridKeyExchange) keyShares(rand io.Reader) (*keySharePrivateKeys, []keyShare, error) {
@ -177,11 +177,7 @@ func (ke *hybridKeyExchange) keyShares(rand io.Reader) (*keySharePrivateKeys, []
if err != nil {
return nil, nil, err
}
seed := make([]byte, mlkem.SeedSize)
if _, err := io.ReadFull(rand, seed); err != nil {
return nil, nil, err
}
priv.mlkem, err = ke.newMLKEMPrivateKey(seed)
priv.mlkem, err = ke.mlkemGenerateKey()
if err != nil {
return nil, nil, err
}
@ -220,7 +216,7 @@ func (ke *hybridKeyExchange) serverSharedSecret(rand io.Reader, clientKeyShare [
if err != nil {
return nil, keyShare{}, err
}
mlkemPeerKey, err := ke.newMLKEMPublicKey(mlkemShareData)
mlkemPeerKey, err := ke.mlkemNewPublicKey(mlkemShareData)
if err != nil {
return nil, keyShare{}, err
}