@@ -11,7 +11,6 @@ import (
1111 "crypto/ecdsa"
1212 "crypto/ed25519"
1313 "crypto/hpke"
14- "crypto/internal/fips140/mlkem"
1514 "crypto/internal/fips140/tls13"
1615 "crypto/rsa"
1716 "crypto/subtle"
@@ -142,43 +141,21 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCli
142141 if len (hello .supportedCurves ) == 0 {
143142 return nil , nil , nil , errors .New ("tls: no supported elliptic curves for ECDHE" )
144143 }
144+ // Since the order is fixed, the first one is always the one to send a
145+ // key share for. All the PQ hybrids sort first, and produce a fallback
146+ // ECDH share.
145147 curveID := hello .supportedCurves [0 ]
146- keyShareKeys = & keySharePrivateKeys {curveID : curveID }
147- // Note that if X25519MLKEM768 is supported, it will be first because
148- // the preference order is fixed.
149- if curveID == X25519MLKEM768 {
150- keyShareKeys .ecdhe , err = generateECDHEKey (config .rand (), X25519 )
151- if err != nil {
152- return nil , nil , nil , err
153- }
154- seed := make ([]byte , mlkem .SeedSize )
155- if _ , err := io .ReadFull (config .rand (), seed ); err != nil {
156- return nil , nil , nil , err
157- }
158- keyShareKeys .mlkem , err = mlkem .NewDecapsulationKey768 (seed )
159- if err != nil {
160- return nil , nil , nil , err
161- }
162- mlkemEncapsulationKey := keyShareKeys .mlkem .EncapsulationKey ().Bytes ()
163- x25519EphemeralKey := keyShareKeys .ecdhe .PublicKey ().Bytes ()
164- hello .keyShares = []keyShare {
165- {group : X25519MLKEM768 , data : append (mlkemEncapsulationKey , x25519EphemeralKey ... )},
166- }
167- // If both X25519MLKEM768 and X25519 are supported, we send both key
168- // shares (as a fallback) and we reuse the same X25519 ephemeral
169- // key, as allowed by draft-ietf-tls-hybrid-design-09, Section 3.2.
170- if slices .Contains (hello .supportedCurves , X25519 ) {
171- hello .keyShares = append (hello .keyShares , keyShare {group : X25519 , data : x25519EphemeralKey })
172- }
173- } else {
174- if _ , ok := curveForCurveID (curveID ); ! ok {
175- return nil , nil , nil , errors .New ("tls: CurvePreferences includes unsupported curve" )
176- }
177- keyShareKeys .ecdhe , err = generateECDHEKey (config .rand (), curveID )
178- if err != nil {
179- return nil , nil , nil , err
180- }
181- hello .keyShares = []keyShare {{group : curveID , data : keyShareKeys .ecdhe .PublicKey ().Bytes ()}}
148+ ke , err := keyExchangeForCurveID (curveID )
149+ if err != nil {
150+ return nil , nil , nil , errors .New ("tls: CurvePreferences includes unsupported curve" )
151+ }
152+ keyShareKeys , hello .keyShares , err = ke .keyShares (config .rand ())
153+ if err != nil {
154+ return nil , nil , nil , err
155+ }
156+ // Only send the fallback ECDH share if the corresponding CurveID is enabled.
157+ if len (hello .keyShares ) == 2 && ! slices .Contains (hello .supportedCurves , hello .keyShares [1 ].group ) {
158+ hello .keyShares = hello .keyShares [:1 ]
182159 }
183160 }
184161
0 commit comments