external/boringssl: Sync to 54c259dec395bd991cce5691723214ffe588e51d.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/8459d0659920ab8c99bd300b8a989d4cda251118..54c259dec395bd991cce5691723214ffe588e51d

Test: BoringSSL CTS Presubmits.
Change-Id: I1868f252e94e424d450ebd8983549d9b13455613
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index 321e01d..ab499df 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -228,6 +228,10 @@
   // A zero-length message will never have a pending reassembly.
   assert(msg_len > 0);
 
+  if (start == end) {
+    return;
+  }
+
   if ((start >> 3) == (end >> 3)) {
     frag->reassembly[start >> 3] |= bit_range(start & 7, end & 7);
   } else {
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index a779b8a..52d2e94 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -430,6 +430,8 @@
   SSL *const ssl = hs->ssl;
 
   ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+  // |session_reused| must be reset in case this is a renegotiation.
+  ssl->s3->session_reused = false;
 
   // Freeze the version range.
   if (!ssl_get_version_range(ssl, &hs->min_version, &hs->max_version)) {
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index f196db0..10e618d 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -632,16 +632,6 @@
   if (ssl->session == NULL) {
     hs->new_session->cipher = hs->new_cipher;
 
-    // On new sessions, stash the SNI value in the session.
-    if (hs->hostname != NULL) {
-      OPENSSL_free(hs->new_session->tlsext_hostname);
-      hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname.get());
-      if (hs->new_session->tlsext_hostname == NULL) {
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        return ssl_hs_error;
-      }
-    }
-
     // Determine whether to request a client certificate.
     hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
     // Only request a certificate if Channel ID isn't negotiated.
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 19968ac..0e44de8 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -1208,9 +1208,6 @@
   uint8_t *certificate_types = nullptr;
   size_t num_certificate_types = 0;
 
-  // hostname, on the server, is the value of the SNI extension.
-  UniquePtr<char> hostname;
-
   // local_pubkey is the public key we are authenticating as.
   UniquePtr<EVP_PKEY> local_pubkey;
 
@@ -1764,6 +1761,9 @@
   uint8_t *alpn_selected;
   size_t alpn_selected_len;
 
+  // hostname, on the server, is the value of the SNI extension.
+  char *hostname;
+
   // For a server:
   //     If |tlsext_channel_id_valid| is true, then this contains the
   //     verified Channel ID from the client: a P256 point, (x,y), where
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index fb705aa..dcf9559 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -208,6 +208,7 @@
   ssl_handshake_free(ssl->s3->hs);
   OPENSSL_free(ssl->s3->next_proto_negotiated);
   OPENSSL_free(ssl->s3->alpn_selected);
+  OPENSSL_free(ssl->s3->hostname);
   Delete(ssl->s3->aead_read_ctx);
   Delete(ssl->s3->aead_write_ctx);
   BUF_MEM_free(ssl->s3->pending_flight);
diff --git a/src/ssl/ssl_asn1.cc b/src/ssl/ssl_asn1.cc
index 73908db..7bcfdd7 100644
--- a/src/ssl/ssl_asn1.cc
+++ b/src/ssl/ssl_asn1.cc
@@ -119,8 +119,6 @@
 //     peer                    [3] Certificate OPTIONAL,
 //     sessionIDContext        [4] OCTET STRING OPTIONAL,
 //     verifyResult            [5] INTEGER OPTIONAL,  -- one of X509_V_* codes
-//     hostName                [6] OCTET STRING OPTIONAL,
-//                                 -- from server_name extension
 //     pskIdentity             [8] OCTET STRING OPTIONAL,
 //     ticketLifetimeHint      [9] INTEGER OPTIONAL,       -- client-only
 //     ticket                  [10] OCTET STRING OPTIONAL, -- client-only
@@ -142,9 +140,11 @@
 // }
 //
 // Note: historically this serialization has included other optional
-// fields. Their presence is currently treated as a parse error:
+// fields. Their presence is currently treated as a parse error, except for
+// hostName, which is ignored.
 //
 //     keyArg                  [0] IMPLICIT OCTET STRING OPTIONAL,
+//     hostName                [6] OCTET STRING OPTIONAL,
 //     pskIdentityHint         [7] OCTET STRING OPTIONAL,
 //     compressionMethod       [11] OCTET STRING OPTIONAL,
 //     srpUsername             [12] OCTET STRING OPTIONAL,
@@ -254,16 +254,6 @@
     }
   }
 
-  if (in->tlsext_hostname) {
-    if (!CBB_add_asn1(&session, &child, kHostNameTag) ||
-        !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
-        !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
-                       strlen(in->tlsext_hostname))) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      return 0;
-    }
-  }
-
   if (in->psk_identity) {
     if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
         !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
@@ -627,10 +617,19 @@
           &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
           kSessionIDContextTag) ||
       !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag,
-                              X509_V_OK) ||
-      !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname,
-                                kHostNameTag) ||
-      !SSL_SESSION_parse_string(&session, &ret->psk_identity,
+                              X509_V_OK)) {
+    return nullptr;
+  }
+
+  // Skip the historical hostName field.
+  CBS unused_hostname;
+  if (!CBS_get_optional_asn1(&session, &unused_hostname, nullptr,
+                             kHostNameTag)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+    return nullptr;
+  }
+
+  if (!SSL_SESSION_parse_string(&session, &ret->psk_identity,
                                 kPSKIdentityTag) ||
       !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint,
                              kTicketLifetimeHintTag, 0) ||
diff --git a/src/ssl/ssl_buffer.cc b/src/ssl/ssl_buffer.cc
index d74278e..b424138 100644
--- a/src/ssl/ssl_buffer.cc
+++ b/src/ssl/ssl_buffer.cc
@@ -50,7 +50,11 @@
   }
 
   // Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment.
-  uint8_t *new_buf = (uint8_t *)OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
+  //
+  // Since this buffer gets allocated quite frequently and doesn't contain any
+  // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and
+  // avoid zeroing on free.
+  uint8_t *new_buf = (uint8_t *)malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
   if (new_buf == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return 0;
@@ -62,7 +66,7 @@
 
   if (buf->buf != NULL) {
     OPENSSL_memcpy(new_buf + new_offset, buf->buf + buf->offset, buf->len);
-    OPENSSL_free(buf->buf);
+    free(buf->buf);  // Allocated with malloc().
   }
 
   buf->buf = new_buf;
@@ -81,7 +85,7 @@
 }
 
 static void clear_buffer(SSL3_BUFFER *buf) {
-  OPENSSL_free(buf->buf);
+  free(buf->buf);  // Allocated with malloc().
   OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
 }
 
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index e7a81a3..78cf60d 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -1337,11 +1337,15 @@
     goto err;
   }
   pref_list->ciphers = cipherstack;
-  pref_list->in_group_flags = (uint8_t *)OPENSSL_malloc(num_in_group_flags);
-  if (!pref_list->in_group_flags) {
-    goto err;
+  pref_list->in_group_flags = NULL;
+  if (num_in_group_flags) {
+    pref_list->in_group_flags = (uint8_t *)OPENSSL_malloc(num_in_group_flags);
+    if (!pref_list->in_group_flags) {
+      goto err;
+    }
+    OPENSSL_memcpy(pref_list->in_group_flags, in_group_flags,
+                   num_in_group_flags);
   }
-  OPENSSL_memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
   OPENSSL_free(in_group_flags);
   in_group_flags = NULL;
   if (*out_cipher_list != NULL) {
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 853994b..7a75776 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -1755,25 +1755,11 @@
     return ssl->tlsext_hostname;
   }
 
-  // During the handshake, report the handshake value.
-  if (ssl->s3->hs != NULL) {
-    return ssl->s3->hs->hostname.get();
-  }
-
-  // SSL_get_servername may also be called after the handshake to look up the
-  // SNI value.
-  //
-  // TODO(davidben): This is almost unused. Can we remove it?
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL) {
-    return NULL;
-  }
-  return session->tlsext_hostname;
+  return ssl->s3->hostname;
 }
 
 int SSL_get_servername_type(const SSL *ssl) {
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL || session->tlsext_hostname == NULL) {
+  if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) == NULL) {
     return -1;
   }
   return TLSEXT_NAMETYPE_host_name;
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 32d3b35..c21c282 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -242,13 +242,6 @@
                  SHA256_DIGEST_LENGTH);
   new_session->peer_sha256_valid = session->peer_sha256_valid;
 
-  if (session->tlsext_hostname != NULL) {
-    new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
-    if (new_session->tlsext_hostname == NULL) {
-      return nullptr;
-    }
-  }
-
   new_session->peer_signature_algorithm = session->peer_signature_algorithm;
 
   new_session->timeout = session->timeout;
@@ -889,7 +882,6 @@
   OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
   sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
   session->x509_method->session_clear(session);
-  OPENSSL_free(session->tlsext_hostname);
   OPENSSL_free(session->tlsext_tick);
   CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
   CRYPTO_BUFFER_free(session->ocsp_response);
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index dd795a6..66f0304 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -542,14 +542,14 @@
 // filling in missing fields from |kOpenSSLSession|. This includes
 // providing |peer_sha256|, so |peer| is not serialized.
 static const char kCustomSession[] =
-    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "MIIBZAIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
     "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
-    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
-    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
-    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
-    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
-    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
-    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
+    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUqAcEBXdvcmxkqQUCAwGJwKqBpwSB"
+    "pBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38"
+    "VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd"
+    "3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hg"
+    "b+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYG"
+    "BgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
 
 // kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
 static const char kBoringSSLSession[] =
@@ -1508,10 +1508,15 @@
   return true;
 }
 
+struct ClientConfig {
+  SSL_SESSION *session = nullptr;
+  std::string servername;
+};
+
 static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client,
                                    bssl::UniquePtr<SSL> *out_server,
                                    SSL_CTX *client_ctx, SSL_CTX *server_ctx,
-                                   SSL_SESSION *session) {
+                                   const ClientConfig &config = ClientConfig()) {
   bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
   if (!client || !server) {
     return false;
@@ -1519,7 +1524,13 @@
   SSL_set_connect_state(client.get());
   SSL_set_accept_state(server.get());
 
-  SSL_set_session(client.get(), session);
+  if (config.session) {
+    SSL_set_session(client.get(), config.session);
+  }
+  if (!config.servername.empty() &&
+      !SSL_set_tlsext_host_name(client.get(), config.servername.c_str())) {
+    return false;
+  }
 
   BIO *bio1, *bio2;
   if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
@@ -1573,9 +1584,9 @@
            SSL_CTX_use_PrivateKey(ctx, key_.get());
   }
 
-  bool Connect() {
+  bool Connect(const ClientConfig &config = ClientConfig()) {
     return ConnectClientAndServer(&client_, &server_, client_ctx_.get(),
-                                  server_ctx_.get(), nullptr /* no session */);
+                                  server_ctx_.get(), config);
   }
 
   uint16_t version() const { return GetParam().version; }
@@ -1679,8 +1690,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
 
   SSL_SESSION *session0 = SSL_get_session(client.get());
   bssl::UniquePtr<SSL_SESSION> session1 =
@@ -2117,15 +2127,16 @@
   return 1;
 }
 
-static bssl::UniquePtr<SSL_SESSION> CreateClientSession(SSL_CTX *client_ctx,
-                                                        SSL_CTX *server_ctx) {
+static bssl::UniquePtr<SSL_SESSION> CreateClientSession(
+    SSL_CTX *client_ctx, SSL_CTX *server_ctx,
+    const ClientConfig &config = ClientConfig()) {
   g_last_session = nullptr;
   SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
 
   // Connect client and server to get a session.
   bssl::UniquePtr<SSL> client, server;
   if (!ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
-                              nullptr /* no session */)) {
+                              config)) {
     fprintf(stderr, "Failed to connect client and server.\n");
     return nullptr;
   }
@@ -2145,8 +2156,10 @@
 static void ExpectSessionReused(SSL_CTX *client_ctx, SSL_CTX *server_ctx,
                                 SSL_SESSION *session, bool want_reused) {
   bssl::UniquePtr<SSL> client, server;
-  EXPECT_TRUE(ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
-                                     session));
+  ClientConfig config;
+  config.session = session;
+  EXPECT_TRUE(
+      ConnectClientAndServer(&client, &server, client_ctx, server_ctx, config));
 
   EXPECT_EQ(SSL_session_reused(client.get()), SSL_session_reused(server.get()));
 
@@ -2161,8 +2174,10 @@
   SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
 
   bssl::UniquePtr<SSL> client, server;
-  if (!ConnectClientAndServer(&client, &server, client_ctx,
-                              server_ctx, session)) {
+  ClientConfig config;
+  config.session = session;
+  if (!ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
+                              config)) {
     fprintf(stderr, "Failed to connect client and server.\n");
     return nullptr;
   }
@@ -2640,7 +2655,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(), nullptr));
+                                     server_ctx.get()));
   EXPECT_EQ(TLS1_2_VERSION, SSL_version(client.get()));
 }
 
@@ -3047,6 +3062,58 @@
   }
 }
 
+TEST_P(SSLVersionTest, GetServerName) {
+  // No extensions in SSL 3.0.
+  if (version() == SSL3_VERSION) {
+    return;
+  }
+
+  ClientConfig config;
+  config.servername = "host1";
+
+  SSL_CTX_set_tlsext_servername_callback(
+      server_ctx_.get(), [](SSL *ssl, int *out_alert, void *arg) -> int {
+        // During the handshake, |SSL_get_servername| must match |config|.
+        ClientConfig *config_p = reinterpret_cast<ClientConfig *>(arg);
+        EXPECT_STREQ(config_p->servername.c_str(),
+                     SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name));
+        return SSL_TLSEXT_ERR_OK;
+      });
+  SSL_CTX_set_tlsext_servername_arg(server_ctx_.get(), &config);
+
+  ASSERT_TRUE(Connect(config));
+  // After the handshake, it must also be available.
+  EXPECT_STREQ(config.servername.c_str(),
+               SSL_get_servername(server_.get(), TLSEXT_NAMETYPE_host_name));
+
+  // Establish a session under host1.
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateClientSession(client_ctx_.get(), server_ctx_.get(), config);
+
+  // If the client resumes a session with a different name, |SSL_get_servername|
+  // must return the new name.
+  ASSERT_TRUE(session);
+  config.session = session.get();
+  config.servername = "host2";
+  ASSERT_TRUE(Connect(config));
+  EXPECT_STREQ(config.servername.c_str(),
+               SSL_get_servername(server_.get(), TLSEXT_NAMETYPE_host_name));
+}
+
+// Test that session cache mode bits are honored in the client session callback.
+TEST_P(SSLVersionTest, ClientSessionCacheMode) {
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_OFF);
+  EXPECT_FALSE(CreateClientSession(client_ctx_.get(), server_ctx_.get()));
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_CLIENT);
+  EXPECT_TRUE(CreateClientSession(client_ctx_.get(), server_ctx_.get()));
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_SERVER);
+  EXPECT_FALSE(CreateClientSession(client_ctx_.get(), server_ctx_.get()));
+}
+
 TEST(SSLTest, AddChainCertHack) {
   // Ensure that we don't accidently break the hack that we have in place to
   // keep curl and serf happy when they use an |X509| even after transfering
@@ -3145,8 +3212,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
 }
 
 TEST(SSLTest, ClientCABuffers) {
@@ -3208,8 +3274,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
   EXPECT_TRUE(cert_cb_called);
 }
 
@@ -3487,16 +3552,14 @@
   // way to enable SSL 3.0.
   bssl::UniquePtr<SSL> client, server;
   EXPECT_FALSE(ConnectClientAndServer(&client, &server, tls_ctx.get(),
-                                      ssl3_ctx.get(),
-                                      nullptr /* no session */));
+                                      ssl3_ctx.get()));
   uint32_t err = ERR_get_error();
   EXPECT_EQ(ERR_LIB_SSL, ERR_GET_LIB(err));
   EXPECT_EQ(SSL_R_NO_SUPPORTED_VERSIONS_ENABLED, ERR_GET_REASON(err));
 
   // Likewise for SSLv3_method clients.
   EXPECT_FALSE(ConnectClientAndServer(&client, &server, ssl3_ctx.get(),
-                                      tls_ctx.get(),
-                                      nullptr /* no session */));
+                                      tls_ctx.get()));
   err = ERR_get_error();
   EXPECT_EQ(ERR_LIB_SSL, ERR_GET_LIB(err));
   EXPECT_EQ(SSL_R_NO_SUPPORTED_VERSIONS_ENABLED, ERR_GET_REASON(err));
@@ -3560,8 +3623,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
 
   const std::vector<uint8_t> record = {1, 2, 3, 4, 5};
   std::vector<uint8_t> prefix(
@@ -3604,8 +3666,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
 
   const std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
   std::vector<uint8_t> record = plaintext;
@@ -3643,8 +3704,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
 
   const std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
   std::vector<uint8_t> record = plaintext;
@@ -3683,8 +3743,7 @@
 
   bssl::UniquePtr<SSL> client, server;
   ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
-                                     server_ctx.get(),
-                                     nullptr /* no session */));
+                                     server_ctx.get()));
 
   std::vector<uint8_t> record = {1, 2, 3, 4, 5};
   std::vector<uint8_t> prefix(
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 481c9f8..ec70d27 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -619,31 +619,14 @@
 
 static int ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
-  SSL *const ssl = hs->ssl;
-  if (contents == NULL) {
-    return 1;
-  }
-
-  if (CBS_len(contents) != 0) {
-    return 0;
-  }
-
-  assert(ssl->tlsext_hostname != NULL);
-
-  if (ssl->session == NULL) {
-    OPENSSL_free(hs->new_session->tlsext_hostname);
-    hs->new_session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname);
-    if (!hs->new_session->tlsext_hostname) {
-      *out_alert = SSL_AD_INTERNAL_ERROR;
-      return 0;
-    }
-  }
-
-  return 1;
+  // The server may acknowledge SNI with an empty extension. We check the syntax
+  // but otherwise ignore this signal.
+  return contents == NULL || CBS_len(contents) == 0;
 }
 
 static int ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
@@ -674,12 +657,10 @@
   }
 
   // Copy the hostname as a string.
-  char *hostname_raw = nullptr;
-  if (!CBS_strdup(&host_name, &hostname_raw)) {
+  if (!CBS_strdup(&host_name, &ssl->s3->hostname)) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
-  hs->hostname.reset(hostname_raw);
 
   hs->should_ack_sni = true;
   return 1;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 0c97438..316ae01 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -63,7 +63,7 @@
 #include "../../crypto/internal.h"
 #include "../internal.h"
 #include "async_bio.h"
-#include "fuzzer.h"
+#include "fuzzer_tags.h"
 #include "packeted_bio.h"
 #include "test_config.h"
 
@@ -2407,6 +2407,11 @@
       return false;
     }
 
+    if (SSL_session_reused(ssl)) {
+      fprintf(stderr, "Renegotiations should never resume sessions.\n");
+      return false;
+    }
+
     // Re-check authentication properties after a renegotiation. The reported
     // values should remain unchanged even if the server sent different SCT
     // lists.
diff --git a/src/ssl/test/fuzzer.h b/src/ssl/test/fuzzer.h
index e52f55e..c794c4c 100644
--- a/src/ssl/test/fuzzer.h
+++ b/src/ssl/test/fuzzer.h
@@ -15,104 +15,46 @@
 #ifndef HEADER_SSL_TEST_FUZZER
 #define HEADER_SSL_TEST_FUZZER
 
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include <openssl/bio.h>
 #include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
 #include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "./fuzzer_tags.h"
 
 
-// SSL fuzzer utilities.
-//
-// The TLS client and server fuzzers coordinate with bssl_shim on a common
-// format to encode configuration parameters in a fuzzer file. To add a new
-// configuration, define a tag, update |SetupTest| below to parse it, and
-// update |WriteSettings| in bssl_shim to serialize it. Finally, record
-// transcripts from a test run, and use the BORINGSSL_FUZZER_DEBUG environment
-// variable to confirm the transcripts are compatible.
+namespace {
 
-// kDataTag denotes that the remainder of the input should be passed to the TLS
-// stack.
-static const uint16_t kDataTag = 0;
+const uint8_t kP256KeyPKCS8[] = {
+    0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+    0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf,
+    0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab,
+    0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42,
+    0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5,
+    0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90,
+    0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba,
+    0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73,
+    0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7,
+    0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec,
+};
 
-// kSessionTag is followed by a u24-length-prefixed serialized SSL_SESSION to
-// resume.
-static const uint16_t kSessionTag = 1;
+const uint8_t kOCSPResponse[] = {0x01, 0x02, 0x03, 0x04};
 
-// kRequestClientCert denotes that the server should request client
-// certificates.
-static const uint16_t kRequestClientCert = 2;
+const uint8_t kSCT[] = {0x00, 0x06, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08};
 
-// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure.
-static const uint16_t kTLS13Variant = 3;
-
-// SetupTest parses parameters from |cbs| and returns a newly-configured |SSL|
-// object or nullptr on error. On success, the caller should feed the remaining
-// input in |cbs| to the SSL stack.
-static inline bssl::UniquePtr<SSL> SetupTest(CBS *cbs, SSL_CTX *ctx,
-                                             bool is_server) {
-  // |ctx| is shared between runs, so we must clear any modifications to it made
-  // later on in this function.
-  SSL_CTX_flush_sessions(ctx, 0);
-
-  bssl::UniquePtr<SSL> ssl(SSL_new(ctx));
-  if (is_server) {
-    SSL_set_accept_state(ssl.get());
-  } else {
-    SSL_set_connect_state(ssl.get());
-  }
-
-  for (;;) {
-    uint16_t tag;
-    if (!CBS_get_u16(cbs, &tag)) {
-      return nullptr;
-    }
-    switch (tag) {
-      case kDataTag:
-        return ssl;
-
-      case kSessionTag: {
-        CBS data;
-        if (!CBS_get_u24_length_prefixed(cbs, &data)) {
-          return nullptr;
-        }
-        bssl::UniquePtr<SSL_SESSION> session(
-            SSL_SESSION_from_bytes(CBS_data(&data), CBS_len(&data), ctx));
-        if (!session) {
-          return nullptr;
-        }
-
-        if (is_server) {
-          SSL_CTX_add_session(ctx, session.get());
-        } else {
-          SSL_set_session(ssl.get(), session.get());
-        }
-        break;
-      }
-
-      case kRequestClientCert:
-        if (!is_server) {
-          return nullptr;
-        }
-        SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, nullptr);
-        break;
-
-      case kTLS13Variant: {
-        uint8_t variant;
-        if (!CBS_get_u8(cbs, &variant)) {
-          return nullptr;
-        }
-        SSL_set_tls13_variant(ssl.get(), static_cast<tls13_variant_t>(variant));
-        break;
-      }
-
-      default:
-        return nullptr;
-    }
-  }
-}
-
-
-// Additional shared constants.
-
-static const uint8_t kCertificateDER[] = {
+const uint8_t kCertificateDER[] = {
     0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x11, 0x00, 0xb1, 0x84, 0xee, 0x34, 0x99, 0x98, 0x76, 0xfb,
     0x6f, 0xb2, 0x15, 0xc8, 0x47, 0x79, 0x05, 0x9b, 0x30, 0x0d, 0x06, 0x09,
@@ -180,7 +122,7 @@
     0x76, 0x8a, 0xbb,
 };
 
-static const uint8_t kRSAPrivateKeyDER[] = {
+const uint8_t kRSAPrivateKeyDER[] = {
     0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
     0xce, 0x47, 0xcb, 0x11, 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14,
     0xaf, 0xc7, 0xea, 0xb6, 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc,
@@ -283,5 +225,294 @@
     0x98, 0x46, 0x89, 0x82, 0x40,
 };
 
+const uint8_t kALPNProtocols[] = {
+    0x01, 'a', 0x02, 'a', 'a', 0x03, 'a', 'a', 'a',
+};
+
+int ALPNSelectCallback(SSL *ssl, const uint8_t **out, uint8_t *out_len,
+                       const uint8_t *in, unsigned in_len, void *arg) {
+  static const uint8_t kProtocol[] = {'a', 'a'};
+  *out = kProtocol;
+  *out_len = sizeof(kProtocol);
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int NPNSelectCallback(SSL *ssl, uint8_t **out, uint8_t *out_len,
+                      const uint8_t *in, unsigned in_len, void *arg) {
+  static const uint8_t kProtocol[] = {'a', 'a'};
+  *out = const_cast<uint8_t *>(kProtocol);
+  *out_len = sizeof(kProtocol);
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int NPNAdvertiseCallback(SSL *ssl, const uint8_t **out, unsigned *out_len,
+                         void *arg) {
+  static const uint8_t kProtocols[] = {
+      0x01, 'a', 0x02, 'a', 'a', 0x03, 'a', 'a', 'a',
+  };
+  *out = kProtocols;
+  *out_len = sizeof(kProtocols);
+  return SSL_TLSEXT_ERR_OK;
+}
+
+class TLSFuzzer {
+ public:
+  enum Protocol {
+    kTLS,
+    kDTLS,
+  };
+
+  enum Role {
+    kClient,
+    kServer,
+  };
+
+  TLSFuzzer(Protocol protocol, Role role)
+      : debug_(getenv("BORINGSSL_FUZZER_DEBUG") != nullptr),
+        protocol_(protocol),
+        role_(role) {
+    if (!Init()) {
+      abort();
+    }
+  }
+
+  int TestOneInput(const uint8_t *buf, size_t len) {
+    RAND_reset_for_fuzzing();
+
+    CBS cbs;
+    CBS_init(&cbs, buf, len);
+    bssl::UniquePtr<SSL> ssl = SetupTest(&cbs);
+    if (!ssl) {
+      if (debug_) {
+        fprintf(stderr, "Error parsing parameters.\n");
+      }
+      return 0;
+    }
+
+    if (role_ == kClient) {
+      SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_freely);
+      SSL_set_tlsext_host_name(ssl.get(), "hostname");
+    }
+
+    SSL_set0_rbio(ssl.get(), MakeBIO(CBS_data(&cbs), CBS_len(&cbs)).release());
+    SSL_set0_wbio(ssl.get(), BIO_new(BIO_s_mem()));
+
+    if (SSL_do_handshake(ssl.get()) == 1) {
+      // Keep reading application data until error or EOF.
+      uint8_t tmp[1024];
+      for (;;) {
+        if (SSL_read(ssl.get(), tmp, sizeof(tmp)) <= 0) {
+          break;
+        }
+      }
+    } else if (debug_) {
+      fprintf(stderr, "Handshake failed.\n");
+    }
+
+    if (debug_) {
+      ERR_print_errors_fp(stderr);
+    }
+    ERR_clear_error();
+    return 0;
+  }
+
+ private:
+  // Init initializes |ctx_| with settings common to all inputs.
+  bool Init() {
+    ctx_.reset(SSL_CTX_new(protocol_ == kDTLS ? DTLS_method() : TLS_method()));
+    bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
+    bssl::UniquePtr<RSA> privkey(RSA_private_key_from_bytes(
+        kRSAPrivateKeyDER, sizeof(kRSAPrivateKeyDER)));
+    if (!ctx_ || !privkey || !pkey ||
+        !EVP_PKEY_set1_RSA(pkey.get(), privkey.get()) ||
+        !SSL_CTX_use_PrivateKey(ctx_.get(), pkey.get())) {
+      return false;
+    }
+
+    const uint8_t *bufp = kCertificateDER;
+    bssl::UniquePtr<X509> cert(d2i_X509(NULL, &bufp, sizeof(kCertificateDER)));
+    if (!cert ||
+        !SSL_CTX_use_certificate(ctx_.get(), cert.get()) ||
+        !SSL_CTX_set_ocsp_response(ctx_.get(), kOCSPResponse,
+                                   sizeof(kOCSPResponse)) ||
+        !SSL_CTX_set_signed_cert_timestamp_list(ctx_.get(), kSCT,
+                                                sizeof(kSCT))) {
+      return false;
+    }
+
+    // When accepting peer certificates, allow any certificate.
+    SSL_CTX_set_cert_verify_callback(
+        ctx_.get(),
+        [](X509_STORE_CTX *store_ctx, void *arg) -> int { return 1; }, nullptr);
+
+    SSL_CTX_enable_signed_cert_timestamps(ctx_.get());
+    SSL_CTX_enable_ocsp_stapling(ctx_.get());
+
+    // Enable versions and ciphers that are off by default.
+    if (!SSL_CTX_set_strict_cipher_list(ctx_.get(), "ALL:NULL-SHA")) {
+      return false;
+    }
+    if (protocol_ == kTLS) {
+      if (!SSL_CTX_set_max_proto_version(ctx_.get(), TLS1_3_VERSION) ||
+          !SSL_CTX_set_min_proto_version(ctx_.get(), SSL3_VERSION)) {
+        return false;
+      }
+    }
+
+    SSL_CTX_set_early_data_enabled(ctx_.get(), 1);
+
+    SSL_CTX_set_next_proto_select_cb(ctx_.get(), NPNSelectCallback, nullptr);
+    SSL_CTX_set_next_protos_advertised_cb(ctx_.get(), NPNAdvertiseCallback,
+                                          nullptr);
+
+    SSL_CTX_set_alpn_select_cb(ctx_.get(), ALPNSelectCallback, nullptr);
+    if (SSL_CTX_set_alpn_protos(ctx_.get(), kALPNProtocols,
+                                sizeof(kALPNProtocols)) != 0) {
+      return false;
+    }
+
+    CBS cbs;
+    CBS_init(&cbs, kP256KeyPKCS8, sizeof(kP256KeyPKCS8));
+    pkey.reset(EVP_parse_private_key(&cbs));
+    if (!pkey || !SSL_CTX_set1_tls_channel_id(ctx_.get(), pkey.get())) {
+      return false;
+    }
+    SSL_CTX_set_tls_channel_id_enabled(ctx_.get(), 1);
+
+    return true;
+  }
+
+  // SetupTest parses parameters from |cbs| and returns a newly-configured |SSL|
+  // object or nullptr on error. On success, the caller should feed the
+  // remaining input in |cbs| to the SSL stack.
+  bssl::UniquePtr<SSL> SetupTest(CBS *cbs) {
+    // |ctx| is shared between runs, so we must clear any modifications to it
+    // made later on in this function.
+    SSL_CTX_flush_sessions(ctx_.get(), 0);
+
+    bssl::UniquePtr<SSL> ssl(SSL_new(ctx_.get()));
+    if (role_ == kServer) {
+      SSL_set_accept_state(ssl.get());
+    } else {
+      SSL_set_connect_state(ssl.get());
+    }
+
+    for (;;) {
+      uint16_t tag;
+      if (!CBS_get_u16(cbs, &tag)) {
+        return nullptr;
+      }
+      switch (tag) {
+        case kDataTag:
+          return ssl;
+
+        case kSessionTag: {
+          CBS data;
+          if (!CBS_get_u24_length_prefixed(cbs, &data)) {
+            return nullptr;
+          }
+          bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(
+              CBS_data(&data), CBS_len(&data), ctx_.get()));
+          if (!session) {
+            return nullptr;
+          }
+
+          if (role_ == kServer) {
+            SSL_CTX_add_session(ctx_.get(), session.get());
+          } else {
+            SSL_set_session(ssl.get(), session.get());
+          }
+          break;
+        }
+
+        case kRequestClientCert:
+          if (role_ == kClient) {
+            return nullptr;
+          }
+          SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, nullptr);
+          break;
+
+        case kTLS13Variant: {
+          uint8_t variant;
+          if (!CBS_get_u8(cbs, &variant)) {
+            return nullptr;
+          }
+          SSL_set_tls13_variant(ssl.get(),
+                                static_cast<tls13_variant_t>(variant));
+          break;
+        }
+
+        default:
+          return nullptr;
+      }
+    }
+  }
+
+  struct BIOData {
+    Protocol protocol;
+    CBS cbs;
+  };
+
+  bssl::UniquePtr<BIO> MakeBIO(const uint8_t *in, size_t len) {
+    BIOData *b = new BIOData;
+    b->protocol = protocol_;
+    CBS_init(&b->cbs, in, len);
+
+    bssl::UniquePtr<BIO> bio(BIO_new(&kBIOMethod));
+    bio->init = 1;
+    bio->ptr = b;
+    return bio;
+  }
+
+  static int BIORead(BIO *bio, char *out, int len) {
+    assert(bio->method == &kBIOMethod);
+    BIOData *b = reinterpret_cast<BIOData *>(bio->ptr);
+    if (b->protocol == kTLS) {
+      len = std::min(static_cast<size_t>(len), CBS_len(&b->cbs));
+      memcpy(out, CBS_data(&b->cbs), len);
+      CBS_skip(&b->cbs, len);
+      return len;
+    }
+
+    // Preserve packet boundaries for DTLS.
+    CBS packet;
+    if (!CBS_get_u24_length_prefixed(&b->cbs, &packet)) {
+      return -1;
+    }
+    len = std::min(static_cast<size_t>(len), CBS_len(&packet));
+    memcpy(out, CBS_data(&packet), len);
+    return len;
+  }
+
+  static int BIODestroy(BIO *bio) {
+    assert(bio->method == &kBIOMethod);
+    BIOData *b = reinterpret_cast<BIOData *>(bio->ptr);
+    delete b;
+    return 1;
+  }
+
+  static const BIO_METHOD kBIOMethod;
+
+  bool debug_;
+  Protocol protocol_;
+  Role role_;
+  bssl::UniquePtr<SSL_CTX> ctx_;
+};
+
+const BIO_METHOD TLSFuzzer::kBIOMethod = {
+    0,        // type
+    nullptr,  // name
+    nullptr,  // bwrite
+    TLSFuzzer::BIORead,
+    nullptr,  // bputs
+    nullptr,  // bgets
+    nullptr,  // ctrl
+    nullptr,  // create
+    TLSFuzzer::BIODestroy,
+    nullptr,  // callback_ctrl
+};
+
+}  // namespace
+
 
 #endif  // HEADER_SSL_TEST_FUZZER
diff --git a/src/ssl/test/fuzzer_tags.h b/src/ssl/test/fuzzer_tags.h
new file mode 100644
index 0000000..b161d80
--- /dev/null
+++ b/src/ssl/test/fuzzer_tags.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2017, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef HEADER_SSL_TEST_FUZZER_TAGS
+#define HEADER_SSL_TEST_FUZZER_TAGS
+
+#include <stdint.h>
+
+
+// SSL fuzzer tag constants.
+//
+// The TLS client and server fuzzers coordinate with bssl_shim on a common
+// format to encode configuration parameters in a fuzzer file. To add a new
+// configuration, define a tag, update |SetupTest| in fuzzer.h to parse it, and
+// update |WriteSettings| in bssl_shim to serialize it. Finally, record
+// transcripts from a test run, and use the BORINGSSL_FUZZER_DEBUG environment
+// variable to confirm the transcripts are compatible.
+
+// kDataTag denotes that the remainder of the input should be passed to the TLS
+// stack.
+static const uint16_t kDataTag = 0;
+
+// kSessionTag is followed by a u24-length-prefixed serialized SSL_SESSION to
+// resume.
+static const uint16_t kSessionTag = 1;
+
+// kRequestClientCert denotes that the server should request client
+// certificates.
+static const uint16_t kRequestClientCert = 2;
+
+// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure.
+static const uint16_t kTLS13Variant = 3;
+
+#endif  // HEADER_SSL_TEST_FUZZER_TAGS
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index 2490bee..2681e71 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -48,8 +48,6 @@
 	// client indicates that it supports ECC with a curve and point format
 	// that we're happy with.
 	suiteECDHE = 1 << iota
-	// suiteDHE indicates that the cipher suite involves Diffie-Hellman.
-	suiteDHE
 	// suiteECDSA indicates that the cipher suite involves an ECDSA
 	// signature and therefore may only be selected when the server's
 	// certificate is ECDSA. If this is not set then the cipher suite is
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 7244527..d5b017f 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -119,6 +119,7 @@
 	extensionUseSRTP                    uint16 = 14
 	extensionALPN                       uint16 = 16
 	extensionSignedCertificateTimestamp uint16 = 18
+	extensionPadding                    uint16 = 21
 	extensionExtendedMasterSecret       uint16 = 23
 	extensionSessionTicket              uint16 = 35
 	extensionKeyShare                   uint16 = 40    // draft-ietf-tls-tls13-16
@@ -1434,6 +1435,10 @@
 	// ExpectRecordSplitting, if true, causes application records to only be
 	// accepted if they follow a 1/n-1 record split.
 	ExpectRecordSplitting bool
+
+	// PadClientHello, if non-zero, pads the ClientHello to a multiple of
+	// that many bytes.
+	PadClientHello int
 }
 
 func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
index c81955e..619710c 100644
--- a/src/ssl/test/runner/dtls.go
+++ b/src/ssl/test/runner/dtls.go
@@ -209,8 +209,8 @@
 	isFinished := header[0] == typeFinished
 
 	if c.config.Bugs.SendEmptyFragments {
-		fragment := c.makeFragment(header, data, 0, 0)
-		c.pendingFragments = append(c.pendingFragments, fragment)
+		c.pendingFragments = append(c.pendingFragments, c.makeFragment(header, data, 0, 0))
+		c.pendingFragments = append(c.pendingFragments, c.makeFragment(header, data, len(data), 0))
 	}
 
 	firstRun := true
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 7da08d8..d65119f 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -175,6 +175,7 @@
 	pskBinderFirst          bool
 	omitExtensions          bool
 	emptyExtensions         bool
+	pad                     int
 }
 
 func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -222,7 +223,8 @@
 		m.hasGREASEExtension == m1.hasGREASEExtension &&
 		m.pskBinderFirst == m1.pskBinderFirst &&
 		m.omitExtensions == m1.omitExtensions &&
-		m.emptyExtensions == m1.emptyExtensions
+		m.emptyExtensions == m1.emptyExtensions &&
+		m.pad == m1.pad
 }
 
 func (m *clientHelloMsg) marshal() []byte {
@@ -454,6 +456,16 @@
 		}
 	}
 
+	if m.pad != 0 && hello.len()%m.pad != 0 {
+		extensions.addU16(extensionPadding)
+		padding := extensions.addU16LengthPrefixed()
+		// Note hello.len() has changed at this point from the length
+		// prefix.
+		if l := hello.len() % m.pad; l != 0 {
+			padding.addBytes(make([]byte, m.pad-l))
+		}
+	}
+
 	if m.omitExtensions || m.emptyExtensions {
 		// Silently erase any extensions which were sent.
 		hello.discardChild()
@@ -463,6 +475,10 @@
 	}
 
 	m.raw = handshakeMsg.finish()
+	// Sanity-check padding.
+	if m.pad != 0 && (len(m.raw)-4)%m.pad != 0 {
+		panic(fmt.Sprintf("%d is not a multiple of %d", len(m.raw)-4, m.pad))
+	}
 	return m.raw
 }
 
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 5dee5fb..4a056b9 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -1935,7 +1935,7 @@
 	if !elliptic.P256().IsOnCurve(x, y) {
 		return nil, errors.New("tls: invalid channel ID public key")
 	}
-	channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
+	channelID := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
 	if !ecdsa.Verify(channelID, channelIDHash, r, s) {
 		return nil, errors.New("tls: invalid channel ID signature")
 	}
diff --git a/src/ssl/test/runner/recordingconn.go b/src/ssl/test/runner/recordingconn.go
index 4dae435..427b236 100644
--- a/src/ssl/test/runner/recordingconn.go
+++ b/src/ssl/test/runner/recordingconn.go
@@ -112,6 +112,10 @@
 		if flow.flowType != writeFlow {
 			continue
 		}
+		if r.isDatagram {
+			// Prepend a length prefix to preserve packet boundaries.
+			ret = append(ret, byte(len(flow.data)>>16), byte(len(flow.data)>>8), byte(len(flow.data)))
+		}
 		ret = append(ret, flow.data...)
 	}
 	return ret
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 0ce6849..2ffe795 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -2123,6 +2123,19 @@
 			},
 		},
 		{
+			testType: serverTest,
+			protocol: dtls,
+			name:     "SendEmptyFragments-Padded-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					// Test empty fragments for a message with a
+					// nice power-of-two length.
+					PadClientHello:     64,
+					SendEmptyFragments: true,
+				},
+			},
+		},
+		{
 			name: "BadFinished-Client",
 			config: Config{
 				MaxVersion: VersionTLS12,
@@ -7115,6 +7128,9 @@
 			},
 		},
 		renegotiate: 1,
+		// Test renegotiation after both an initial and resumption
+		// handshake.
+		resumeSession: true,
 		flags: []string{
 			"-renegotiate-freely",
 			"-expect-total-renegotiations", "1",
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index f91da26..98ddaf3 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -839,7 +839,8 @@
   session->ticket_age_add_valid = 1;
   session->not_resumable = 0;
 
-  if (ssl->ctx->new_session_cb != NULL &&
+  if ((ssl->ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) &&
+      ssl->ctx->new_session_cb != NULL &&
       ssl->ctx->new_session_cb(ssl, session.get())) {
     // |new_session_cb|'s return value signals that it took ownership.
     session.release();
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 65c2f11..cd6baa4 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -413,15 +413,6 @@
   // Record connection properties in the new session.
   hs->new_session->cipher = hs->new_cipher;
 
-  if (hs->hostname != NULL) {
-    OPENSSL_free(hs->new_session->tlsext_hostname);
-    hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname.get());
-    if (hs->new_session->tlsext_hostname == NULL) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      return ssl_hs_error;
-    }
-  }
-
   // Store the initial negotiated ALPN in the session.
   if (ssl->s3->alpn_selected != NULL) {
     hs->new_session->early_alpn = (uint8_t *)BUF_memdup(