mirror of
https://github.com/XTLS/REALITY.git
synced 2025-08-22 14:38:35 +00:00
crypto/tls: clarify group selection logic
I initially thought the logic was broken, but writing the test I realized it was actually very clever (derogative). It was relying on the outer loop continuing after a supported match without a key share, allowing a later key share to override it (but not a later supported match because of the "if selectedGroup != 0 { continue }"). Replaced the clever loop with two hopefully more understandable loops, and added a test (which was already passing). We were however not checking that the selected group is in the supported list if we found it in key shares first. (This was only a MAY.) Fixed. Fixes #65686 Change-Id: I09ea44f90167ffa36809deb78255ed039a217b6d Reviewed-on: https://go-review.googlesource.com/c/go/+/586655 Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
parent
194e5a43dc
commit
8be2b3051b
@ -298,6 +298,9 @@ type ConnectionState struct {
|
|||||||
|
|
||||||
// ekm is a closure exposed via ExportKeyingMaterial.
|
// ekm is a closure exposed via ExportKeyingMaterial.
|
||||||
ekm func(label string, context []byte, length int) ([]byte, error)
|
ekm func(label string, context []byte, length int) ([]byte, error)
|
||||||
|
|
||||||
|
// testingOnlyDidHRR is true if a HelloRetryRequest was sent/received.
|
||||||
|
testingOnlyDidHRR bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportKeyingMaterial returns length bytes of exported key material in a new
|
// ExportKeyingMaterial returns length bytes of exported key material in a new
|
||||||
|
2
conn.go
2
conn.go
@ -52,6 +52,7 @@ type Conn struct {
|
|||||||
handshakes int
|
handshakes int
|
||||||
extMasterSecret bool
|
extMasterSecret bool
|
||||||
didResume bool // whether this connection was a session resumption
|
didResume bool // whether this connection was a session resumption
|
||||||
|
didHRR bool // whether a HelloRetryRequest was sent/received
|
||||||
cipherSuite uint16
|
cipherSuite uint16
|
||||||
ocspResponse []byte // stapled OCSP response
|
ocspResponse []byte // stapled OCSP response
|
||||||
scts [][]byte // signed certificate timestamps from server
|
scts [][]byte // signed certificate timestamps from server
|
||||||
@ -1669,6 +1670,7 @@ func (c *Conn) connectionStateLocked() ConnectionState {
|
|||||||
state.Version = c.vers
|
state.Version = c.vers
|
||||||
state.NegotiatedProtocol = c.clientProtocol
|
state.NegotiatedProtocol = c.clientProtocol
|
||||||
state.DidResume = c.didResume
|
state.DidResume = c.didResume
|
||||||
|
state.testingOnlyDidHRR = c.didHRR
|
||||||
state.NegotiatedProtocolIsMutual = true
|
state.NegotiatedProtocolIsMutual = true
|
||||||
state.ServerName = c.serverName
|
state.ServerName = c.serverName
|
||||||
state.CipherSuite = c.cipherSuite
|
state.CipherSuite = c.cipherSuite
|
||||||
|
@ -307,6 +307,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.didHRR = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -233,21 +234,25 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
|
|||||||
// groups with a key share, to avoid a HelloRetryRequest round-trip.
|
// groups with a key share, to avoid a HelloRetryRequest round-trip.
|
||||||
var selectedGroup CurveID
|
var selectedGroup CurveID
|
||||||
var clientKeyShare *keyShare
|
var clientKeyShare *keyShare
|
||||||
GroupSelection:
|
preferredGroups := c.config.curvePreferences()
|
||||||
for _, preferredGroup := range c.config.curvePreferences() {
|
for _, preferredGroup := range preferredGroups {
|
||||||
for _, ks := range hs.clientHello.keyShares {
|
ki := slices.IndexFunc(hs.clientHello.keyShares, func(ks keyShare) bool {
|
||||||
if ks.group == preferredGroup {
|
return ks.group == preferredGroup
|
||||||
selectedGroup = ks.group
|
})
|
||||||
clientKeyShare = &ks
|
if ki != -1 {
|
||||||
break GroupSelection
|
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 {
|
if selectedGroup == 0 {
|
||||||
continue
|
for _, preferredGroup := range preferredGroups {
|
||||||
}
|
if slices.Contains(hs.clientHello.supportedCurves, preferredGroup) {
|
||||||
for _, group := range hs.clientHello.supportedCurves {
|
selectedGroup = preferredGroup
|
||||||
if group == preferredGroup {
|
|
||||||
selectedGroup = group
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,6 +589,7 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID)
|
|||||||
return errors.New("tls: client illegally modified second ClientHello")
|
return errors.New("tls: client illegally modified second ClientHello")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.didHRR = true
|
||||||
hs.clientHello = clientHello
|
hs.clientHello = clientHello
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user