Test application data and Finished reordering.

This is fatal for TLS but buffered in DTLS. The buffering isn't strictly
necessary (it would be just as valid to drop the record on the floor), but so
long as we want this behavior it should have a test.

Change-Id: I5846bb2fe80d78e25b6dfad51bcfcff2dc427c3f
Reviewed-on: https://boringssl-review.googlesource.com/3029
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 774c7a3..7aaf9a2 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -599,6 +599,10 @@
 	// server will send in the ServerHello. This does not affect the cipher
 	// the server believes it has actually negotiated.
 	SendCipherSuite uint16
+
+	// AppDataAfterChangeCipherSpec, if not null, causes application data to
+	// be sent immediately after ChangeCipherSpec.
+	AppDataAfterChangeCipherSpec []byte
 }
 
 func (c *Config) serverInit() {
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 25fd7a8..f297fc1 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -840,6 +840,10 @@
 		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 	}
 
+	if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
+		c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
+	}
+
 	c.writeRecord(recordTypeHandshake, postCCSBytes)
 	return nil
 }
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index f811fb2..b61292e 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -819,6 +819,10 @@
 		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 	}
 
+	if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
+		c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
+	}
+
 	c.writeRecord(recordTypeHandshake, postCCSBytes)
 
 	c.cipherSuite = hs.suite.id
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index e298725..137a87c 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -632,6 +632,25 @@
 		damageFirstWrite: true,
 		flags:            []string{"-async"},
 	},
+	{
+		name: "AppDataAfterChangeCipherSpec",
+		config: Config{
+			Bugs: ProtocolBugs{
+				AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
+	},
+	{
+		protocol: dtls,
+		name:     "AppDataAfterChangeCipherSpec-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+			},
+		},
+	},
 }
 
 func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
@@ -759,14 +778,21 @@
 		return err
 	}
 
-	if messageLen == 0 {
-		messageLen = 32
+	var testMessage []byte
+	if config.Bugs.AppDataAfterChangeCipherSpec != nil {
+		// We've already sent a message. Expect the shim to echo it
+		// back.
+		testMessage = config.Bugs.AppDataAfterChangeCipherSpec
+	} else {
+		if messageLen == 0 {
+			messageLen = 32
+		}
+		testMessage = make([]byte, messageLen)
+		for i := range testMessage {
+			testMessage[i] = 0x42
+		}
+		tlsConn.Write(testMessage)
 	}
-	testMessage := make([]byte, messageLen)
-	for i := range testMessage {
-		testMessage[i] = 0x42
-	}
-	tlsConn.Write(testMessage)
 
 	buf := make([]byte, len(testMessage))
 	if test.protocol == dtls {