Add assertions on the initial record version number.

The record-layer version of the ServerHello should match the final version. The
record-layer version of the ClientHello should be the advertised version, but
clamped at TLS 1.0. This is to ensure future rewrites do not regress this.

Change-Id: I96f1f0674944997ff38b562453a322ce61652635
Reviewed-on: https://boringssl-review.googlesource.com/2540
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 90c5294..4dd710c 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -586,6 +586,10 @@
 	// RequireFastradioPadding, if true, requires that ClientHello messages
 	// be at least 1000 bytes long.
 	RequireFastradioPadding bool
+
+	// ExpectInitialRecordVersion, if non-zero, is the expected
+	// version of the records before the version is determined.
+	ExpectInitialRecordVersion uint16
 }
 
 func (c *Config) serverInit() {
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 177e458..1c64c6a 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -625,9 +625,16 @@
 
 	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
 	n := int(b.data[3])<<8 | int(b.data[4])
-	if c.haveVers && vers != c.vers {
-		c.sendAlert(alertProtocolVersion)
-		return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+	if c.haveVers {
+		if vers != c.vers {
+			c.sendAlert(alertProtocolVersion)
+			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+		}
+	} else {
+		if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
+			c.sendAlert(alertProtocolVersion)
+			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, expect))
+		}
 	}
 	if n > maxCiphertext {
 		c.sendAlert(alertRecordOverflow)
diff --git a/ssl/test/runner/dtls.go b/ssl/test/runner/dtls.go
index 9c48b19..e7c5041 100644
--- a/ssl/test/runner/dtls.go
+++ b/ssl/test/runner/dtls.go
@@ -66,9 +66,16 @@
 	}
 	typ := recordType(b.data[0])
 	vers := wireToVersion(uint16(b.data[1])<<8|uint16(b.data[2]), c.isDTLS)
-	if c.haveVers && vers != c.vers {
-		c.sendAlert(alertProtocolVersion)
-		return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers))
+	if c.haveVers {
+		if vers != c.vers {
+			c.sendAlert(alertProtocolVersion)
+			return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers))
+		}
+	} else {
+		if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
+			c.sendAlert(alertProtocolVersion)
+			return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect))
+		}
 	}
 	seq := b.data[3:11]
 	// For test purposes, we assume a reliable channel. Require
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index ecf80db..5fed62b 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1632,12 +1632,19 @@
 					suffix += "-DTLS"
 				}
 
+				clientVers := shimVers.version
+				if clientVers > VersionTLS10 {
+					clientVers = VersionTLS10
+				}
 				testCases = append(testCases, testCase{
 					protocol: protocol,
 					testType: clientTest,
 					name:     "VersionNegotiation-Client-" + suffix,
 					config: Config{
 						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							ExpectInitialRecordVersion: clientVers,
+						},
 					},
 					flags:           flags,
 					expectedVersion: expectedVersion,
@@ -1649,6 +1656,9 @@
 					name:     "VersionNegotiation-Server-" + suffix,
 					config: Config{
 						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							ExpectInitialRecordVersion: expectedVersion,
+						},
 					},
 					flags:           flags,
 					expectedVersion: expectedVersion,
@@ -2157,25 +2167,25 @@
 }
 
 func addFastRadioPaddingTests() {
-	testCases = append(testCases, testCase {
-		protocol:	tls,
-		name:		"FastRadio-Padding",
+	testCases = append(testCases, testCase{
+		protocol: tls,
+		name:     "FastRadio-Padding",
 		config: Config{
 			Bugs: ProtocolBugs{
 				RequireFastradioPadding: true,
 			},
 		},
-		flags:		[]string{"-fastradio-padding"},
+		flags: []string{"-fastradio-padding"},
 	})
-	testCases = append(testCases, testCase {
-		protocol:	dtls,
-		name:		"FastRadio-Padding",
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "FastRadio-Padding",
 		config: Config{
 			Bugs: ProtocolBugs{
 				RequireFastradioPadding: true,
 			},
 		},
-		flags:		[]string{"-fastradio-padding"},
+		flags: []string{"-fastradio-padding"},
 	})
 }