crypto/tls: implement MLKEM1024 key exchange

Fixes #78543

Change-Id: I26a70a64665c75e5116b83f73a75093f6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/777221
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>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
yuhan6665
2026-09-10 22:11:48 -04:00
parent a18db620ec
commit 72e1a2490a
7 changed files with 44 additions and 8 deletions
+3 -2
View File
@@ -155,11 +155,12 @@ const (
X25519MLKEM768 CurveID = 4588
SecP256r1MLKEM768 CurveID = 4587
SecP384r1MLKEM1024 CurveID = 4589
MLKEM1024 CurveID = 514
)
func isTLS13OnlyKeyExchange(curve CurveID) bool {
switch curve {
case X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024:
case X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024, MLKEM1024:
return true
default:
return false
@@ -168,7 +169,7 @@ func isTLS13OnlyKeyExchange(curve CurveID) bool {
func isPQKeyExchange(curve CurveID) bool {
switch curve {
case X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024:
case X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024, MLKEM1024:
return true
default:
return false
+7 -3
View File
@@ -82,17 +82,19 @@ func _() {
_ = x[X25519MLKEM768-4588]
_ = x[SecP256r1MLKEM768-4587]
_ = x[SecP384r1MLKEM1024-4589]
_ = x[MLKEM1024-514]
}
const (
_CurveID_name_0 = "CurveP256CurveP384CurveP521"
_CurveID_name_1 = "X25519"
_CurveID_name_2 = "SecP256r1MLKEM768X25519MLKEM768SecP384r1MLKEM1024"
_CurveID_name_2 = "MLKEM1024"
_CurveID_name_3 = "SecP256r1MLKEM768X25519MLKEM768SecP384r1MLKEM1024"
)
var (
_CurveID_index_0 = [...]uint8{0, 9, 18, 27}
_CurveID_index_2 = [...]uint8{0, 17, 31, 49}
_CurveID_index_3 = [...]uint8{0, 17, 31, 49}
)
func (i CurveID) String() string {
@@ -102,9 +104,11 @@ func (i CurveID) String() string {
return _CurveID_name_0[_CurveID_index_0[i]:_CurveID_index_0[i+1]]
case i == 29:
return _CurveID_name_1
case i == 514:
return _CurveID_name_2
case 4587 <= i && i <= 4589:
i -= 4587
return _CurveID_name_2[_CurveID_index_2[i]:_CurveID_index_2[i+1]]
return _CurveID_name_3[_CurveID_index_3[i]:_CurveID_index_3[i+1]]
default:
return "CurveID(" + strconv.FormatInt(int64(i), 10) + ")"
}
+1 -1
View File
@@ -37,7 +37,7 @@ func defaultCurveEnabled(c CurveID) bool {
// include every supported key exchange.
func curvePreferenceOrder() []CurveID {
return []CurveID{
X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024,
X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024, MLKEM1024,
X25519, CurveP256, CurveP384, CurveP521,
}
}
+1
View File
@@ -35,6 +35,7 @@ var (
X25519MLKEM768,
SecP256r1MLKEM768,
SecP384r1MLKEM1024,
MLKEM1024,
CurveP256,
CurveP384,
CurveP521,
+1 -1
View File
@@ -140,7 +140,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCli
}
if len(hello.supportedCurves) == 0 {
return nil, nil, nil, errors.New("tls: no supported elliptic curves for ECDHE")
return nil, nil, nil, errors.New("tls: no supported key exchange methods (CurveIDs)")
}
// Since the order is fixed, the first one is always the one to send a
// key share for. All the PQ hybrids sort first, and produce a fallback
+2 -1
View File
@@ -54,7 +54,8 @@ func (hs *clientHandshakeStateTLS13) handshake() error {
}
// Consistency check on the presence of a keyShare and its parameters.
if hs.keyShareKeys == nil || hs.keyShareKeys.ecdhe == nil || len(hs.hello.keyShares) == 0 {
if hs.keyShareKeys == nil || (hs.keyShareKeys.ecdhe == nil && hs.keyShareKeys.mlkem == nil) ||
len(hs.hello.keyShares) == 0 {
return c.sendAlert(alertInternalError)
}
+29
View File
@@ -108,11 +108,40 @@ func keyExchangeForCurveID(id CurveID) (keyExchange, error) {
return &hybridKeyExchange{id, ecdhKeyExchange{CurveP384, ecdh.P384()},
97, mlkem.EncapsulationKeySize1024, mlkem.CiphertextSize1024,
mlkemGenerateKey1024, mlkemNewPublicKey1024}, nil
case MLKEM1024:
return &mlkem1024KeyExchange{}, nil
default:
return nil, errors.New("tls: unsupported key exchange")
}
}
type mlkem1024KeyExchange struct{}
func (ke *mlkem1024KeyExchange) keyShares(_ io.Reader) (*keySharePrivateKeys, []keyShare, error) {
priv, err := mlkem.GenerateKey1024()
if err != nil {
return nil, nil, err
}
return &keySharePrivateKeys{mlkem: priv}, []keyShare{{MLKEM1024, priv.EncapsulationKey().Bytes()}}, nil
}
func (ke *mlkem1024KeyExchange) serverSharedSecret(_ io.Reader, clientKeyShare []byte) ([]byte, keyShare, error) {
peerKey, err := mlkem.NewEncapsulationKey1024(clientKeyShare)
if err != nil {
return nil, keyShare{}, err
}
sharedKey, keyShareData := peerKey.Encapsulate()
return sharedKey, keyShare{MLKEM1024, keyShareData}, nil
}
func (ke *mlkem1024KeyExchange) clientSharedSecret(priv *keySharePrivateKeys, serverKeyShare []byte) ([]byte, error) {
sharedKey, err := priv.mlkem.Decapsulate(serverKeyShare)
if err != nil {
return nil, err
}
return sharedKey, nil
}
type ecdhKeyExchange struct {
id CurveID
curve ecdh.Curve