From b130dab7927741223d40f221e27f3bd351e9cddf Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 9 Dec 2025 01:04:16 +0100 Subject: [PATCH] crypto/hpke: apply fips140.WithoutEnforcement to ML-KEM+X25519 hybrid Since it uses an Approved KEM (ML-KEM), the overall hybrid KEM is Approved, even if X25519 is not. Updates #70514 Updates #74630 Change-Id: I2bb60c36fcf570baa3c389e2daa3698e6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/728505 Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker Reviewed-by: Dmitri Shuralyov --- src/crypto/hpke/pq.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/crypto/hpke/pq.go b/src/crypto/hpke/pq.go index f2adbef54e..e8dc80fd23 100644 --- a/src/crypto/hpke/pq.go +++ b/src/crypto/hpke/pq.go @@ -8,6 +8,7 @@ import ( "bytes" "crypto" "crypto/ecdh" + "crypto/fips140" "crypto/internal/fips140/drbg" "crypto/internal/rand" "crypto/mlkem" @@ -168,7 +169,10 @@ func (kem *hybridKEM) NewPublicKey(data []byte) (PublicKey, error) { if err != nil { return nil, err } - k, err := kem.curve.NewPublicKey(data[kem.pqEncapsKeySize:]) + var k *ecdh.PublicKey + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + k, err = kem.curve.NewPublicKey(data[kem.pqEncapsKeySize:]) + }) if err != nil { return nil, err } @@ -186,14 +190,20 @@ func (pk *hybridPublicKey) Bytes() []byte { var testingOnlyEncapsulate func() (ss, ct []byte) func (pk *hybridPublicKey) encap() (sharedSecret []byte, encapPub []byte, err error) { - skE, err := pk.t.Curve().GenerateKey(rand.Reader) + var skE *ecdh.PrivateKey + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + skE, err = pk.t.Curve().GenerateKey(rand.Reader) + }) if err != nil { return nil, nil, err } if testingOnlyGenerateKey != nil { skE = testingOnlyGenerateKey() } - ssT, err := skE.ECDH(pk.t) + var ssT []byte + fips140.WithoutEnforcement(func() { + ssT, err = skE.ECDH(pk.t) + }) if err != nil { return nil, nil, err } @@ -259,7 +269,10 @@ func (kem *hybridKEM) NewPrivateKey(priv []byte) (PrivateKey, error) { seedT := make([]byte, kem.curveSeedSize) for { s.Read(seedT) - k, err := kem.curve.NewPrivateKey(seedT) + var k ecdh.KeyExchanger + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + k, err = kem.curve.NewPrivateKey(seedT) + }) if err != nil { continue } @@ -326,11 +339,17 @@ func (k *hybridPrivateKey) decap(enc []byte) ([]byte, error) { if err != nil { return nil, err } - pub, err := k.t.Curve().NewPublicKey(ctT) + var pub *ecdh.PublicKey + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + pub, err = k.t.Curve().NewPublicKey(ctT) + }) if err != nil { return nil, err } - ssT, err := k.t.ECDH(pub) + var ssT []byte + fips140.WithoutEnforcement(func() { + ssT, err = k.t.ECDH(pub) + }) if err != nil { return nil, err } -- 2.52.0