diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 15db760716c..eb740c03b5e 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -1932,6 +1932,7 @@ func TestAESCipherReorderingTLS13(t *testing.T) { supportedVersions: []uint16{VersionTLS13}, compressionMethods: []uint8{compressionNone}, keyShares: []keyShare{{group: X25519, data: pk.PublicKey().Bytes()}}, + supportedCurves: []CurveID{X25519}, }, } diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index f65a4edf34a..298d271d5c6 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -256,26 +256,19 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { } } - // Pick the ECDHE group in server preference order, but give priority to - // groups with a key share, to avoid a HelloRetryRequest round-trip. + // Pick group by server preference. In contrast to upstream Go, we will + // send an HelloRetryRequest and accept an extra roundtrip if there is + // a more preferred group, than those for which the client has sent + // a keyshare in the initial ClientHello. + // Cf. https://datatracker.ietf.org/doc/draft-davidben-tls-key-share-prediction/ var selectedGroup CurveID var clientKeyShare *keyShare GroupSelection: for _, preferredGroup := range supportedCurves { - for _, ks := range hs.clientHello.keyShares { - if ks.group == preferredGroup { - selectedGroup = ks.group - clientKeyShare = &ks - break GroupSelection - } - } - if selectedGroup != 0 { - continue - } for _, group := range hs.clientHello.supportedCurves { if group == preferredGroup { selectedGroup = group - break + break GroupSelection } } } @@ -283,6 +276,12 @@ GroupSelection: c.sendAlert(alertHandshakeFailure) return errors.New("tls: no ECDHE curve supported by both client and server") } + for _, ks := range hs.clientHello.keyShares { + if ks.group == selectedGroup { + clientKeyShare = &ks + break + } + } if clientKeyShare == nil { if err := hs.doHelloRetryRequest(selectedGroup); err != nil { return err