diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go index d69f09f6..6c1dfcdc 100644 --- a/ssl/test/runner/common.go +++ b/ssl/test/runner/common.go @@ -393,10 +393,15 @@ type ProtocolBugs struct { SendFallbackSCSV bool // MaxHandshakeRecordLength, if non-zero, is the maximum size of a - // handshake record. Handshake messages will be split at the record - // layer. + // handshake record. Handshake messages will be split into multiple + // records at the specified size, except that the client_version will + // never be fragmented. MaxHandshakeRecordLength int + // FragmentClientVersion will allow MaxHandshakeRecordLength to apply to + // the first 6 bytes of the ClientHello. + FragmentClientVersion bool + // RsaClientKeyExchangeVersion, if non-zero, causes the client to send a // ClientKeyExchange with the specified version rather than the // client_version when performing the RSA key exchange. diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go index 52582ad8..f3e24957 100644 --- a/ssl/test/runner/conn.go +++ b/ssl/test/runner/conn.go @@ -714,6 +714,8 @@ func (c *Conn) writeV2Record(data []byte) (n int, err error) { // c.out.Mutex <= L. func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { b := c.out.newBlock() + first := true + isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello for len(data) > 0 { m := len(data) if m > maxPlaintext { @@ -721,9 +723,16 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { } if typ == recordTypeHandshake && c.config.Bugs.MaxHandshakeRecordLength > 0 && m > c.config.Bugs.MaxHandshakeRecordLength { m = c.config.Bugs.MaxHandshakeRecordLength + // By default, do not fragment the client_version or + // server_version, which are located in the first 6 + // bytes. + if first && isClientHello && !c.config.Bugs.FragmentClientVersion && m < 6 { + m = 6 + } } explicitIVLen := 0 explicitIVIsSeq := false + first = false var cbc cbcMode if c.out.version >= VersionTLS11 { diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 701de81d..36276be8 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -383,6 +383,18 @@ var testCases = []testCase{ }, }, }, + { + testType: serverTest, + name: "FragmentedClientVersion", + config: Config{ + Bugs: ProtocolBugs{ + MaxHandshakeRecordLength: 1, + FragmentClientVersion: true, + }, + }, + shouldFail: true, + expectedError: ":RECORD_TOO_SMALL:", + }, } func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) error { @@ -863,7 +875,7 @@ func addStateMachineCoverageTests(async bool, splitHandshake bool) { } if splitHandshake { suffix += "-SplitHandshakeRecords" - maxHandshakeRecordLength = 10 + maxHandshakeRecordLength = 1 } // Basic handshake, with resumption. Client and server.