This mirror's 2dc0204603
on the C side.
BUG=90
Change-Id: Iebb72df5a5ae98cb2fd8db519d973cd734ff05ea
Reviewed-on: https://boringssl-review.googlesource.com/11320
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
kris/onging/CECPQ3_patch15
@@ -736,8 +736,8 @@ type ProtocolBugs struct { | |||
// across a renego. | |||
RequireSameRenegoClientVersion bool | |||
// ExpectInitialRecordVersion, if non-zero, is the expected | |||
// version of the records before the version is determined. | |||
// ExpectInitialRecordVersion, if non-zero, is the expected value of | |||
// record-layer version field before the version is determined. | |||
ExpectInitialRecordVersion uint16 | |||
// MaxPacketLength, if non-zero, is the maximum acceptable size for a | |||
@@ -25,16 +25,38 @@ import ( | |||
func versionToWire(vers uint16, isDTLS bool) uint16 { | |||
if isDTLS { | |||
return ^(vers - 0x0201) | |||
switch vers { | |||
case VersionTLS12: | |||
return 0xfefd | |||
case VersionTLS10: | |||
return 0xfeff | |||
} | |||
} else { | |||
switch vers { | |||
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13: | |||
return vers | |||
} | |||
} | |||
return vers | |||
panic("unknown version") | |||
} | |||
func wireToVersion(vers uint16, isDTLS bool) uint16 { | |||
func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) { | |||
if isDTLS { | |||
return ^vers + 0x0201 | |||
switch vers { | |||
case 0xfefd: | |||
return VersionTLS12, true | |||
case 0xfeff: | |||
return VersionTLS10, true | |||
} | |||
} else { | |||
switch vers { | |||
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13: | |||
return vers, true | |||
} | |||
} | |||
return vers | |||
return 0, false | |||
} | |||
func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) { | |||
@@ -70,15 +92,15 @@ func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) { | |||
return 0, nil, errors.New("dtls: failed to read record header") | |||
} | |||
typ := recordType(b.data[0]) | |||
vers := wireToVersion(uint16(b.data[1])<<8|uint16(b.data[2]), c.isDTLS) | |||
vers := uint16(b.data[1])<<8 | uint16(b.data[2]) | |||
// Alerts sent near version negotiation do not have a well-defined | |||
// record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer | |||
// version is irrelevant.) | |||
if typ != recordTypeAlert { | |||
if c.haveVers { | |||
if vers != c.vers { | |||
if wireVers := versionToWire(c.vers, c.isDTLS); vers != wireVers { | |||
c.sendAlert(alertProtocolVersion) | |||
return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers)) | |||
return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, wireVers)) | |||
} | |||
} else { | |||
// Pre-version-negotiation alerts may be sent with any version. | |||
@@ -364,8 +364,10 @@ NextCipherSuite: | |||
return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg) | |||
} | |||
var ok bool | |||
c.vers, ok = c.config.mutualVersion(wireToVersion(serverWireVersion, c.isDTLS), c.isDTLS) | |||
serverVersion, ok := wireToVersion(serverWireVersion, c.isDTLS) | |||
if ok { | |||
c.vers, ok = c.config.mutualVersion(serverVersion, c.isDTLS) | |||
} | |||
if !ok { | |||
c.sendAlert(alertProtocolVersion) | |||
return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers) | |||
@@ -719,6 +719,7 @@ type serverHelloMsg struct { | |||
raw []byte | |||
isDTLS bool | |||
vers uint16 | |||
versOverride uint16 | |||
random []byte | |||
sessionId []byte | |||
cipherSuite uint16 | |||
@@ -739,8 +740,20 @@ func (m *serverHelloMsg) marshal() []byte { | |||
handshakeMsg := newByteBuilder() | |||
handshakeMsg.addU8(typeServerHello) | |||
hello := handshakeMsg.addU24LengthPrefixed() | |||
vers := wireToVersion(m.vers, m.isDTLS) | |||
hello.addU16(m.vers) | |||
// m.vers is used both to determine the format of the rest of the | |||
// ServerHello and to override the value, so include a second version | |||
// field. | |||
vers, ok := wireToVersion(m.vers, m.isDTLS) | |||
if !ok { | |||
panic("unknown version") | |||
} | |||
if m.versOverride != 0 { | |||
hello.addU16(m.versOverride) | |||
} else { | |||
hello.addU16(m.vers) | |||
} | |||
hello.addBytes(m.random) | |||
if vers < VersionTLS13 { | |||
sessionId := hello.addU8LengthPrefixed() | |||
@@ -787,7 +800,10 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { | |||
} | |||
m.raw = data | |||
m.vers = uint16(data[4])<<8 | uint16(data[5]) | |||
vers := wireToVersion(m.vers, m.isDTLS) | |||
vers, ok := wireToVersion(m.vers, m.isDTLS) | |||
if !ok { | |||
return false | |||
} | |||
m.random = data[6:38] | |||
data = data[38:] | |||
if vers < VersionTLS13 { | |||
@@ -205,7 +205,39 @@ func (hs *serverHandshakeState) readClientHello() error { | |||
} | |||
} | |||
c.clientVersion = hs.clientHello.vers | |||
clientVersion := wireToVersion(c.clientVersion, c.isDTLS) | |||
var clientVersion uint16 | |||
if c.isDTLS { | |||
if hs.clientHello.vers <= 0xfefd { | |||
clientVersion = VersionTLS12 | |||
} else if hs.clientHello.vers <= 0xfeff { | |||
clientVersion = VersionTLS10 | |||
} | |||
} else { | |||
if hs.clientHello.vers >= VersionTLS13 { | |||
clientVersion = VersionTLS13 | |||
} else if hs.clientHello.vers >= VersionTLS12 { | |||
clientVersion = VersionTLS12 | |||
} else if hs.clientHello.vers >= VersionTLS11 { | |||
clientVersion = VersionTLS11 | |||
} else if hs.clientHello.vers >= VersionTLS10 { | |||
clientVersion = VersionTLS10 | |||
} else if hs.clientHello.vers >= VersionSSL30 { | |||
clientVersion = VersionSSL30 | |||
} | |||
} | |||
if config.Bugs.NegotiateVersion != 0 { | |||
c.vers = config.Bugs.NegotiateVersion | |||
} else if c.haveVers && config.Bugs.NegotiateVersionOnRenego != 0 { | |||
c.vers = config.Bugs.NegotiateVersionOnRenego | |||
} else { | |||
c.vers, ok = config.mutualVersion(clientVersion, c.isDTLS) | |||
if !ok { | |||
c.sendAlert(alertProtocolVersion) | |||
return fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) | |||
} | |||
} | |||
c.haveVers = true | |||
// Reject < 1.2 ClientHellos with signature_algorithms. | |||
if clientVersion < VersionTLS12 && len(hs.clientHello.signatureAlgorithms) > 0 { | |||
@@ -234,19 +266,6 @@ func (hs *serverHandshakeState) readClientHello() error { | |||
return fmt.Errorf("tls: client offered unexpected PSK identities") | |||
} | |||
if config.Bugs.NegotiateVersion != 0 { | |||
c.vers = config.Bugs.NegotiateVersion | |||
} else if c.haveVers && config.Bugs.NegotiateVersionOnRenego != 0 { | |||
c.vers = config.Bugs.NegotiateVersionOnRenego | |||
} else { | |||
c.vers, ok = config.mutualVersion(clientVersion, c.isDTLS) | |||
if !ok { | |||
c.sendAlert(alertProtocolVersion) | |||
return fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", clientVersion) | |||
} | |||
} | |||
c.haveVers = true | |||
var scsvFound, greaseFound bool | |||
for _, cipherSuite := range hs.clientHello.cipherSuites { | |||
if cipherSuite == fallbackSCSV { | |||
@@ -311,12 +330,9 @@ func (hs *serverHandshakeState) doTLS13Handshake() error { | |||
config := c.config | |||
hs.hello = &serverHelloMsg{ | |||
isDTLS: c.isDTLS, | |||
vers: versionToWire(c.vers, c.isDTLS), | |||
} | |||
if config.Bugs.SendServerHelloVersion != 0 { | |||
hs.hello.vers = config.Bugs.SendServerHelloVersion | |||
isDTLS: c.isDTLS, | |||
vers: versionToWire(c.vers, c.isDTLS), | |||
versOverride: config.Bugs.SendServerHelloVersion, | |||
} | |||
hs.hello.random = make([]byte, 32) | |||
@@ -818,13 +834,10 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) | |||
hs.hello = &serverHelloMsg{ | |||
isDTLS: c.isDTLS, | |||
vers: versionToWire(c.vers, c.isDTLS), | |||
versOverride: config.Bugs.SendServerHelloVersion, | |||
compressionMethod: compressionNone, | |||
} | |||
if config.Bugs.SendServerHelloVersion != 0 { | |||
hs.hello.vers = config.Bugs.SendServerHelloVersion | |||
} | |||
hs.hello.random = make([]byte, 32) | |||
_, err = io.ReadFull(config.rand(), hs.hello.random) | |||
if err != nil { | |||
@@ -4102,14 +4102,18 @@ func addVersionNegotiationTests() { | |||
shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls))) | |||
// Determine the expected initial record-layer versions. | |||
clientVers := shimVers.version | |||
if clientVers > VersionTLS10 { | |||
clientVers = VersionTLS10 | |||
} | |||
clientVers = versionToWire(clientVers, protocol == dtls) | |||
serverVers := expectedVersion | |||
if expectedVersion >= VersionTLS13 { | |||
serverVers = VersionTLS10 | |||
} | |||
serverVers = versionToWire(serverVers, protocol == dtls) | |||
testCases = append(testCases, testCase{ | |||
protocol: protocol, | |||
testType: clientTest, | |||