Add experimental TLS 1.3 short record header extension.
This extension will be used to test whether
https://github.com/tlswg/tls13-spec/pull/762 is deployable against
middleboxes. For simplicity, it is mutually exclusive with 0-RTT. If
client and server agree on the extension, TLS 1.3 records will use the
format in the PR rather than what is in draft 18.
BUG=119
Change-Id: I1372ddf7b328ddf73d496df54ac03a95ede961e1
Reviewed-on: https://boringssl-review.googlesource.com/12684
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>
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 80a5b06..510bcf7 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -163,6 +163,8 @@
trafficSecret []byte
+ shortHeader bool
+
config *Config
}
@@ -301,10 +303,17 @@
copy(hc.outSeq[:], hc.seq[:])
}
+func (hc *halfConn) isShortHeader() bool {
+ return hc.shortHeader && hc.cipher != nil
+}
+
func (hc *halfConn) recordHeaderLen() int {
if hc.isDTLS {
return dtlsRecordHeaderLen
}
+ if hc.isShortHeader() {
+ return 2
+ }
return tlsRecordHeaderLen
}
@@ -608,6 +617,9 @@
n := len(b.data) - recordHeaderLen
b.data[recordHeaderLen-2] = byte(n >> 8)
b.data[recordHeaderLen-1] = byte(n)
+ if hc.isShortHeader() && !hc.config.Bugs.ClearShortHeaderBit {
+ b.data[0] |= 0x80
+ }
hc.incSeq(true)
return true, 0
@@ -716,7 +728,7 @@
return c.dtlsDoReadRecord(want)
}
- recordHeaderLen := tlsRecordHeaderLen
+ recordHeaderLen := c.in.recordHeaderLen()
if c.rawInput == nil {
c.rawInput = c.in.newBlock()
@@ -736,19 +748,36 @@
}
return 0, nil, err
}
- typ := recordType(b.data[0])
- // No valid TLS record has a type of 0x80, however SSLv2 handshakes
- // start with a uint16 length where the MSB is set and the first record
- // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
- // an SSLv2 client.
- if want == recordTypeHandshake && typ == 0x80 {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+ var typ recordType
+ var vers uint16
+ var n int
+ if c.in.isShortHeader() {
+ typ = recordTypeApplicationData
+ vers = VersionTLS10
+ n = int(b.data[0])<<8 | int(b.data[1])
+ if n&0x8000 == 0 {
+ c.sendAlert(alertDecodeError)
+ return 0, nil, c.in.setErrorLocked(errors.New("tls: length did not have high bit set"))
+ }
+
+ n = n & 0x7fff
+ } else {
+ typ = recordType(b.data[0])
+
+ // No valid TLS record has a type of 0x80, however SSLv2 handshakes
+ // start with a uint16 length where the MSB is set and the first record
+ // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+ // an SSLv2 client.
+ if want == recordTypeHandshake && typ == 0x80 {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+ }
+
+ vers = uint16(b.data[1])<<8 | uint16(b.data[2])
+ n = int(b.data[3])<<8 | int(b.data[4])
}
- vers := uint16(b.data[1])<<8 | uint16(b.data[2])
- n := int(b.data[3])<<8 | int(b.data[4])
// 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.)
@@ -1007,7 +1036,7 @@
}
func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) {
- recordHeaderLen := tlsRecordHeaderLen
+ recordHeaderLen := c.out.recordHeaderLen()
b := c.out.newBlock()
first := true
isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
@@ -1049,32 +1078,36 @@
}
}
b.resize(recordHeaderLen + explicitIVLen + m)
- b.data[0] = byte(typ)
- if c.vers >= VersionTLS13 && c.out.cipher != nil {
- b.data[0] = byte(recordTypeApplicationData)
- if outerType := c.config.Bugs.OuterRecordType; outerType != 0 {
- b.data[0] = byte(outerType)
+ // If using a short record header, the length will be filled in
+ // by encrypt.
+ if !c.out.isShortHeader() {
+ b.data[0] = byte(typ)
+ if c.vers >= VersionTLS13 && c.out.cipher != nil {
+ b.data[0] = byte(recordTypeApplicationData)
+ if outerType := c.config.Bugs.OuterRecordType; outerType != 0 {
+ b.data[0] = byte(outerType)
+ }
}
+ vers := c.vers
+ if vers == 0 || vers >= VersionTLS13 {
+ // Some TLS servers fail if the record version is
+ // greater than TLS 1.0 for the initial ClientHello.
+ //
+ // TLS 1.3 fixes the version number in the record
+ // layer to {3, 1}.
+ vers = VersionTLS10
+ }
+ if c.config.Bugs.SendRecordVersion != 0 {
+ vers = c.config.Bugs.SendRecordVersion
+ }
+ if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 {
+ vers = c.config.Bugs.SendInitialRecordVersion
+ }
+ b.data[1] = byte(vers >> 8)
+ b.data[2] = byte(vers)
+ b.data[3] = byte(m >> 8)
+ b.data[4] = byte(m)
}
- vers := c.vers
- if vers == 0 || vers >= VersionTLS13 {
- // Some TLS servers fail if the record version is
- // greater than TLS 1.0 for the initial ClientHello.
- //
- // TLS 1.3 fixes the version number in the record
- // layer to {3, 1}.
- vers = VersionTLS10
- }
- if c.config.Bugs.SendRecordVersion != 0 {
- vers = c.config.Bugs.SendRecordVersion
- }
- if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 {
- vers = c.config.Bugs.SendInitialRecordVersion
- }
- b.data[1] = byte(vers >> 8)
- b.data[2] = byte(vers)
- b.data[3] = byte(m >> 8)
- b.data[4] = byte(m)
if explicitIVLen > 0 {
explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
if explicitIVIsSeq {
@@ -1620,6 +1653,7 @@
state.SCTList = c.sctList
state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
state.CurveID = c.curveID
+ state.ShortHeader = c.in.shortHeader
}
return state
@@ -1781,3 +1815,8 @@
_, err := c.conn.Write(payload)
return err
}
+
+func (c *Conn) setShortHeader() {
+ c.in.shortHeader = true
+ c.out.shortHeader = true
+}