sync: merge changes from go 1.23.4

This commit is contained in:
Mingye Chen 2025-01-07 15:55:09 -07:00
commit cefe226467
98 changed files with 8089 additions and 4530 deletions

View file

@ -10,12 +10,14 @@ import (
"crypto"
"crypto/hmac"
"crypto/rsa"
"encoding/binary"
"errors"
"fmt"
"hash"
"io"
"slices"
"time"
"github.com/refraction-networking/utls/internal/byteorder"
"github.com/refraction-networking/utls/internal/mlkem768"
)
// maxClientPSKIdentities is the number of client PSK identities the server will
@ -165,9 +167,6 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
preferenceList = defaultCipherSuitesTLS13NoAES
}
if needFIPS() {
preferenceList = defaultCipherSuitesTLS13FIPS
}
for _, suiteID := range preferenceList {
hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
if hs.suite != nil {
@ -182,25 +181,29 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
hs.hello.cipherSuite = hs.suite.id
hs.transcript = hs.suite.hash.New()
// Pick the ECDHE group in server preference order, but give priority to
// groups with a key share, to avoid a HelloRetryRequest round-trip.
// Pick the key exchange method in server preference order, but give
// priority to key shares, to avoid a HelloRetryRequest round-trip.
var selectedGroup CurveID
var clientKeyShare *keyShare
GroupSelection:
for _, preferredGroup := range c.config.curvePreferences() {
for _, ks := range hs.clientHello.keyShares {
if ks.group == preferredGroup {
selectedGroup = ks.group
clientKeyShare = &ks
break GroupSelection
preferredGroups := c.config.curvePreferences(c.vers)
for _, preferredGroup := range preferredGroups {
ki := slices.IndexFunc(hs.clientHello.keyShares, func(ks keyShare) bool {
return ks.group == preferredGroup
})
if ki != -1 {
clientKeyShare = &hs.clientHello.keyShares[ki]
selectedGroup = clientKeyShare.group
if !slices.Contains(hs.clientHello.supportedCurves, selectedGroup) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: client sent key share for group it does not support")
}
break
}
if selectedGroup != 0 {
continue
}
for _, group := range hs.clientHello.supportedCurves {
if group == preferredGroup {
selectedGroup = group
}
if selectedGroup == 0 {
for _, preferredGroup := range preferredGroups {
if slices.Contains(hs.clientHello.supportedCurves, preferredGroup) {
selectedGroup = preferredGroup
break
}
}
@ -210,43 +213,53 @@ GroupSelection:
return errors.New("tls: no ECDHE curve supported by both client and server")
}
if clientKeyShare == nil {
if err := hs.doHelloRetryRequest(selectedGroup); err != nil {
ks, err := hs.doHelloRetryRequest(selectedGroup)
if err != nil {
return err
}
clientKeyShare = &hs.clientHello.keyShares[0]
clientKeyShare = ks
}
c.curveID = selectedGroup
// [uTLS SECTION BEGIN]
// ported from cloudflare/go
if _, ok := curveForCurveID(selectedGroup); selectedGroup != X25519 && curveIdToCirclScheme(selectedGroup) == nil && !ok {
ecdhGroup := selectedGroup
ecdhData := clientKeyShare.data
if selectedGroup == x25519Kyber768Draft00 {
ecdhGroup = X25519
if len(ecdhData) != x25519PublicKeySize+mlkem768.EncapsulationKeySize {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid Kyber client key share")
}
ecdhData = ecdhData[:x25519PublicKeySize]
}
if _, ok := curveForCurveID(ecdhGroup); !ok {
c.sendAlert(alertInternalError)
return errors.New("tls: CurvePreferences includes unsupported curve")
}
if kem := curveIdToCirclScheme(selectedGroup); kem != nil {
ct, ss, alert, err := encapsulateForKem(kem, c.config.rand(), clientKeyShare.data)
if err != nil {
c.sendAlert(alert)
return fmt.Errorf("%s encap: %w", kem.Name(), err)
}
hs.hello.serverShare = keyShare{group: selectedGroup, data: ct}
hs.sharedKey = ss
} else {
key, err := generateECDHEKey(c.config.rand(), selectedGroup)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
hs.hello.serverShare = keyShare{group: selectedGroup, data: key.PublicKey().Bytes()}
peerKey, err := key.Curve().NewPublicKey(clientKeyShare.data)
if err == nil {
hs.sharedKey, _ = key.ECDH(peerKey)
}
key, err := generateECDHEKey(c.config.rand(), ecdhGroup)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
if hs.sharedKey == nil {
hs.hello.serverShare = keyShare{group: selectedGroup, data: key.PublicKey().Bytes()}
peerKey, err := key.Curve().NewPublicKey(ecdhData)
if err != nil {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid client key share")
}
// [uTLS SECTION END]
hs.sharedKey, err = key.ECDH(peerKey)
if err != nil {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid client key share")
}
if selectedGroup == x25519Kyber768Draft00 {
ciphertext, kyberShared, err := kyberEncapsulate(clientKeyShare.data[x25519PublicKeySize:])
if err != nil {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid Kyber client key share")
}
hs.sharedKey = append(hs.sharedKey, kyberShared...)
hs.hello.serverShare.data = append(hs.hello.serverShare.data, ciphertext...)
}
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, c.quic != nil)
if err != nil {
@ -366,6 +379,12 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
continue
}
if c.quic != nil && c.quic.enableSessionEvents {
if err := c.quicResumeSession(sessionState); err != nil {
return err
}
}
hs.earlySecret = hs.suite.extract(sessionState.secret, nil)
binderKey := hs.suite.deriveSecret(hs.earlySecret, resumptionBinderLabel, nil)
// Clone the transcript in case a HelloRetryRequest was recorded.
@ -490,13 +509,13 @@ func (hs *serverHandshakeStateTLS13) sendDummyChangeCipherSpec() error {
return hs.c.writeChangeCipherRecord()
}
func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error {
func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) (*keyShare, error) {
c := hs.c
// The first ClientHello gets double-hashed into the transcript upon a
// HelloRetryRequest. See RFC 8446, Section 4.4.1.
if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil {
return err
return nil, err
}
chHash := hs.transcript.Sum(nil)
hs.transcript.Reset()
@ -514,42 +533,49 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID)
}
if _, err := hs.c.writeHandshakeRecord(helloRetryRequest, hs.transcript); err != nil {
return err
return nil, err
}
if err := hs.sendDummyChangeCipherSpec(); err != nil {
return err
return nil, err
}
// clientHelloMsg is not included in the transcript.
msg, err := c.readHandshake(nil)
if err != nil {
return err
return nil, err
}
clientHello, ok := msg.(*clientHelloMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(clientHello, msg)
return nil, unexpectedMessageError(clientHello, msg)
}
if len(clientHello.keyShares) != 1 || clientHello.keyShares[0].group != selectedGroup {
if len(clientHello.keyShares) != 1 {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: client sent invalid key share in second ClientHello")
return nil, errors.New("tls: client didn't send one key share in second ClientHello")
}
ks := &clientHello.keyShares[0]
if ks.group != selectedGroup {
c.sendAlert(alertIllegalParameter)
return nil, errors.New("tls: client sent unexpected key share in second ClientHello")
}
if clientHello.earlyData {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: client indicated early data in second ClientHello")
return nil, errors.New("tls: client indicated early data in second ClientHello")
}
if illegalClientHelloChange(clientHello, hs.clientHello) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: client illegally modified second ClientHello")
return nil, errors.New("tls: client illegally modified second ClientHello")
}
c.didHRR = true
hs.clientHello = clientHello
return nil
return ks, nil
}
// illegalClientHelloChange reports whether the two ClientHello messages are
@ -838,10 +864,10 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
if !hs.shouldSendSessionTickets() {
return nil
}
return c.sendSessionTicket(false)
return c.sendSessionTicket(false, nil)
}
func (c *Conn) sendSessionTicket(earlyData bool) error {
func (c *Conn) sendSessionTicket(earlyData bool, extra [][]byte) error {
suite := cipherSuiteTLS13ByID(c.cipherSuite)
if suite == nil {
return errors.New("tls: internal error: unknown cipher suite")
@ -853,13 +879,12 @@ func (c *Conn) sendSessionTicket(earlyData bool) error {
m := new(newSessionTicketMsgTLS13)
state, err := c.sessionState()
if err != nil {
return err
}
state := c.sessionState()
state.secret = psk
state.EarlyData = earlyData
state.Extra = extra
if c.config.WrapSession != nil {
var err error
m.label, err = c.config.WrapSession(c.connectionStateLocked(), state)
if err != nil {
return err
@ -881,11 +906,10 @@ func (c *Conn) sendSessionTicket(earlyData bool) error {
// The value is not stored anywhere; we never need to check the ticket age
// because 0-RTT is not supported.
ageAdd := make([]byte, 4)
_, err = c.config.rand().Read(ageAdd)
if err != nil {
if _, err := c.config.rand().Read(ageAdd); err != nil {
return err
}
m.ageAdd = binary.LittleEndian.Uint32(ageAdd)
m.ageAdd = byteorder.LeUint32(ageAdd)
if earlyData {
// RFC 9001, Section 4.6.1