Add TLS 1.3 record layer to go implementation.

This implements the cipher suite constraints in "fake TLS 1.3". It also makes
bssl_shim and runner enable it by default so we can start adding MaxVersion:
VersionTLS12 markers to tests as 1.2 vs. 1.3 differences begin to take effect.

Change-Id: If1caf6e43938c8d15b0a0f39f40963b8199dcef5
Reviewed-on: https://boringssl-review.googlesource.com/8340
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 5d21486..fd58e2d 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1111,6 +1111,10 @@
  * for |cipher|. */
 OPENSSL_EXPORT uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher);
 
+/* SSL_CIPHER_get_max_version returns the maximum protocol version that
+ * supports |cipher|. */
+OPENSSL_EXPORT uint16_t SSL_CIPHER_get_max_version(const SSL_CIPHER *cipher);
+
 /* SSL_CIPHER_get_name returns the OpenSSL name of |cipher|. */
 OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
 
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index 9b96bcd..2d49200 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -591,6 +591,8 @@
         (cipher->algorithm_auth & ssl->cert->mask_a)) {
       continue;
     }
+    /* TODO(davidben): Also check |SSL_CIPHER_get_max_version| against the
+     * minimum enabled version. See https://crbug.com/boringssl/66. */
     if (SSL_CIPHER_get_min_version(cipher) >
         ssl3_version_from_wire(ssl, ssl->client_version)) {
       continue;
@@ -864,7 +866,8 @@
   /* If the cipher is disabled then we didn't sent it in the ClientHello, so if
    * the server selected it, it's an error. */
   if ((c->algorithm_mkey & ct->mask_k) || (c->algorithm_auth & ct->mask_a) ||
-      SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl)) {
+      SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
+      SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
     al = SSL_AD_ILLEGAL_PARAMETER;
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
     goto f_err;
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 43dcb02..9dab142 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -293,7 +293,8 @@
     ok = 1;
 
     /* Check the TLS version. */
-    if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl)) {
+    if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
+        SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
       ok = 0;
     }
 
diff --git a/ssl/ssl_cipher.c b/ssl/ssl_cipher.c
index 539472d..3c4f325 100644
--- a/ssl/ssl_cipher.c
+++ b/ssl/ssl_cipher.c
@@ -1727,6 +1727,15 @@
   return SSL3_VERSION;
 }
 
+uint16_t SSL_CIPHER_get_max_version(const SSL_CIPHER *cipher) {
+  if (cipher->algorithm_mac == SSL_AEAD &&
+      (cipher->algorithm_enc & SSL_CHACHA20POLY1305_OLD) == 0 &&
+      (cipher->algorithm_mkey & SSL_kECDHE) != 0) {
+    return TLS1_3_VERSION;
+  }
+  return TLS1_2_VERSION;
+}
+
 /* return the actual cipher being used */
 const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher) {
   if (cipher != NULL) {
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index ef759d9..99a5b93 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -752,6 +752,11 @@
     return nullptr;
   }
 
+  if (!config->is_dtls) {
+    // Enable TLS 1.3 for tests.
+    SSL_CTX_set_max_version(ssl_ctx.get(), TLS1_3_VERSION);
+  }
+
   std::string cipher_list = "ALL";
   if (!config->cipher.empty()) {
     cipher_list = config->cipher;
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index 26f51b0..8c5be3d 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -52,8 +52,11 @@
 	// RSA based.
 	suiteECDSA
 	// suiteTLS12 indicates that the cipher suite should only be advertised
-	// and accepted when using TLS 1.2.
+	// and accepted when using TLS 1.2 or greater.
 	suiteTLS12
+	// suiteTLS13 indicates that the cipher suite can be used with TLS 1.3.
+	// Cipher suites lacking this flag may not be used with TLS 1.3.
+	suiteTLS13
 	// suiteSHA384 indicates that the cipher suite uses SHA384 as the
 	// handshake hash.
 	suiteSHA384
@@ -77,66 +80,89 @@
 	// the lengths, in bytes, of the key material needed for each component.
 	keyLen int
 	macLen int
-	ivLen  int
+	ivLen  func(version uint16) int
 	ka     func(version uint16) keyAgreement
 	// flags is a bitmask of the suite* values, above.
 	flags  int
 	cipher func(key, iv []byte, isRead bool) interface{}
 	mac    func(version uint16, macKey []byte) macFunction
-	aead   func(key, fixedNonce []byte) *tlsAead
+	aead   func(version uint16, key, fixedNonce []byte) *tlsAead
 }
 
 var cipherSuites = []*cipherSuite{
 	// Ciphersuite order is chosen so that ECDHE comes before plain RSA
 	// and RC4 comes before AES (because of the Lucky13 attack).
-	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
-	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, 0, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
-	{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
-	{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
-	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
-	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
-	{TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
-	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
-	{TLS_RSA_WITH_RC4_128_MD5, 16, 16, 0, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
-	{TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
-	{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
-	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
-	{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
-	{TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
-	{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
-	{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_NULL_SHA, 0, 20, 0, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteTLS13, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteTLS13, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, noIV, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
+	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, noIV, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
+	{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteTLS13, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteTLS13, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, noIV, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, noIV, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, ivLenAES, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, dheRSAKA, suiteTLS12 | suiteTLS13, nil, nil, aeadAESGCM},
+	{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, dheRSAKA, suiteTLS12 | suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, ivLenAES, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, dheRSAKA, 0, cipherAES, macSHA1, nil},
+	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, dheRSAKA, 0, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, noIV, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
+	{TLS_RSA_WITH_RC4_128_MD5, 16, 16, noIV, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
+	{TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, ivLenAES, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, rsaKA, 0, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, rsaKA, 0, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, ivLen3DES, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
+	{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, ivLen3DES, dheRSAKA, 0, cipher3DES, macSHA1, nil},
+	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, ivLen3DES, rsaKA, 0, cipher3DES, macSHA1, nil},
+	{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12 | suiteTLS13, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12 | suiteTLS13, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12 | suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
+	{TLS_PSK_WITH_RC4_128_SHA, 16, 20, noIV, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
+	{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil},
+	{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_NULL_SHA, 0, 20, noIV, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil},
+}
+
+func noIV(vers uint16) int {
+	return 0
+}
+
+func ivLenChaCha20Poly1305(vers uint16) int {
+	return 12
+}
+
+func ivLenAESGCM(vers uint16) int {
+	if vers >= VersionTLS13 {
+		return 12
+	}
+	return 4
+}
+
+func ivLenAES(vers uint16) int {
+	return 16
+}
+
+func ivLen3DES(vers uint16) int {
+	return 8
 }
 
 type nullCipher struct{}
@@ -243,7 +269,7 @@
 	return f.aead.Open(out, f.openNonce, plaintext, additionalData)
 }
 
-func aeadAESGCM(key, fixedNonce []byte) *tlsAead {
+func aeadAESGCM(version uint16, key, fixedNonce []byte) *tlsAead {
 	aes, err := aes.NewCipher(key)
 	if err != nil {
 		panic(err)
@@ -257,10 +283,14 @@
 	copy(nonce1, fixedNonce)
 	copy(nonce2, fixedNonce)
 
+	if version >= VersionTLS13 {
+		return &tlsAead{&xorNonceAEAD{nonce1, nonce2, aead}, false}
+	}
+
 	return &tlsAead{&fixedNonceAEAD{nonce1, nonce2, aead}, true}
 }
 
-func aeadCHACHA20POLY1305Old(key, fixedNonce []byte) *tlsAead {
+func aeadCHACHA20POLY1305Old(version uint16, key, fixedNonce []byte) *tlsAead {
 	aead, err := newChaCha20Poly1305Old(key)
 	if err != nil {
 		panic(err)
@@ -301,7 +331,7 @@
 	return ret, err
 }
 
-func aeadCHACHA20POLY1305(key, fixedNonce []byte) *tlsAead {
+func aeadCHACHA20POLY1305(version uint16, key, fixedNonce []byte) *tlsAead {
 	aead, err := newChaCha20Poly1305(key)
 	if err != nil {
 		panic(err)
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 6ff8bac..ae03850 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -23,6 +23,7 @@
 	VersionTLS10 = 0x0301
 	VersionTLS11 = 0x0302
 	VersionTLS12 = 0x0303
+	VersionTLS13 = 0x0304
 )
 
 const (
@@ -33,7 +34,7 @@
 	maxHandshake        = 65536 // maximum handshake we support (protocol max is 16 MB)
 
 	minVersion = VersionSSL30
-	maxVersion = VersionTLS12
+	maxVersion = VersionTLS13
 )
 
 // TLS record types.
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 3913995..3f406bb 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -345,8 +345,9 @@
 
 // decrypt checks and strips the mac and decrypts the data in b. Returns a
 // success boolean, the number of bytes to skip from the start of the record in
-// order to get the application payload, and an optional alert value.
-func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) {
+// order to get the application payload, the encrypted record type (or 0
+// if there is none), and an optional alert value.
+func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, contentType recordType, alertValue alert) {
 	recordHeaderLen := hc.recordHeaderLen()
 
 	// pull out payload
@@ -376,22 +377,37 @@
 			if c.explicitNonce {
 				explicitIVLen = 8
 				if len(payload) < explicitIVLen {
-					return false, 0, alertBadRecordMAC
+					return false, 0, 0, alertBadRecordMAC
 				}
 				nonce = payload[:8]
 				payload = payload[8:]
 			}
 
-			var additionalData [13]byte
-			copy(additionalData[:], seq)
-			copy(additionalData[8:], b.data[:3])
-			n := len(payload) - c.Overhead()
-			additionalData[11] = byte(n >> 8)
-			additionalData[12] = byte(n)
+			var additionalData []byte
+			if hc.version < VersionTLS13 {
+				additionalData = make([]byte, 13)
+				copy(additionalData, seq)
+				copy(additionalData[8:], b.data[:3])
+				n := len(payload) - c.Overhead()
+				additionalData[11] = byte(n >> 8)
+				additionalData[12] = byte(n)
+			}
 			var err error
-			payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+			payload, err = c.Open(payload[:0], nonce, payload, additionalData)
 			if err != nil {
-				return false, 0, alertBadRecordMAC
+				return false, 0, 0, alertBadRecordMAC
+			}
+			if hc.version >= VersionTLS13 {
+				i := len(payload)
+				for i > 0 && payload[i-1] == 0 {
+					i--
+				}
+				payload = payload[:i]
+				if len(payload) == 0 {
+					return false, 0, 0, alertUnexpectedMessage
+				}
+				contentType = recordType(payload[len(payload)-1])
+				payload = payload[:len(payload)-1]
 			}
 			b.resize(recordHeaderLen + explicitIVLen + len(payload))
 		case cbcMode:
@@ -401,7 +417,7 @@
 			}
 
 			if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
-				return false, 0, alertBadRecordMAC
+				return false, 0, 0, alertBadRecordMAC
 			}
 
 			if explicitIVLen > 0 {
@@ -436,7 +452,7 @@
 	// check, strip mac
 	if hc.mac != nil {
 		if len(payload) < macSize {
-			return false, 0, alertBadRecordMAC
+			return false, 0, 0, alertBadRecordMAC
 		}
 
 		// strip mac off payload, b.data
@@ -448,13 +464,13 @@
 		localMAC := hc.mac.MAC(hc.inDigestBuf, seq, b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], payload[:n])
 
 		if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
-			return false, 0, alertBadRecordMAC
+			return false, 0, 0, alertBadRecordMAC
 		}
 		hc.inDigestBuf = localMAC
 	}
 	hc.incSeq(false)
 
-	return true, recordHeaderLen + explicitIVLen, 0
+	return true, recordHeaderLen + explicitIVLen, contentType, 0
 }
 
 // padToBlockSize calculates the needed padding block, if any, for a payload.
@@ -486,7 +502,7 @@
 }
 
 // encrypt encrypts and macs the data in b.
-func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
+func (hc *halfConn) encrypt(b *block, explicitIVLen int, typ recordType) (bool, alert) {
 	recordHeaderLen := hc.recordHeaderLen()
 
 	// mac
@@ -507,8 +523,18 @@
 		case cipher.Stream:
 			c.XORKeyStream(payload, payload)
 		case *tlsAead:
+			contentTypeLen := 0
+			if hc.version >= VersionTLS13 {
+				contentTypeLen = 1
+			}
 			payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
-			b.resize(len(b.data) + c.Overhead())
+			b.resize(len(b.data) + contentTypeLen + c.Overhead())
+			if hc.version >= VersionTLS13 {
+				b.data[payloadLen+recordHeaderLen] = byte(typ)
+				payloadLen += 1
+				// TODO(nharper): Add ProtocolBugs to add
+				// padding.
+			}
 			nonce := hc.outSeq[:]
 			if c.explicitNonce {
 				nonce = b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
@@ -516,13 +542,16 @@
 			payload := b.data[recordHeaderLen+explicitIVLen:]
 			payload = payload[:payloadLen]
 
-			var additionalData [13]byte
-			copy(additionalData[:], hc.outSeq[:])
-			copy(additionalData[8:], b.data[:3])
-			additionalData[11] = byte(payloadLen >> 8)
-			additionalData[12] = byte(payloadLen)
+			var additionalData []byte
+			if hc.version < VersionTLS13 {
+				additionalData = make([]byte, 13)
+				copy(additionalData, hc.outSeq[:])
+				copy(additionalData[8:], b.data[:3])
+				additionalData[11] = byte(payloadLen >> 8)
+				additionalData[12] = byte(payloadLen)
+			}
 
-			c.Seal(payload[:0], nonce, payload, additionalData[:])
+			c.Seal(payload[:0], nonce, payload, additionalData)
 		case cbcMode:
 			blockSize := c.BlockSize()
 			if explicitIVLen > 0 {
@@ -686,7 +715,7 @@
 	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
 	n := int(b.data[3])<<8 | int(b.data[4])
 	if c.haveVers {
-		if vers != c.vers {
+		if vers != c.vers && c.vers < VersionTLS13 {
 			c.sendAlert(alertProtocolVersion)
 			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
 		}
@@ -726,7 +755,12 @@
 
 	// Process message.
 	b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
-	ok, off, err := c.in.decrypt(b)
+	ok, off, encTyp, err := c.in.decrypt(b)
+	if c.vers >= VersionTLS13 && c.in.cipher != nil {
+		// TODO(nharper): Check that outer type (typ) is
+		// application data.
+		typ = encTyp
+	}
 	if !ok {
 		c.in.setErrorLocked(c.sendAlert(err))
 	}
@@ -931,10 +965,17 @@
 		}
 		b.resize(recordHeaderLen + explicitIVLen + m)
 		b.data[0] = byte(typ)
+		if c.vers >= VersionTLS13 && c.out.cipher != nil {
+			// TODO(nharper): Add a ProtocolBugs to skip this.
+			b.data[0] = byte(recordTypeApplicationData)
+		}
 		vers := c.vers
-		if vers == 0 {
+		if vers == 0 || vers >= VersionTLS13 {
 			// Some TLS servers fail if the record version is
 			// greater than TLS 1.0 for the initial ClientHello.
+			//
+			// TLS 1.3 fixes the version number in the record
+			// layer to {3, 1}.
 			vers = VersionTLS10
 		}
 		b.data[1] = byte(vers >> 8)
@@ -952,7 +993,7 @@
 			}
 		}
 		copy(b.data[recordHeaderLen+explicitIVLen:], data)
-		c.out.encrypt(b, explicitIVLen)
+		c.out.encrypt(b, explicitIVLen, typ)
 		_, err = c.conn.Write(b.data)
 		if err != nil {
 			break
diff --git a/ssl/test/runner/dtls.go b/ssl/test/runner/dtls.go
index a31dfc0..3623c55 100644
--- a/ssl/test/runner/dtls.go
+++ b/ssl/test/runner/dtls.go
@@ -105,7 +105,9 @@
 
 	// Process message.
 	b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
-	ok, off, err := c.in.decrypt(b)
+	// TODO(nharper): Once DTLS 1.3 is defined, handle the extra
+	// parameter from decrypt.
+	ok, off, _, err := c.in.decrypt(b)
 	if !ok {
 		c.in.setErrorLocked(c.sendAlert(err))
 	}
@@ -302,6 +304,8 @@
 		panic("Unknown cipher")
 	}
 	b.resize(recordHeaderLen + explicitIVLen + len(data))
+	// TODO(nharper): DTLS 1.3 will likely need to set this to
+	// recordTypeApplicationData if c.out.cipher != nil.
 	b.data[0] = byte(typ)
 	vers := c.vers
 	if vers == 0 {
@@ -327,7 +331,7 @@
 		}
 	}
 	copy(b.data[recordHeaderLen+explicitIVLen:], data)
-	c.out.encrypt(b, explicitIVLen)
+	c.out.encrypt(b, explicitIVLen, typ)
 	return
 }
 
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 76118b3..5123f55 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -670,7 +670,7 @@
 	c := hs.c
 
 	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
-		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
 	var clientCipher, serverCipher interface{}
 	var clientHash, serverHash macFunction
 	if hs.suite.cipher != nil {
@@ -679,8 +679,8 @@
 		serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
 		serverHash = hs.suite.mac(c.vers, serverMAC)
 	} else {
-		clientCipher = hs.suite.aead(clientKey, clientIV)
-		serverCipher = hs.suite.aead(serverKey, serverIV)
+		clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
+		serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
 	}
 
 	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index cf5701f..7d462b5 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -779,7 +779,7 @@
 	c := hs.c
 
 	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
-		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
 
 	var clientCipher, serverCipher interface{}
 	var clientHash, serverHash macFunction
@@ -790,8 +790,8 @@
 		serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
 		serverHash = hs.suite.mac(c.vers, serverMAC)
 	} else {
-		clientCipher = hs.suite.aead(clientKey, clientIV)
-		serverCipher = hs.suite.aead(serverKey, serverIV)
+		clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
+		serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
 	}
 
 	c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index f1b26de..1bfe84c 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -130,7 +130,11 @@
 		return prf30
 	case VersionTLS10, VersionTLS11:
 		return prf10
-	case VersionTLS12:
+	// TODO(nharper): VersionTLS13 is in the case statement below only to
+	// support Fake TLS 1.3. Real TLS 1.3 should never call this function.
+	// Once we no longer support Fake TLS 1.3, the VersionTLS13 should be
+	// removed from this case statement.
+	case VersionTLS12, VersionTLS13:
 		if suite.flags&suiteSHA384 != 0 {
 			return prf12(sha512.New384)
 		}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 17e03cb..e6bfba4 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -883,6 +883,8 @@
 	{"TLS1", VersionTLS10, "-no-tls1", true},
 	{"TLS11", VersionTLS11, "-no-tls11", false},
 	{"TLS12", VersionTLS12, "-no-tls12", true},
+	// TODO(nharper): Once we have a real implementation of TLS 1.3, update the name here.
+	{"FakeTLS13", VersionTLS13, "-no-tls13", false},
 }
 
 var testCipherSuites = []struct {
@@ -948,6 +950,10 @@
 		hasComponent(suiteName, "POLY1305")
 }
 
+func isTLS13Suite(suiteName string) bool {
+	return (hasComponent(suiteName, "GCM") || hasComponent(suiteName, "POLY1305")) && hasComponent(suiteName, "ECDHE") && !hasComponent(suiteName, "OLD")
+}
+
 func isDTLSCipher(suiteName string) bool {
 	return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
 }
@@ -1310,7 +1316,7 @@
 					FragmentClientVersion:    true,
 				},
 			},
-			expectedVersion: VersionTLS12,
+			expectedVersion: VersionTLS13,
 		},
 		{
 			testType: serverTest,
@@ -1320,7 +1326,7 @@
 					SendClientVersion: 0x03ff,
 				},
 			},
-			expectedVersion: VersionTLS12,
+			expectedVersion: VersionTLS13,
 		},
 		{
 			testType: serverTest,
@@ -1330,7 +1336,7 @@
 					SendClientVersion: 0x0400,
 				},
 			},
-			expectedVersion: VersionTLS12,
+			expectedVersion: VersionTLS13,
 		},
 		{
 			testType: serverTest,
@@ -1388,6 +1394,7 @@
 		{
 			name: "RSAEphemeralKey",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
 				Bugs: ProtocolBugs{
 					RSAEphemeralKey: true,
@@ -1657,6 +1664,7 @@
 		{
 			name: "FalseStart-SkipServerSecondLeg",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1678,6 +1686,7 @@
 		{
 			name: "FalseStart-SkipServerSecondLeg-Implicit",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1841,6 +1850,7 @@
 		{
 			name: "FalseStart-BadFinished",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1860,6 +1870,7 @@
 		{
 			name: "NoFalseStart-NoALPN",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				Bugs: ProtocolBugs{
 					ExpectFalseStart:          true,
@@ -1877,6 +1888,7 @@
 		{
 			name: "NoFalseStart-NoAEAD",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1896,6 +1908,7 @@
 		{
 			name: "NoFalseStart-RSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1915,6 +1928,7 @@
 		{
 			name: "NoFalseStart-DHE_RSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1947,6 +1961,7 @@
 			testType: serverTest,
 			name:     "NoCommonCurves",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				CipherSuites: []uint16{
 					TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 					TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
@@ -2301,6 +2316,10 @@
 					shouldClientFail = true
 					shouldServerFail = true
 				}
+				if !isTLS13Suite(suite.name) && ver.version == VersionTLS13 {
+					shouldClientFail = true
+					shouldServerFail = true
+				}
 				if !isDTLSCipher(suite.name) && protocol == dtls {
 					shouldClientFail = true
 					shouldServerFail = true
@@ -2360,40 +2379,31 @@
 					shouldFail:    shouldClientFail,
 					expectedError: expectedClientError,
 				})
-			}
-		}
 
-		// Ensure both TLS and DTLS accept their maximum record sizes.
-		testCases = append(testCases, testCase{
-			name: suite.name + "-LargeRecord",
-			config: Config{
-				CipherSuites:         []uint16{suite.id},
-				Certificates:         []Certificate{cert},
-				PreSharedKey:         []byte(psk),
-				PreSharedKeyIdentity: pskIdentity,
-			},
-			flags:      flags,
-			messageLen: maxPlaintext,
-		})
-		if isDTLSCipher(suite.name) {
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				name:     suite.name + "-LargeRecord-DTLS",
-				config: Config{
-					CipherSuites:         []uint16{suite.id},
-					Certificates:         []Certificate{cert},
-					PreSharedKey:         []byte(psk),
-					PreSharedKeyIdentity: pskIdentity,
-				},
-				flags:      flags,
-				messageLen: maxPlaintext,
-			})
+				if !shouldClientFail {
+					// Ensure the maximum record size is accepted.
+					testCases = append(testCases, testCase{
+						name: prefix + ver.name + "-" + suite.name + "-LargeRecord",
+						config: Config{
+							MinVersion:           ver.version,
+							MaxVersion:           ver.version,
+							CipherSuites:         []uint16{suite.id},
+							Certificates:         []Certificate{cert},
+							PreSharedKey:         []byte(psk),
+							PreSharedKeyIdentity: pskIdentity,
+						},
+						flags:      flags,
+						messageLen: maxPlaintext,
+					})
+				}
+			}
 		}
 	}
 
 	testCases = append(testCases, testCase{
 		name: "WeakDH",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
 				// This is a 1023-bit prime number, generated
@@ -2409,6 +2419,7 @@
 	testCases = append(testCases, testCase{
 		name: "SillyDH",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
 				// This is a 4097-bit prime number, generated
@@ -2428,6 +2439,7 @@
 		testType: serverTest,
 		name:     "DHPublicValuePadded",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
 				RequireDHPublicValueLen: (1025 + 7) / 8,
@@ -2559,6 +2571,7 @@
 	testCases = append(testCases, testCase{
 		name: "MaxCBCPadding",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
 				MaxPadding: true,
@@ -2569,6 +2582,7 @@
 	testCases = append(testCases, testCase{
 		name: "BadCBCPadding",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
 				PaddingFirstByteBad: true,
@@ -2582,6 +2596,7 @@
 	testCases = append(testCases, testCase{
 		name: "BadCBCPadding255",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
 				MaxPadding:               true,
@@ -2690,9 +2705,15 @@
 		}
 	}
 
+	// TODO(davidben): These tests will need TLS 1.3 versions when the
+	// handshake is separate.
+
 	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "RequireAnyClientCertificate",
+		testType: serverTest,
+		name:     "RequireAnyClientCertificate",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		flags:         []string{"-require-any-client-certificate"},
 		shouldFail:    true,
 		expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
@@ -2713,6 +2734,7 @@
 		testType: serverTest,
 		name:     "SkipClientCertificate",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				SkipClientCertificate: true,
 			},
@@ -2728,6 +2750,7 @@
 		testType: clientTest,
 		name:     "ClientAuth-PSK",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
 			PreSharedKey: []byte("secret"),
 			ClientAuth:   RequireAnyClientCert,
@@ -2744,6 +2767,7 @@
 		testType: clientTest,
 		name:     "ClientAuth-ECDHE_PSK",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
 			PreSharedKey: []byte("secret"),
 			ClientAuth:   RequireAnyClientCert,
@@ -2895,6 +2919,9 @@
 func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
 	var tests []testCase
 
+	// TODO(davidben): These tests will need both TLS 1.2 and TLS 1.3
+	// versions when the handshake becomes completely different.
+
 	// Basic handshake, with resumption. Client and server,
 	// session ID and session ticket.
 	tests = append(tests, testCase{
@@ -3038,6 +3065,7 @@
 			testType: serverTest,
 			name:     "Basic-Server-RSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 			},
 			flags: []string{
@@ -3049,6 +3077,7 @@
 			testType: serverTest,
 			name:     "Basic-Server-ECDHE-RSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			},
 			flags: []string{
@@ -3060,6 +3089,7 @@
 			testType: serverTest,
 			name:     "Basic-Server-ECDHE-ECDSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
 			},
 			flags: []string{
@@ -3097,6 +3127,7 @@
 	tests = append(tests, testCase{
 		name: "EmptyPSKHint-Client",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
 			PreSharedKey: []byte("secret"),
 		},
@@ -3106,6 +3137,7 @@
 		testType: serverTest,
 		name:     "EmptyPSKHint-Server",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
 			PreSharedKey: []byte("secret"),
 		},
@@ -3204,6 +3236,7 @@
 		tests = append(tests, testCase{
 			name: "FalseStart",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -3222,6 +3255,7 @@
 		tests = append(tests, testCase{
 			name: "FalseStart-ALPN",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -3241,6 +3275,7 @@
 		tests = append(tests, testCase{
 			name: "FalseStart-Implicit",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 			},
@@ -3255,6 +3290,7 @@
 		tests = append(tests, testCase{
 			name: "FalseStart-SessionTicketsDisabled",
 			config: Config{
+				MaxVersion:             VersionTLS12,
 				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:             []string{"foo"},
 				SessionTicketsDisabled: true,
@@ -3277,6 +3313,7 @@
 				// Choose a cipher suite that does not involve
 				// elliptic curves, so no extensions are
 				// involved.
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
 				Bugs: ProtocolBugs{
 					SendV2ClientHello: true,
@@ -3467,6 +3504,10 @@
 				if clientVers > VersionTLS10 {
 					clientVers = VersionTLS10
 				}
+				serverVers := expectedVersion
+				if expectedVersion >= VersionTLS13 {
+					serverVers = VersionTLS10
+				}
 				testCases = append(testCases, testCase{
 					protocol: protocol,
 					testType: clientTest,
@@ -3501,7 +3542,7 @@
 					config: Config{
 						MaxVersion: runnerVers.version,
 						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: expectedVersion,
+							ExpectInitialRecordVersion: serverVers,
 						},
 					},
 					flags:           flags,
@@ -3514,7 +3555,7 @@
 					config: Config{
 						MaxVersion: runnerVers.version,
 						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: expectedVersion,
+							ExpectInitialRecordVersion: serverVers,
 						},
 					},
 					flags:           []string{"-max-version", shimVersFlag},
@@ -4062,6 +4103,17 @@
 func addResumptionVersionTests() {
 	for _, sessionVers := range tlsVersions {
 		for _, resumeVers := range tlsVersions {
+			cipher := TLS_RSA_WITH_AES_128_CBC_SHA
+			if sessionVers.version >= VersionTLS13 || resumeVers.version >= VersionTLS13 {
+				// TLS 1.3 only shares ciphers with TLS 1.2, so
+				// we skip certain combinations and use a
+				// different cipher to test with.
+				cipher = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+				if sessionVers.version < VersionTLS12 || resumeVers.version < VersionTLS12 {
+					continue
+				}
+			}
+
 			protocols := []protocol{tls}
 			if sessionVers.hasDTLS && resumeVers.hasDTLS {
 				protocols = append(protocols, dtls)
@@ -4079,7 +4131,7 @@
 						resumeSession: true,
 						config: Config{
 							MaxVersion:   sessionVers.version,
-							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+							CipherSuites: []uint16{cipher},
 						},
 						expectedVersion:       sessionVers.version,
 						expectedResumeVersion: resumeVers.version,
@@ -4091,12 +4143,12 @@
 						resumeSession: true,
 						config: Config{
 							MaxVersion:   sessionVers.version,
-							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+							CipherSuites: []uint16{cipher},
 						},
 						expectedVersion: sessionVers.version,
 						resumeConfig: &Config{
 							MaxVersion:   resumeVers.version,
-							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+							CipherSuites: []uint16{cipher},
 							Bugs: ProtocolBugs{
 								AllowSessionVersionMismatch: true,
 							},
@@ -4113,12 +4165,12 @@
 					resumeSession: true,
 					config: Config{
 						MaxVersion:   sessionVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						CipherSuites: []uint16{cipher},
 					},
 					expectedVersion: sessionVers.version,
 					resumeConfig: &Config{
 						MaxVersion:   resumeVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						CipherSuites: []uint16{cipher},
 					},
 					newSessionsOnResume:   true,
 					expectResumeRejected:  true,
@@ -4132,13 +4184,13 @@
 					resumeSession: true,
 					config: Config{
 						MaxVersion:   sessionVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						CipherSuites: []uint16{cipher},
 					},
 					expectedVersion:      sessionVers.version,
 					expectResumeRejected: sessionVers.version != resumeVers.version,
 					resumeConfig: &Config{
 						MaxVersion:   resumeVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						CipherSuites: []uint16{cipher},
 					},
 					expectedResumeVersion: resumeVers.version,
 				})
@@ -4146,13 +4198,16 @@
 		}
 	}
 
+	// TODO(davidben): This test should have a TLS 1.3 variant later.
 	testCases = append(testCases, testCase{
 		name:          "Resume-Client-CipherMismatch",
 		resumeSession: true,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 		},
 		resumeConfig: &Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
 				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
@@ -4278,6 +4333,7 @@
 		name:        "Renegotiate-Client-SwitchCiphers",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
 		},
 		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
@@ -4290,6 +4346,7 @@
 		name:        "Renegotiate-Client-SwitchCiphers2",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 		},
 		renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
@@ -4316,6 +4373,7 @@
 		name:        "Renegotiate-FalseStart",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			NextProtos:   []string{"foo"},
 		},
@@ -5110,6 +5168,7 @@
 		testType: clientTest,
 		name:     "CECPQ1-Client-BadX25519Part",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			MinVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
 			Bugs: ProtocolBugs{
@@ -5124,6 +5183,7 @@
 		testType: clientTest,
 		name:     "CECPQ1-Client-BadNewhopePart",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			MinVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
 			Bugs: ProtocolBugs{
@@ -5138,6 +5198,7 @@
 		testType: serverTest,
 		name:     "CECPQ1-Server-BadX25519Part",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			MinVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
 			Bugs: ProtocolBugs{
@@ -5152,6 +5213,7 @@
 		testType: serverTest,
 		name:     "CECPQ1-Server-BadNewhopePart",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			MinVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
 			Bugs: ProtocolBugs{
@@ -5168,6 +5230,7 @@
 	testCases = append(testCases, testCase{
 		name: "KeyExchangeInfo-RSA-Client",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 		},
 		// key.pem is a 1024-bit RSA key.
@@ -5180,6 +5243,7 @@
 	testCases = append(testCases, testCase{
 		name: "KeyExchangeInfo-DHE-Client",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
 				// This is a 1234-bit prime number, generated
@@ -5194,15 +5258,20 @@
 		testType: serverTest,
 		name:     "KeyExchangeInfo-DHE-Server",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
 		},
 		// bssl_shim as a server configures a 2048-bit DHE group.
 		flags: []string{"-expect-key-exchange-info", "2048"},
 	})
 
+	// TODO(davidben): Add TLS 1.3 versions of these tests once the
+	// handshake is separate.
+
 	testCases = append(testCases, testCase{
 		name: "KeyExchangeInfo-ECDHE-Client",
 		config: Config{
+			MaxVersion:       VersionTLS12,
 			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			CurvePreferences: []CurveID{CurveX25519},
 		},
@@ -5212,6 +5281,7 @@
 		testType: serverTest,
 		name:     "KeyExchangeInfo-ECDHE-Server",
 		config: Config{
+			MaxVersion:       VersionTLS12,
 			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			CurvePreferences: []CurveID{CurveX25519},
 		},