Add a basic MTU test.

The minimum MTU (not consistently enforced) is just under 256, so it's
difficult to test everything, but this is a basic test. (E.g., without renego,
the only handshake message with encryption is Finished which fits in the MTU.)
It tests the server side because the Certificate message is large enough to
require fragmentation.

Change-Id: Ida11f1057cebae2b800ad13696f98bb3a7fbbc5e
Reviewed-on: https://boringssl-review.googlesource.com/2824
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 6266ad1..4fee8dc 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -436,6 +436,10 @@
   if (config->max_version != 0) {
     SSL_set_max_version(ssl, (uint16_t)config->max_version);
   }
+  if (config->mtu != 0) {
+    SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU);
+    SSL_set_mtu(ssl, config->mtu);
+  }
 
   BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
   if (bio == NULL) {
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 4dd710c..443d464 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -590,6 +590,10 @@
 	// ExpectInitialRecordVersion, if non-zero, is the expected
 	// version of the records before the version is determined.
 	ExpectInitialRecordVersion uint16
+
+	// MaxPacketLength, if non-zero, is the maximum acceptable size for a
+	// packet.
+	MaxPacketLength int
 }
 
 func (c *Config) serverInit() {
diff --git a/ssl/test/runner/dtls.go b/ssl/test/runner/dtls.go
index e7c5041..2e1fb65 100644
--- a/ssl/test/runner/dtls.go
+++ b/ssl/test/runner/dtls.go
@@ -53,6 +53,9 @@
 		if err != nil {
 			return 0, nil, err
 		}
+		if c.config.Bugs.MaxPacketLength != 0 && n > c.config.Bugs.MaxPacketLength {
+			return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length")
+		}
 		c.rawInput.resize(n)
 	}
 
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 6faccb5..d76bdf7 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -564,6 +564,30 @@
 		shouldFail:    true,
 		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
 	},
+	{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "MTU",
+		config: Config{
+			Bugs: ProtocolBugs{
+				MaxPacketLength: 256,
+			},
+		},
+		flags: []string{"-mtu", "256"},
+	},
+	{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "MTUExceeded",
+		config: Config{
+			Bugs: ProtocolBugs{
+				MaxPacketLength: 255,
+			},
+		},
+		flags:              []string{"-mtu", "256"},
+		shouldFail:         true,
+		expectedLocalError: "dtls: exceeded maximum packet length",
+	},
 }
 
 func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index a678a69..c032d96 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -104,6 +104,7 @@
 const Flag<int> kIntFlags[] = {
   { "-min-version", &TestConfig::min_version },
   { "-max-version", &TestConfig::max_version },
+  { "-mtu", &TestConfig::mtu },
 };
 
 }  // namespace
@@ -134,7 +135,8 @@
       enable_signed_cert_timestamps(false),
       fastradio_padding(false),
       min_version(0),
-      max_version(0) {
+      max_version(0),
+      mtu(0) {
 }
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index c7fd136..ba54227 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -66,6 +66,7 @@
   bool fastradio_padding;
   int min_version;
   int max_version;
+  int mtu;
 };
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);