crypto/tls: wrap ML-KEM hybrids in fips140.WithoutEnforcement

Fixes #78298
Fixes #78178
Fixes #75528
Fixes #75166
Fixes #76112

Change-Id: Ie78f3bf5f0b232482da44aba28a0f6d66a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/759383
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
Filippo Valsorda 2026-03-25 20:48:44 +01:00 committed by Gopher Robot
parent 8b2f069b14
commit 3103a23124
3 changed files with 50 additions and 3 deletions

View file

@ -7,7 +7,9 @@ package tls
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/fips140"
"crypto/internal/boring"
"crypto/internal/cryptotest"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
@ -96,6 +98,10 @@ func TestFIPSServerProtocolVersion(t *testing.T) {
test(t, "VersionTLS12", VersionTLS12, "")
test(t, "VersionTLS13", VersionTLS13, "")
})
if !fips140.Enforced() {
cryptotest.RerunWithFIPS140Enforced(t)
}
}
func isFIPSVersion(v uint16) bool {
@ -216,6 +222,10 @@ func TestFIPSServerCipherSuites(t *testing.T) {
})
})
}
if !fips140.Enforced() {
cryptotest.RerunWithFIPS140Enforced(t)
}
}
func TestFIPSServerCurves(t *testing.T) {
@ -241,6 +251,10 @@ func TestFIPSServerCurves(t *testing.T) {
})
})
}
if !fips140.Enforced() {
cryptotest.RerunWithFIPS140Enforced(t)
}
}
func fipsHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) {
@ -294,6 +308,10 @@ func TestFIPSServerSignatureAndHash(t *testing.T) {
})
})
}
if !fips140.Enforced() {
cryptotest.RerunWithFIPS140Enforced(t)
}
}
func TestFIPSClientHello(t *testing.T) {

View file

@ -7,6 +7,7 @@ package tls
import (
"crypto"
"crypto/ecdh"
"crypto/fips140"
"crypto/hmac"
"crypto/internal/fips140/tls13"
"crypto/mlkem"
@ -165,7 +166,14 @@ type hybridKeyExchange struct {
}
func (ke *hybridKeyExchange) keyShares(rand io.Reader) (*keySharePrivateKeys, []keyShare, error) {
priv, ecdhShares, err := ke.ecdh.keyShares(rand)
var (
priv *keySharePrivateKeys
ecdhShares []keyShare
err error
)
fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved.
priv, ecdhShares, err = ke.ecdh.keyShares(rand)
})
if err != nil {
return nil, nil, err
}
@ -201,7 +209,14 @@ func (ke *hybridKeyExchange) serverSharedSecret(rand io.Reader, clientKeyShare [
ecdhShareData = clientKeyShare[:ke.ecdhElementSize]
mlkemShareData = clientKeyShare[ke.ecdhElementSize:]
}
ecdhSharedSecret, ks, err := ke.ecdh.serverSharedSecret(rand, ecdhShareData)
var (
ecdhSharedSecret []byte
ks keyShare
err error
)
fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved.
ecdhSharedSecret, ks, err = ke.ecdh.serverSharedSecret(rand, ecdhShareData)
})
if err != nil {
return nil, keyShare{}, err
}
@ -234,7 +249,13 @@ func (ke *hybridKeyExchange) clientSharedSecret(priv *keySharePrivateKeys, serve
ecdhShareData = serverKeyShare[:ke.ecdhElementSize]
mlkemShareData = serverKeyShare[ke.ecdhElementSize:]
}
ecdhSharedSecret, err := ke.ecdh.clientSharedSecret(priv, ecdhShareData)
var (
ecdhSharedSecret []byte
err error
)
fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved.
ecdhSharedSecret, err = ke.ecdh.clientSharedSecret(priv, ecdhShareData)
})
if err != nil {
return nil, err
}

View file

@ -11,6 +11,7 @@ import (
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/fips140"
"crypto/internal/boring"
"crypto/rand"
"crypto/tls/internal/fips140tls"
@ -194,6 +195,13 @@ func runWithFIPSEnabled(t *testing.T, testFunc func(t *testing.T)) {
}
func runWithFIPSDisabled(t *testing.T, testFunc func(t *testing.T)) {
if fips140.Enforced() {
t.Run("no-fips140tls", func(t *testing.T) {
t.Skip("can't run no-fips140tls tests in fips140=only mode")
})
return
}
originalFIPS := fips140tls.Required()
defer func() {
if originalFIPS {