Add DTLS replay tests.

At the record layer, DTLS maintains a window of seen sequence numbers to detect
replays. Add tests to cover that case. Test both repeated sequence numbers
within the window and sequence numbers past the window's left edge. Also test
receiving sequence numbers far past the window's right edge.

Change-Id: If6a7a24869db37fdd8fb3c4b3521b730e31f8f86
Reviewed-on: https://boringssl-review.googlesource.com/2221
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 4b43481..44e15d1 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -156,6 +156,9 @@
 	// renegotiateCiphers is a list of ciphersuite ids that will be
 	// switched in just before renegotiation.
 	renegotiateCiphers []uint16
+	// replayWrites, if true, configures the underlying transport
+	// to replay every write it makes in DTLS tests.
+	replayWrites bool
 	// flags, if not empty, contains a list of command-line flags that will
 	// be passed to the shim program.
 	flags []string
@@ -497,6 +500,9 @@
 func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
 	if test.protocol == dtls {
 		conn = newPacketAdaptor(conn)
+		if test.replayWrites {
+			conn = newReplayAdaptor(conn)
+		}
 	}
 
 	if test.sendPrefix != "" {
@@ -1854,6 +1860,28 @@
 	})
 }
 
+func addDTLSReplayTests() {
+	// Test that sequence number replays are detected.
+	testCases = append(testCases, testCase{
+		protocol:     dtls,
+		name:         "DTLS-Replay",
+		replayWrites: true,
+	})
+
+	// Test the outgoing sequence number skipping by values larger
+	// than the retransmit window.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "DTLS-Replay-LargeGaps",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SequenceNumberIncrement: 127,
+			},
+		},
+		replayWrites: true,
+	})
+}
+
 func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
 	defer wg.Done()
 
@@ -1911,6 +1939,7 @@
 	addResumptionVersionTests()
 	addExtendedMasterSecretTests()
 	addRenegotiationTests()
+	addDTLSReplayTests()
 	for _, async := range []bool{false, true} {
 		for _, splitHandshake := range []bool{false, true} {
 			for _, protocol := range []protocol{tls, dtls} {