Merge "Rename target.linux[_x86[_64]] to target.linux_glibc[_x86[_64]]"
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index e46e525..7112211 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-3a18bf04745c0ef9850efeec1a52e402c4392388
+575334657fcb66a4861c9d125430b2aef60476a6
diff --git a/src/PORTING.md b/src/PORTING.md
index c9a16d6..bf3807a 100644
--- a/src/PORTING.md
+++ b/src/PORTING.md
@@ -6,17 +6,27 @@
 library compiles and, on failure, consult the documentation in the header files
 and see if problematic features can be removed.
 
-In some cases, BoringSSL-specific code may be necessary. In that case, the
-`OPENSSL_IS_BORINGSSL` preprocessor macro may be used in `#ifdef`s. This macro
-should also be used in lieu of the presence of any particular function to detect
-OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary.
-Before using the preprocessor, however, contact the BoringSSL maintainers about
-the missing APIs. If not an intentionally removed feature, BoringSSL will
-typically add compatibility functions for convenience.
+BoringSSL's `OPENSSL_VERSION_NUMBER` matches the OpenSSL version it targets.
+Version checks for OpenSSL should ideally work as-is in BoringSSL. BoringSSL
+also defines upstream's `OPENSSL_NO_*` feature macros corresponding to removed
+features. If the preprocessor is needed, use these version checks or feature
+macros where possible, especially when patching third-party projects. Such
+patches are more generally useful to OpenSSL consumers and thus more
+appropriate to send upstream.
 
-For convenience, BoringSSL defines upstream's `OPENSSL_NO_*` feature macros
-corresponding to removed features. These may also be used to disable code which
-uses a removed feature.
+In some cases, BoringSSL-specific code may be necessary. Use the
+`OPENSSL_IS_BORINGSSL` preprocessor macro in `#ifdef`s. However, first contact
+the BoringSSL maintainers about the missing APIs. We will typically add
+compatibility functions for convenience. In particular, *contact BoringSSL
+maintainers before working around missing OpenSSL 1.1.0 accessors*. BoringSSL
+was originally derived from OpenSSL 1.0.2 but now targets OpenSSL 1.1.0. Some
+newer APIs may be missing but can be added on request. (Not all projects have
+been ported to OpenSSL 1.1.0, so BoringSSL also remains largely compatible with
+OpenSSL 1.0.2.)
+
+The `OPENSSL_IS_BORINGSSL` macro may also be used to distinguish OpenSSL from
+BoringSSL in configure scripts. Do not use the presence or absence of particular
+symbols to detect BoringSSL.
 
 Note: BoringSSL does *not* have a stable API or ABI. It must be updated with its
 consumers. It is not suitable for, say, a system library in a traditional Linux
@@ -39,15 +49,19 @@
 Most notably, the `STACK_OF(T)` types have all been converted to use `size_t`
 instead of `int` for indices and lengths.
 
-### Reference counts
+### Reference counts and opaque types
 
 Some external consumers increment reference counts directly by calling
-`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value.
+`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value. These APIs no longer
+exist in BoringSSL. Instead, code which increments reference counts should call
+the corresponding `FOO_up_ref` function, such as `EVP_PKEY_up_ref`.
 
-These APIs no longer exist in BoringSSL. Instead, code which increments
-reference counts should call the corresponding `FOO_up_ref` function, such as
-`EVP_PKEY_up_ref`. Note that not all of these APIs are present in OpenSSL and
-may require `#ifdef`s.
+BoringSSL also hides some structs which were previously exposed in OpenSSL
+1.0.2, particularly in libssl. Use the relevant accessors instead.
+
+Note that some of these APIs were added in OpenSSL 1.1.0, so projects which do
+not yet support 1.1.0 may need additional `#ifdef`s. Projects supporting OpenSSL
+1.1.0 should not require modification.
 
 ### Error codes
 
diff --git a/src/crypto/asn1/asn1_lib.c b/src/crypto/asn1/asn1_lib.c
index f4441d2..ea727f3 100644
--- a/src/crypto/asn1/asn1_lib.c
+++ b/src/crypto/asn1/asn1_lib.c
@@ -435,3 +435,8 @@
 {
     return M_ASN1_STRING_data(x);
 }
+
+const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
+{
+    return x->data;
+}
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 4e88966..3e788b8 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -555,3 +555,82 @@
 }
 
 int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
+
+static struct CRYPTO_STATIC_MUTEX g_index_lock = CRYPTO_STATIC_MUTEX_INIT;
+static int g_index = BIO_TYPE_START;
+
+int BIO_get_new_index(void) {
+  CRYPTO_STATIC_MUTEX_lock_write(&g_index_lock);
+  // If |g_index| exceeds 255, it will collide with the flags bits.
+  int ret = g_index > 255 ? -1 : g_index++;
+  CRYPTO_STATIC_MUTEX_unlock_write(&g_index_lock);
+  return ret;
+}
+
+BIO_METHOD *BIO_meth_new(int type, const char *name) {
+  BIO_METHOD *method = OPENSSL_malloc(sizeof(BIO_METHOD));
+  if (method == NULL) {
+    return NULL;
+  }
+  OPENSSL_memset(method, 0, sizeof(BIO_METHOD));
+  method->type = type;
+  method->name = name;
+  return method;
+}
+
+void BIO_meth_free(BIO_METHOD *method) {
+  OPENSSL_free(method);
+}
+
+int BIO_meth_set_create(BIO_METHOD *method,
+                        int (*create)(BIO *)) {
+  method->create = create;
+  return 1;
+}
+
+int BIO_meth_set_destroy(BIO_METHOD *method,
+                         int (*destroy)(BIO *)) {
+  method->destroy = destroy;
+  return 1;
+}
+
+int BIO_meth_set_write(BIO_METHOD *method,
+                       int (*write)(BIO *, const char *, int)) {
+  method->bwrite = write;
+  return 1;
+}
+
+int BIO_meth_set_read(BIO_METHOD *method,
+                      int (*read)(BIO *, char *, int)) {
+  method->bread = read;
+  return 1;
+}
+
+int BIO_meth_set_gets(BIO_METHOD *method,
+                      int (*gets)(BIO *, char *, int)) {
+  method->bgets = gets;
+  return 1;
+}
+
+int BIO_meth_set_ctrl(BIO_METHOD *method,
+                      long (*ctrl)(BIO *, int, long, void *)) {
+  method->ctrl = ctrl;
+  return 1;
+}
+
+void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; }
+
+void *BIO_get_data(BIO *bio) { return bio->ptr; }
+
+void BIO_set_init(BIO *bio, int init) { bio->init = init; }
+
+int BIO_get_init(BIO *bio) { return bio->init; }
+
+void BIO_set_shutdown(BIO *bio, int shutdown) { bio->shutdown = shutdown; }
+
+int BIO_get_shutdown(BIO *bio) { return bio->shutdown; }
+
+int BIO_meth_set_puts(BIO_METHOD *method, int (*puts)(BIO *, const char *)) {
+  // Ignore the parameter. We implement |BIO_puts| using |BIO_write|.
+  return 1;
+}
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index aee3521..390cd8b 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -156,10 +156,18 @@
   return "BoringSSL";
 }
 
+const char *OpenSSL_version(int unused) {
+  return "BoringSSL";
+}
+
 unsigned long SSLeay(void) {
   return OPENSSL_VERSION_NUMBER;
 }
 
+unsigned long OpenSSL_version_num(void) {
+  return OPENSSL_VERSION_NUMBER;
+}
+
 int CRYPTO_malloc_init(void) {
   return 1;
 }
@@ -171,3 +179,8 @@
 }
 
 void OPENSSL_load_builtin_modules(void) {}
+
+int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) {
+  CRYPTO_library_init();
+  return 1;
+}
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
index 3356776..04e245e 100644
--- a/src/crypto/dh/dh.c
+++ b/src/crypto/dh/dh.c
@@ -124,6 +124,20 @@
   }
 }
 
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
+  if (pub_key != NULL) {
+    BN_free(dh->pub_key);
+    dh->pub_key = pub_key;
+  }
+
+  if (priv_key != NULL) {
+    BN_free(dh->priv_key);
+    dh->priv_key = priv_key;
+  }
+
+  return 1;
+}
+
 void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
                  const BIGNUM **out_g) {
   if (out_p != NULL) {
@@ -137,6 +151,30 @@
   }
 }
 
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
+  if ((dh->p == NULL && p == NULL) ||
+      (dh->g == NULL && g == NULL)) {
+    return 0;
+  }
+
+  if (p != NULL) {
+    BN_free(dh->p);
+    dh->p = p;
+  }
+
+  if (q != NULL) {
+    BN_free(dh->q);
+    dh->q = q;
+  }
+
+  if (g == NULL) {
+    BN_free(dh->g);
+    dh->g = g;
+  }
+
+  return 1;
+}
+
 int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
   // We generate DH parameters as follows
   // find a prime q which is prime_bits/2 bits long.
diff --git a/src/crypto/digest_extra/digest_extra.c b/src/crypto/digest_extra/digest_extra.c
index ab7ff59..4b4bb38 100644
--- a/src/crypto/digest_extra/digest_extra.c
+++ b/src/crypto/digest_extra/digest_extra.c
@@ -62,7 +62,6 @@
 #include <openssl/bytestring.h>
 #include <openssl/nid.h>
 
-#include "internal.h"
 #include "../internal.h"
 
 
@@ -120,22 +119,22 @@
 static const struct {
   uint8_t oid[9];
   uint8_t oid_len;
-  const EVP_MD *(*md_func) (void);
+  int nid;
 } kMDOIDs[] = {
   // 1.2.840.113549.2.4
-  { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, EVP_md4 },
+  { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, NID_md4 },
   // 1.2.840.113549.2.5
-  { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, EVP_md5 },
+  { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, NID_md5 },
   // 1.3.14.3.2.26
-  { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, EVP_sha1 },
+  { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, NID_sha1 },
   // 2.16.840.1.101.3.4.2.1
-  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, EVP_sha256 },
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, NID_sha256 },
   // 2.16.840.1.101.3.4.2.2
-  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, EVP_sha384 },
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, NID_sha384 },
   // 2.16.840.1.101.3.4.2.3
-  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, EVP_sha512 },
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, NID_sha512 },
   // 2.16.840.1.101.3.4.2.4
-  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 },
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, NID_sha224 },
 };
 
 static const EVP_MD *cbs_to_md(const CBS *cbs) {
@@ -143,7 +142,7 @@
     if (CBS_len(cbs) == kMDOIDs[i].oid_len &&
         OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) ==
             0) {
-      return kMDOIDs[i].md_func();
+      return EVP_get_digestbynid(kMDOIDs[i].nid);
     }
   }
 
@@ -192,6 +191,41 @@
   return ret;
 }
 
+int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md) {
+  CBB algorithm, oid, null;
+  if (!CBB_add_asn1(cbb, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
+    OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+
+  int found = 0;
+  int nid = EVP_MD_type(md);
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
+    if (nid == kMDOIDs[i].nid) {
+      if (!CBB_add_bytes(&oid, kMDOIDs[i].oid, kMDOIDs[i].oid_len)) {
+        OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+        return 0;
+      }
+      found = 1;
+      break;
+    }
+  }
+
+  if (!found) {
+    OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH);
+    return 0;
+  }
+
+  if (!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+      !CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+
+  return 1;
+}
+
 const EVP_MD *EVP_get_digestbyname(const char *name) {
   for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
     const char *short_name = nid_to_digest_mapping[i].short_name;
diff --git a/src/crypto/digest_extra/digest_test.cc b/src/crypto/digest_extra/digest_test.cc
index 96fa778..910c731 100644
--- a/src/crypto/digest_extra/digest_test.cc
+++ b/src/crypto/digest_extra/digest_test.cc
@@ -21,6 +21,7 @@
 #include <gtest/gtest.h>
 
 #include <openssl/asn1.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
@@ -31,6 +32,7 @@
 #include <openssl/sha.h>
 
 #include "../internal.h"
+#include "../test/test_util.h"
 
 
 struct MD {
@@ -215,3 +217,44 @@
   EXPECT_EQ(EVP_md5_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_md5_sha1)));
   EXPECT_EQ(EVP_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_sha1)));
 }
+
+TEST(DigestTest, ASN1) {
+  bssl::ScopedCBB cbb;
+  ASSERT_TRUE(CBB_init(cbb.get(), 0));
+  EXPECT_FALSE(EVP_marshal_digest_algorithm(cbb.get(), EVP_md5_sha1()));
+
+  static const uint8_t kSHA256[] = {0x30, 0x0d, 0x06, 0x09, 0x60,
+                                    0x86, 0x48, 0x01, 0x65, 0x03,
+                                    0x04, 0x02, 0x01, 0x05, 0x00};
+  static const uint8_t kSHA256NoParam[] = {0x30, 0x0b, 0x06, 0x09, 0x60,
+                                           0x86, 0x48, 0x01, 0x65, 0x03,
+                                           0x04, 0x02, 0x01};
+  static const uint8_t kSHA256GarbageParam[] = {
+      0x30, 0x0e, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+      0x65, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x2a};
+
+  // Serialize SHA-256.
+  cbb.Reset();
+  ASSERT_TRUE(CBB_init(cbb.get(), 0));
+  ASSERT_TRUE(EVP_marshal_digest_algorithm(cbb.get(), EVP_sha256()));
+  uint8_t *der;
+  size_t der_len;
+  ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
+  bssl::UniquePtr<uint8_t> free_der(der);
+  EXPECT_EQ(Bytes(kSHA256), Bytes(der, der_len));
+
+  // Parse SHA-256.
+  CBS cbs;
+  CBS_init(&cbs, kSHA256, sizeof(kSHA256));
+  EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs));
+  EXPECT_EQ(0u, CBS_len(&cbs));
+
+  // Missing parameters are tolerated for compatibility.
+  CBS_init(&cbs, kSHA256NoParam, sizeof(kSHA256NoParam));
+  EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs));
+  EXPECT_EQ(0u, CBS_len(&cbs));
+
+  // Garbage parameters are not.
+  CBS_init(&cbs, kSHA256GarbageParam, sizeof(kSHA256GarbageParam));
+  EXPECT_FALSE(EVP_parse_digest_algorithm(&cbs));
+}
diff --git a/src/crypto/digest_extra/internal.h b/src/crypto/digest_extra/internal.h
deleted file mode 100644
index 1df200e..0000000
--- a/src/crypto/digest_extra/internal.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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 OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL_H
-#define OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL_H
-
-#include <openssl/base.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
-
-
-#if defined(__cplusplus)
-}  // extern C
-#endif
-
-#endif  // OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
index 1dfc567..61f0c6c 100644
--- a/src/crypto/dsa/dsa.c
+++ b/src/crypto/dsa/dsa.c
@@ -153,6 +153,46 @@
   }
 }
 
+int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key) {
+  if (dsa->pub_key == NULL && pub_key == NULL) {
+    return 0;
+  }
+
+  if (pub_key != NULL) {
+    BN_free(dsa->pub_key);
+    dsa->pub_key = pub_key;
+  }
+  if (priv_key != NULL) {
+    BN_free(dsa->priv_key);
+    dsa->priv_key = priv_key;
+  }
+
+  return 1;
+}
+
+int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
+  if ((dsa->p == NULL && p == NULL) ||
+      (dsa->q == NULL && q == NULL) ||
+      (dsa->g == NULL && g == NULL)) {
+    return 0;
+  }
+
+  if (p != NULL) {
+    BN_free(dsa->p);
+    dsa->p = p;
+  }
+  if (q != NULL) {
+    BN_free(dsa->q);
+    dsa->q = q;
+  }
+  if (g != NULL) {
+    BN_free(dsa->g);
+    dsa->g = g;
+  }
+
+  return 1;
+}
+
 int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
                                size_t seed_len, int *out_counter,
                                unsigned long *out_h, BN_GENCB *cb) {
diff --git a/src/crypto/evp/p_dsa_asn1.c b/src/crypto/evp/p_dsa_asn1.c
index 16d78b7..34b2e70 100644
--- a/src/crypto/evp/p_dsa_asn1.c
+++ b/src/crypto/evp/p_dsa_asn1.c
@@ -151,8 +151,8 @@
   // Calculate the public key.
   ctx = BN_CTX_new();
   if (ctx == NULL ||
-      !BN_mod_exp_mont(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx,
-                       NULL)) {
+      !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p,
+                                 ctx, NULL)) {
     goto err;
   }
 
diff --git a/src/crypto/fipsmodule/cipher/cipher.c b/src/crypto/fipsmodule/cipher/cipher.c
index 00d8390..7b00c3f 100644
--- a/src/crypto/fipsmodule/cipher/cipher.c
+++ b/src/crypto/fipsmodule/cipher/cipher.c
@@ -125,6 +125,11 @@
   return 1;
 }
 
+void EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) {
+  EVP_CIPHER_CTX_cleanup(ctx);
+  EVP_CIPHER_CTX_init(ctx);
+}
+
 int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                       ENGINE *engine, const uint8_t *key, const uint8_t *iv,
                       int enc) {
diff --git a/src/crypto/fipsmodule/digest/digest.c b/src/crypto/fipsmodule/digest/digest.c
index 8afd1e1..1c35809 100644
--- a/src/crypto/fipsmodule/digest/digest.c
+++ b/src/crypto/fipsmodule/digest/digest.c
@@ -79,7 +79,7 @@
   OPENSSL_memset(ctx, 0, sizeof(EVP_MD_CTX));
 }
 
-EVP_MD_CTX *EVP_MD_CTX_create(void) {
+EVP_MD_CTX *EVP_MD_CTX_new(void) {
   EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
 
   if (ctx) {
@@ -89,6 +89,8 @@
   return ctx;
 }
 
+EVP_MD_CTX *EVP_MD_CTX_create(void) { return EVP_MD_CTX_new(); }
+
 int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) {
   OPENSSL_free(ctx->md_data);
 
@@ -102,7 +104,7 @@
   return 1;
 }
 
-void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) {
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx) {
   if (!ctx) {
     return;
   }
@@ -111,6 +113,8 @@
   OPENSSL_free(ctx);
 }
 
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { EVP_MD_CTX_free(ctx); }
+
 int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) {
   if (in == NULL || in->digest == NULL) {
     OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED);
@@ -162,6 +166,11 @@
   return EVP_MD_CTX_copy_ex(out, in);
 }
 
+void EVP_MD_CTX_reset(EVP_MD_CTX *ctx) {
+  EVP_MD_CTX_cleanup(ctx);
+  EVP_MD_CTX_init(ctx);
+}
+
 int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) {
   if (ctx->digest != type) {
     assert(type->ctx_size != 0);
diff --git a/src/crypto/fipsmodule/hmac/hmac.c b/src/crypto/fipsmodule/hmac/hmac.c
index 5c098db..fb57bf2 100644
--- a/src/crypto/fipsmodule/hmac/hmac.c
+++ b/src/crypto/fipsmodule/hmac/hmac.c
@@ -87,6 +87,14 @@
   EVP_MD_CTX_init(&ctx->md_ctx);
 }
 
+HMAC_CTX *HMAC_CTX_new(void) {
+  HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
+  if (ctx != NULL) {
+    HMAC_CTX_init(ctx);
+  }
+  return ctx;
+}
+
 void HMAC_CTX_cleanup(HMAC_CTX *ctx) {
   EVP_MD_CTX_cleanup(&ctx->i_ctx);
   EVP_MD_CTX_cleanup(&ctx->o_ctx);
@@ -94,6 +102,15 @@
   OPENSSL_cleanse(ctx, sizeof(HMAC_CTX));
 }
 
+void HMAC_CTX_free(HMAC_CTX *ctx) {
+  if (ctx == NULL) {
+    return;
+  }
+
+  HMAC_CTX_cleanup(ctx);
+  OPENSSL_free(ctx);
+}
+
 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
                  const EVP_MD *md, ENGINE *impl) {
   if (md == NULL) {
@@ -193,6 +210,11 @@
   return 1;
 }
 
+void HMAC_CTX_reset(HMAC_CTX *ctx) {
+  HMAC_CTX_cleanup(ctx);
+  HMAC_CTX_init(ctx);
+}
+
 int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) {
   if (key && md) {
     HMAC_CTX_init(ctx);
diff --git a/src/crypto/fipsmodule/rsa/rsa.c b/src/crypto/fipsmodule/rsa/rsa.c
index 17348c1..d001d7b 100644
--- a/src/crypto/fipsmodule/rsa/rsa.c
+++ b/src/crypto/fipsmodule/rsa/rsa.c
@@ -193,6 +193,69 @@
   }
 }
 
+int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
+  if ((rsa->n == NULL && n == NULL) ||
+      (rsa->e == NULL && e == NULL)) {
+    return 0;
+  }
+
+  if (n != NULL) {
+    BN_free(rsa->n);
+    rsa->n = n;
+  }
+  if (e != NULL) {
+    BN_free(rsa->e);
+    rsa->e = e;
+  }
+  if (d != NULL) {
+    BN_free(rsa->d);
+    rsa->d = d;
+  }
+
+  return 1;
+}
+
+int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q) {
+  if ((rsa->p == NULL && p == NULL) ||
+      (rsa->q == NULL && q == NULL)) {
+    return 0;
+  }
+
+  if (p != NULL) {
+    BN_free(rsa->p);
+    rsa->p = p;
+  }
+  if (q != NULL) {
+    BN_free(rsa->q);
+    rsa->q = q;
+  }
+
+  return 1;
+}
+
+int RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) {
+  if ((rsa->dmp1 == NULL && dmp1 == NULL) ||
+      (rsa->dmq1 == NULL && dmq1 == NULL) ||
+      (rsa->iqmp == NULL && iqmp == NULL)) {
+    return 0;
+  }
+
+  if (dmp1 != NULL) {
+    BN_free(rsa->dmp1);
+    rsa->dmp1 = dmp1;
+  }
+  if (dmq1 != NULL) {
+    BN_free(rsa->dmq1);
+    rsa->dmq1 = dmq1;
+  }
+  if (iqmp != NULL) {
+    BN_free(rsa->iqmp);
+    rsa->iqmp = iqmp;
+  }
+
+  return 1;
+}
+
 int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
                        int padding) {
   size_t out_len;
diff --git a/src/crypto/obj/obj.c b/src/crypto/obj/obj.c
index 3968515..52e265b 100644
--- a/src/crypto/obj/obj.c
+++ b/src/crypto/obj/obj.c
@@ -172,6 +172,22 @@
   return OPENSSL_memcmp(a->data, b->data, a->length);
 }
 
+const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj) {
+  if (obj == NULL) {
+    return NULL;
+  }
+
+  return obj->data;
+}
+
+size_t OBJ_length(const ASN1_OBJECT *obj) {
+  if (obj == NULL || obj->length < 0) {
+    return 0;
+  }
+
+  return (size_t)obj->length;
+}
+
 // obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
 // an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
 // unsigned int in the array.
diff --git a/src/crypto/pkcs8/pkcs8_x509.c b/src/crypto/pkcs8/pkcs8_x509.c
index ace5f33..b3e2d93 100644
--- a/src/crypto/pkcs8/pkcs8_x509.c
+++ b/src/crypto/pkcs8/pkcs8_x509.c
@@ -71,7 +71,6 @@
 
 #include "internal.h"
 #include "../bytestring/internal.h"
-#include "../digest_extra/internal.h"
 #include "../internal.h"
 
 
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index d4f6bba..3339523 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -299,7 +299,8 @@
     return (0);
 }
 
-int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
+int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
+                         const ASN1_STRING *sig)
 {
     if (BIO_puts(bp, "    Signature Algorithm: ") <= 0)
         return 0;
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
index f2371bd..1014a05 100644
--- a/src/crypto/x509/x509_lu.c
+++ b/src/crypto/x509/x509_lu.c
@@ -434,6 +434,19 @@
     }
 }
 
+int X509_OBJECT_get_type(const X509_OBJECT *a)
+{
+    return a->type;
+}
+
+X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
+{
+    if (a == NULL || a->type != X509_LU_X509) {
+        return NULL;
+    }
+    return a->data.x509;
+}
+
 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
                                X509_NAME *name, int *pnmatch)
 {
@@ -496,6 +509,11 @@
     return sk_X509_OBJECT_value(h, idx);
 }
 
+STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st)
+{
+    return st->objs;
+}
+
 STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
 {
     int i, idx, cnt;
@@ -684,6 +702,11 @@
     return X509_VERIFY_PARAM_set1(ctx->param, param);
 }
 
+X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
+{
+    return ctx->param;
+}
+
 void X509_STORE_set_verify_cb(X509_STORE *ctx,
                               int (*verify_cb) (int, X509_STORE_CTX *))
 {
diff --git a/src/crypto/x509/x509_set.c b/src/crypto/x509/x509_set.c
index 67c1842..413a20d 100644
--- a/src/crypto/x509/x509_set.c
+++ b/src/crypto/x509/x509_set.c
@@ -124,6 +124,11 @@
     return (in != NULL);
 }
 
+const ASN1_TIME *X509_get0_notBefore(const X509 *x)
+{
+    return x->cert_info->validity->notBefore;
+}
+
 int X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
 {
     ASN1_TIME *in;
@@ -141,6 +146,11 @@
     return (in != NULL);
 }
 
+const ASN1_TIME *X509_get0_notAfter(const X509 *x)
+{
+    return x->cert_info->validity->notAfter;
+}
+
 int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
 {
     if ((x == NULL) || (x->cert_info == NULL))
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
index 5228d01..8e258fe 100644
--- a/src/crypto/x509/x509_vfy.c
+++ b/src/crypto/x509/x509_vfy.c
@@ -2176,6 +2176,11 @@
     ctx->untrusted = sk;
 }
 
+STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
+{
+    return ctx->untrusted;
+}
+
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
 {
     ctx->crls = sk;
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
index 9852415..0980463 100644
--- a/src/crypto/x509/x_name.c
+++ b/src/crypto/x509/x_name.c
@@ -534,3 +534,8 @@
 }
 
 IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)
+
+int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
+{
+    return ne->set;
+}
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
index 9edfa00..01464a1 100644
--- a/src/crypto/x509/x_x509.c
+++ b/src/crypto/x509/x_x509.c
@@ -313,7 +313,7 @@
     return length;
 }
 
-void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg,
                          const X509 *x)
 {
     if (psig)
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
index 45d4848..2ef4c97 100644
--- a/src/include/openssl/asn1.h
+++ b/src/include/openssl/asn1.h
@@ -660,6 +660,7 @@
 OPENSSL_EXPORT void ASN1_STRING_length_set(ASN1_STRING *x, int n);
 OPENSSL_EXPORT int ASN1_STRING_type(ASN1_STRING *x);
 OPENSSL_EXPORT unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+OPENSSL_EXPORT const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
 
 DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
 OPENSSL_EXPORT int		i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 2be5ed0..aa65b4a 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -135,8 +135,12 @@
 #define OPENSSL_NO_THREADS
 #endif
 
+#if !defined(OPENSSL_NO_THREADS)
+#define OPENSSL_THREADS
+#endif
+
 #define OPENSSL_IS_BORINGSSL
-#define OPENSSL_VERSION_NUMBER 0x100020af
+#define OPENSSL_VERSION_NUMBER 0x1010007f
 #define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
 
 // BORINGSSL_API_VERSION is a positive integer that increments as BoringSSL
@@ -318,6 +322,7 @@
 typedef struct hmac_ctx_st HMAC_CTX;
 typedef struct md4_state_st MD4_CTX;
 typedef struct md5_state_st MD5_CTX;
+typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
 typedef struct pkcs12_st PKCS12;
 typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
 typedef struct private_key_st X509_PKEY;
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index 095ac75..b397696 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -218,6 +218,18 @@
 // values.
 OPENSSL_EXPORT int BIO_method_type(const BIO *bio);
 
+// These are passed to the BIO callback
+#define BIO_CB_FREE 0x01
+#define BIO_CB_READ 0x02
+#define BIO_CB_WRITE 0x03
+#define BIO_CB_PUTS 0x04
+#define BIO_CB_GETS 0x05
+#define BIO_CB_CTRL 0x06
+
+// The callback is called before and after the underling operation,
+// The BIO_CB_RETURN flag indicates if it is after the call
+#define BIO_CB_RETURN 0x80
+
 // bio_info_cb is the type of a callback function that can be called for most
 // BIO operations. The |event| argument is one of |BIO_CB_*| and can be ORed
 // with |BIO_CB_RETURN| if the callback is being made after the operation in
@@ -348,6 +360,11 @@
 //
 // |BIO_ctrl_pending| returns the number of bytes currently stored.
 
+// BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
+// flag" is passed to a BIO function.
+#define BIO_NOCLOSE 0
+#define BIO_CLOSE 1
+
 // BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer.
 OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void);
 
@@ -589,22 +606,72 @@
 OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio);
 
 
-// BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
-// flag" is passed to a BIO function.
-#define BIO_NOCLOSE 0
-#define BIO_CLOSE 1
+// Custom BIOs.
+//
+// Consumers can create custom |BIO|s by filling in a |BIO_METHOD| and using
+// low-level control functions to set state.
 
-// These are passed to the BIO callback
-#define BIO_CB_FREE 0x01
-#define BIO_CB_READ 0x02
-#define BIO_CB_WRITE 0x03
-#define BIO_CB_PUTS 0x04
-#define BIO_CB_GETS 0x05
-#define BIO_CB_CTRL 0x06
+// BIO_get_new_index returns a new "type" value for a custom |BIO|.
+OPENSSL_EXPORT int BIO_get_new_index(void);
 
-// The callback is called before and after the underling operation,
-// The BIO_CB_RETURN flag indicates if it is after the call
-#define BIO_CB_RETURN 0x80
+// BIO_meth_new returns a newly-allocated |BIO_METHOD| or NULL on allocation
+// error. The |type| specifies the type that will be returned by
+// |BIO_method_type|. If this is unnecessary, this value may be zero. The |name|
+// parameter is vestigial and may be NULL.
+//
+// Use the |BIO_meth_set_*| functions below to initialize the |BIO_METHOD|. The
+// function implementations may use |BIO_set_data| and |BIO_get_data| to add
+// method-specific state to associated |BIO|s. Additionally, |BIO_set_init| must
+// be called after an associated |BIO| is fully initialized.
+OPENSSL_EXPORT BIO_METHOD *BIO_meth_new(int type, const char *name);
+
+// BIO_meth_free releases memory associated with |method|.
+OPENSSL_EXPORT void BIO_meth_free(BIO_METHOD *method);
+
+// BIO_meth_set_create sets a function to be called on |BIO_new| for |method|
+// and returns one. The function should return one on success and zero on
+// error.
+OPENSSL_EXPORT int BIO_meth_set_create(BIO_METHOD *method,
+                                       int (*create)(BIO *));
+
+// BIO_meth_set_destroy sets a function to release data associated with a |BIO|
+// and returns one. The function's return value is ignored.
+OPENSSL_EXPORT int BIO_meth_set_destroy(BIO_METHOD *method,
+                                        int (*destroy)(BIO *));
+
+// BIO_meth_set_write sets the implementation of |BIO_write| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_write(BIO_METHOD *method,
+                                      int (*write)(BIO *, const char *, int));
+
+// BIO_meth_set_read sets the implementation of |BIO_read| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_read(BIO_METHOD *method,
+                                     int (*read)(BIO *, char *, int));
+
+// BIO_meth_set_gets sets the implementation of |BIO_gets| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_gets(BIO_METHOD *method,
+                                     int (*gets)(BIO *, char *, int));
+
+// BIO_meth_set_ctrl sets the implementation of |BIO_ctrl| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_ctrl(BIO_METHOD *method,
+                                     long (*ctrl)(BIO *, int, long, void *));
+
+// BIO_set_data sets custom data on |bio|. It may be retried with
+// |BIO_get_data|.
+OPENSSL_EXPORT void BIO_set_data(BIO *bio, void *ptr);
+
+// BIO_get_data returns custom data on |bio| set by |BIO_get_data|.
+OPENSSL_EXPORT void *BIO_get_data(BIO *bio);
+
+// BIO_set_init sets whether |bio| has been fully initialized. Until fully
+// initialized, |BIO_read| and |BIO_write| will fail.
+OPENSSL_EXPORT void BIO_set_init(BIO *bio, int init);
+
+// BIO_get_init returns whether |bio| has been fully initialized.
+OPENSSL_EXPORT int BIO_get_init(BIO *bio);
 
 // These are values of the |cmd| argument to |BIO_ctrl|.
 #define BIO_CTRL_RESET		1  // opt - rewind/zero etc
@@ -643,6 +710,17 @@
 // BIO_set_write_buffer_size returns zero.
 OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size);
 
+// BIO_set_shutdown sets a method-specific "shutdown" bit on |bio|.
+OPENSSL_EXPORT void BIO_set_shutdown(BIO *bio, int shutdown);
+
+// BIO_get_shutdown returns the method-specific "shutdown" bit.
+OPENSSL_EXPORT int BIO_get_shutdown(BIO *bio);
+
+// BIO_meth_set_puts returns one. |BIO_puts| is implemented with |BIO_write| in
+// BoringSSL.
+OPENSSL_EXPORT int BIO_meth_set_puts(BIO_METHOD *method,
+                                     int (*puts)(BIO *, const char *));
+
 
 // Private functions
 
@@ -681,10 +759,16 @@
 #define BIO_TYPE_ASN1 (22 | 0x0200)  // filter
 #define BIO_TYPE_COMP (23 | 0x0200)  // filter
 
+// |BIO_TYPE_DESCRIPTOR| denotes that the |BIO| responds to the |BIO_C_SET_FD|
+// (|BIO_set_fd|) and |BIO_C_GET_FD| (|BIO_get_fd|) control hooks.
 #define BIO_TYPE_DESCRIPTOR 0x0100  // socket, fd, connect or accept
 #define BIO_TYPE_FILTER 0x0200
 #define BIO_TYPE_SOURCE_SINK 0x0400
 
+// BIO_TYPE_START is the first user-allocated |BIO| type. No pre-defined type,
+// flag bits aside, may exceed this value.
+#define BIO_TYPE_START 128
+
 struct bio_method_st {
   int type;
   const char *name;
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
index a09b49c..66f6204 100644
--- a/src/include/openssl/bytestring.h
+++ b/src/include/openssl/bytestring.h
@@ -17,6 +17,8 @@
 
 #include <openssl/base.h>
 
+#include <openssl/span.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -37,6 +39,13 @@
 struct cbs_st {
   const uint8_t *data;
   size_t len;
+
+#if !defined(BORINGSSL_NO_CXX)
+  // Allow implicit conversions to bssl::Span<const uint8_t>.
+  operator bssl::Span<const uint8_t>() const {
+    return bssl::MakeConstSpan(data, len);
+  }
+#endif
 };
 
 // CBS_init sets |cbs| to point to |data|. It does not take ownership of
diff --git a/src/include/openssl/cipher.h b/src/include/openssl/cipher.h
index 7fbee8b..5c380a1 100644
--- a/src/include/openssl/cipher.h
+++ b/src/include/openssl/cipher.h
@@ -135,6 +135,10 @@
 OPENSSL_EXPORT int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out,
                                        const EVP_CIPHER_CTX *in);
 
+// EVP_CIPHER_CTX_reset calls |EVP_CIPHER_CTX_cleanup| followed by
+// |EVP_CIPHER_CTX_init|.
+OPENSSL_EXPORT void EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
+
 
 // Cipher context configuration.
 
diff --git a/src/include/openssl/crypto.h b/src/include/openssl/crypto.h
index c94f39f..dc87dd2 100644
--- a/src/include/openssl/crypto.h
+++ b/src/include/openssl/crypto.h
@@ -63,7 +63,7 @@
 
 // OPENSSL_VERSION_TEXT contains a string the identifies the version of
 // “OpenSSL”. node.js requires a version number in this text.
-#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2 (compatible; BoringSSL)"
+#define OPENSSL_VERSION_TEXT "OpenSSL 1.1.0 (compatible; BoringSSL)"
 
 #define SSLEAY_VERSION 0
 
@@ -71,10 +71,20 @@
 // "BoringSSL".
 OPENSSL_EXPORT const char *SSLeay_version(int unused);
 
+#define OPENSSL_VERSION 0
+
+// OpenSSL_version is a compatibility function that returns the string
+// "BoringSSL".
+OPENSSL_EXPORT const char *OpenSSL_version(int unused);
+
 // SSLeay is a compatibility function that returns OPENSSL_VERSION_NUMBER from
 // base.h.
 OPENSSL_EXPORT unsigned long SSLeay(void);
 
+// OpenSSL_version_num is a compatibility function that returns
+// OPENSSL_VERSION_NUMBER from base.h.
+OPENSSL_EXPORT unsigned long OpenSSL_version_num(void);
+
 // CRYPTO_malloc_init returns one.
 OPENSSL_EXPORT int CRYPTO_malloc_init(void);
 
@@ -87,6 +97,19 @@
 // OPENSSL_load_builtin_modules does nothing.
 OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void);
 
+#define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0
+#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0
+#define OPENSSL_INIT_ADD_ALL_CIPHERS 0
+#define OPENSSL_INIT_ADD_ALL_DIGESTS 0
+#define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0
+#define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0
+#define OPENSSL_INIT_LOAD_CONFIG 0
+#define OPENSSL_INIT_NO_LOAD_CONFIG 0
+
+// OPENSSL_init_crypto calls |CRYPTO_library_init| and returns one.
+OPENSSL_EXPORT int OPENSSL_init_crypto(uint64_t opts,
+                                       const OPENSSL_INIT_SETTINGS *settings);
+
 
 #if defined(__cplusplus)
 }  // extern C
diff --git a/src/include/openssl/dh.h b/src/include/openssl/dh.h
index d78bbeb..ae24c25 100644
--- a/src/include/openssl/dh.h
+++ b/src/include/openssl/dh.h
@@ -92,11 +92,22 @@
 OPENSSL_EXPORT void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
                                 const BIGNUM **out_priv_key);
 
+// DH_set0_key sets |dh|'s public and private key to the specified values. If
+// NULL, the field is left unchanged. On success, it takes ownership of each
+// argument and returns one. Otherwise, it returns zero.
+OPENSSL_EXPORT int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+
 // DH_get0_pqg sets |*out_p|, |*out_q|, and |*out_g|, if non-NULL, to |dh|'s p,
 // q, and g parameters, respectively.
 OPENSSL_EXPORT void DH_get0_pqg(const DH *dh, const BIGNUM **out_p,
                                 const BIGNUM **out_q, const BIGNUM **out_g);
 
+// DH_set0_pqg sets |dh|'s p, q, and g parameters to the specified values.  If
+// NULL, the field is left unchanged. On success, it takes ownership of each
+// argument and returns one. Otherwise, it returns zero. |q| may be NULL, but
+// |p| and |g| must either be specified or already configured on |dh|.
+OPENSSL_EXPORT int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+
 
 // Standard parameters.
 
diff --git a/src/include/openssl/digest.h b/src/include/openssl/digest.h
index ad6dd50..81f5892 100644
--- a/src/include/openssl/digest.h
+++ b/src/include/openssl/digest.h
@@ -106,21 +106,25 @@
 // same as setting the structure to zero.
 OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
 
-// EVP_MD_CTX_create allocates and initialises a fresh |EVP_MD_CTX| and returns
-// it, or NULL on allocation failure.
-OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void);
+// EVP_MD_CTX_new allocates and initialises a fresh |EVP_MD_CTX| and returns
+// it, or NULL on allocation failure. The caller must use |EVP_MD_CTX_free| to
+// release the resulting object.
+OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_new(void);
 
 // EVP_MD_CTX_cleanup frees any resources owned by |ctx| and resets it to a
 // freshly initialised state. It does not free |ctx| itself. It returns one.
 OPENSSL_EXPORT int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
 
-// EVP_MD_CTX_destroy calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself.
-OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+// EVP_MD_CTX_free calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself.
+OPENSSL_EXPORT void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
 
 // EVP_MD_CTX_copy_ex sets |out|, which must already be initialised, to be a
 // copy of |in|. It returns one on success and zero on error.
 OPENSSL_EXPORT int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
 
+// EVP_MD_CTX_reset calls |EVP_MD_CTX_cleanup| followed by |EVP_MD_CTX_init|.
+OPENSSL_EXPORT void EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
+
 
 // Digest operations.
 
@@ -201,6 +205,43 @@
 #define EVP_MD_FLAG_DIGALGID_ABSENT 2
 
 
+// Digest operation accessors.
+
+// EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not
+// been set.
+OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+
+// EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It
+// will crash if a digest hasn't been set on |ctx|.
+OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
+
+// EVP_MD_CTX_block_size returns the block size of the digest function used by
+// |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|.
+OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
+
+// EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
+// (For example, |NID_sha256|.) It will crash if a digest hasn't been set on
+// |ctx|.
+OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx);
+
+
+// ASN.1 functions.
+//
+// These functions allow code to parse and serialize AlgorithmIdentifiers for
+// hash functions.
+
+// EVP_parse_digest_algorithm parses an AlgorithmIdentifier structure containing
+// a hash function OID (for example, 2.16.840.1.101.3.4.2.1 is SHA-256) and
+// advances |cbs|. The parameters field may either be omitted or a NULL. It
+// returns the digest function or NULL on error.
+OPENSSL_EXPORT const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
+
+// EVP_marshal_digest_algorithm marshals |md| as an AlgorithmIdentifier
+// structure and appends the result to |cbb|. It returns one on success and zero
+// on error.
+OPENSSL_EXPORT int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md);
+
+
 // Deprecated functions.
 
 // EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of
@@ -221,25 +262,11 @@
 // interface will always fail.
 OPENSSL_EXPORT const EVP_MD *EVP_dss1(void);
 
+// EVP_MD_CTX_create calls |EVP_MD_CTX_new|.
+OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void);
 
-// Digest operation accessors.
-
-// EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not
-// been set.
-OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
-
-// EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It
-// will crash if a digest hasn't been set on |ctx|.
-OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
-
-// EVP_MD_CTX_block_size returns the block size of the digest function used by
-// |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|.
-OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
-
-// EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
-// (For example, |NID_sha256|.) It will crash if a digest hasn't been set on
-// |ctx|.
-OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx);
+// EVP_MD_CTX_destroy calls |EVP_MD_CTX_free|.
+OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
 
 
 struct evp_md_pctx_ops;
@@ -269,7 +296,7 @@
 
 namespace bssl {
 
-BORINGSSL_MAKE_DELETER(EVP_MD_CTX, EVP_MD_CTX_destroy)
+BORINGSSL_MAKE_DELETER(EVP_MD_CTX, EVP_MD_CTX_free)
 
 using ScopedEVP_MD_CTX =
     internal::StackAllocated<EVP_MD_CTX, int, EVP_MD_CTX_init,
diff --git a/src/include/openssl/dsa.h b/src/include/openssl/dsa.h
index 2b4c08b..315e7ca 100644
--- a/src/include/openssl/dsa.h
+++ b/src/include/openssl/dsa.h
@@ -101,6 +101,21 @@
 OPENSSL_EXPORT void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p,
                                  const BIGNUM **out_q, const BIGNUM **out_g);
 
+// DSA_set0_key sets |dsa|'s public and private key to |pub_key| and |priv_key|,
+// respectively, if non-NULL. On success, it takes ownership of each argument
+// and returns one. Otherwise, it returns zero.
+//
+// |priv_key| may be NULL, but |pub_key| must either be non-NULL or already
+// configured on |dsa|.
+OPENSSL_EXPORT int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key);
+
+// DSA_set0_pqg sets |dsa|'s parameters to |p|, |q|, and |g|, if non-NULL, and
+// takes ownership of them. On success, it takes ownership of each argument and
+// returns one. Otherwise, it returns zero.
+//
+// Each argument must either be non-NULL or already configured on |dsa|.
+OPENSSL_EXPORT int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+
 
 // Parameter generation.
 
diff --git a/src/include/openssl/hmac.h b/src/include/openssl/hmac.h
index 1754d7f..8491b8d 100644
--- a/src/include/openssl/hmac.h
+++ b/src/include/openssl/hmac.h
@@ -87,13 +87,20 @@
 
 // HMAC_CTX_init initialises |ctx| for use in an HMAC operation. It's assumed
 // that HMAC_CTX objects will be allocated on the stack thus no allocation
-// function is provided. If needed, allocate |sizeof(HMAC_CTX)| and call
-// |HMAC_CTX_init| on it.
+// function is provided.
 OPENSSL_EXPORT void HMAC_CTX_init(HMAC_CTX *ctx);
 
-// HMAC_CTX_cleanup frees data owned by |ctx|.
+// HMAC_CTX_new allocates and initialises a new |HMAC_CTX| and returns it, or
+// NULL on allocation failure. The caller must use |HMAC_CTX_free| to release
+// the resulting object.
+OPENSSL_EXPORT HMAC_CTX *HMAC_CTX_new(void);
+
+// HMAC_CTX_cleanup frees data owned by |ctx|. It does not free |ctx| itself.
 OPENSSL_EXPORT void HMAC_CTX_cleanup(HMAC_CTX *ctx);
 
+// HMAC_CTX_free calls |HMAC_CTX_cleanup| and then frees |ctx| itself.
+OPENSSL_EXPORT void HMAC_CTX_free(HMAC_CTX *ctx);
+
 // HMAC_Init_ex sets up an initialised |HMAC_CTX| to use |md| as the hash
 // function and |key| as the key. For a non-initial call, |md| may be NULL, in
 // which case the previous hash function will be used. If the hash function has
@@ -131,6 +138,9 @@
 // on error.
 OPENSSL_EXPORT int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src);
 
+// HMAC_CTX_reset calls |HMAC_CTX_cleanup| followed by |HMAC_CTX_init|.
+OPENSSL_EXPORT void HMAC_CTX_reset(HMAC_CTX *ctx);
+
 
 // Deprecated functions.
 
@@ -161,6 +171,8 @@
 
 namespace bssl {
 
+BORINGSSL_MAKE_DELETER(HMAC_CTX, HMAC_CTX_free)
+
 using ScopedHMAC_CTX =
     internal::StackAllocated<HMAC_CTX, void, HMAC_CTX_init, HMAC_CTX_cleanup>;
 
diff --git a/src/include/openssl/obj.h b/src/include/openssl/obj.h
index ae1a4ec..2bdc3b7 100644
--- a/src/include/openssl/obj.h
+++ b/src/include/openssl/obj.h
@@ -91,6 +91,12 @@
 // less than, equal to or greater than |b|, respectively.
 OPENSSL_EXPORT int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b);
 
+// OBJ_get0_data returns a pointer to the DER representation of |obj|.
+OPENSSL_EXPORT const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj);
+
+// OBJ_length returns the length of the DER representation of |obj|.
+OPENSSL_EXPORT size_t OBJ_length(const ASN1_OBJECT *obj);
+
 
 // Looking up nids.
 
diff --git a/src/include/openssl/opensslconf.h b/src/include/openssl/opensslconf.h
index db409d9..3c6ffd8 100644
--- a/src/include/openssl/opensslconf.h
+++ b/src/include/openssl/opensslconf.h
@@ -19,18 +19,23 @@
 #define OPENSSL_HEADER_OPENSSLCONF_H
 
 
+#define OPENSSL_NO_ASYNC
 #define OPENSSL_NO_BF
+#define OPENSSL_NO_BLAKE2
 #define OPENSSL_NO_BUF_FREELISTS
 #define OPENSSL_NO_CAMELLIA
 #define OPENSSL_NO_CAPIENG
 #define OPENSSL_NO_CAST
 #define OPENSSL_NO_CMS
 #define OPENSSL_NO_COMP
+#define OPENSSL_NO_CT
 #define OPENSSL_NO_DANE
 #define OPENSSL_NO_DEPRECATED
+#define OPENSSL_NO_DGRAM
 #define OPENSSL_NO_DYNAMIC_ENGINE
 #define OPENSSL_NO_EC_NISTP_64_GCC_128
 #define OPENSSL_NO_EC2M
+#define OPENSSL_NO_EGD
 #define OPENSSL_NO_ENGINE
 #define OPENSSL_NO_GMP
 #define OPENSSL_NO_GOST
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index d463f85..3f45318 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -108,6 +108,29 @@
                                         const BIGNUM **out_dmq1,
                                         const BIGNUM **out_iqmp);
 
+// RSA_set0_key sets |rsa|'s modulus, public exponent, and private exponent to
+// |n|, |e|, and |d| respectively, if non-NULL. On success, it takes ownership
+// of each argument and returns one. Otherwise, it returns zero.
+//
+// |d| may be NULL, but |n| and |e| must either be non-NULL or already
+// configured on |rsa|.
+OPENSSL_EXPORT int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+
+// RSA_set0_factors sets |rsa|'s prime factors to |p| and |q|, if non-NULL, and
+// takes ownership of them. On success, it takes ownership of each argument and
+// returns one. Otherwise, it returns zero.
+//
+// Each argument must either be non-NULL or already configured on |rsa|.
+OPENSSL_EXPORT int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q);
+
+// RSA_set0_crt_params sets |rsa|'s CRT parameters to |dmp1|, |dmq1|, and
+// |iqmp|, if non-NULL, and takes ownership of them. On success, it takes
+// ownership of its parameters and returns one. Otherwise, it returns zero.
+//
+// Each argument must either be non-NULL or already configured on |rsa|.
+OPENSSL_EXPORT int RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1,
+                                       BIGNUM *iqmp);
+
 
 // Key generation.
 
diff --git a/src/include/openssl/span.h b/src/include/openssl/span.h
index 08c4518..d447314 100644
--- a/src/include/openssl/span.h
+++ b/src/include/openssl/span.h
@@ -92,13 +92,15 @@
 template <typename T>
 class Span : private internal::SpanBase<const T> {
  private:
-  template <bool B, class V = void>
-  using enable_if_t = typename std::enable_if<B, V>::type;
-
   // Heuristically test whether C is a container type that can be converted into
   // a Span by checking for data() and size() member functions.
+  //
+  // TODO(davidben): Switch everything to std::enable_if_t when we remove
+  // support for MSVC 2015. Although we could write our own enable_if_t and MSVC
+  // 2015 has std::enable_if_t anyway, MSVC 2015's SFINAE implementation is
+  // problematic and does not work below unless we write the ::type at use.
   template <typename C>
-  using EnableIfContainer = enable_if_t<
+  using EnableIfContainer = std::enable_if<
       std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
       std::is_integral<decltype(std::declval<C>().size())>::value>;
 
@@ -109,12 +111,14 @@
   template <size_t N>
   constexpr Span(T (&array)[N]) : Span(array, N) {}
 
-  template <typename C, typename = EnableIfContainer<C>,
-            typename = enable_if_t<std::is_const<T>::value, C>>
+  template <
+      typename C, typename = typename EnableIfContainer<C>::type,
+      typename = typename std::enable_if<std::is_const<T>::value, C>::type>
   Span(const C &container) : data_(container.data()), size_(container.size()) {}
 
-  template <typename C, typename = EnableIfContainer<C>,
-            typename = enable_if_t<!std::is_const<T>::value, C>>
+  template <
+      typename C, typename = typename EnableIfContainer<C>::type,
+      typename = typename std::enable_if<!std::is_const<T>::value, C>::type>
   explicit Span(C &container)
       : data_(container.data()), size_(container.size()) {}
 
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index d6f6149..a85fc9c 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -1074,11 +1074,20 @@
 OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,
                                                   pem_password_cb *cb);
 
+// SSL_CTX_get_default_passwd_cb returns the callback set by
+// |SSL_CTX_set_default_passwd_cb|.
+OPENSSL_EXPORT pem_password_cb *SSL_CTX_get_default_passwd_cb(
+    const SSL_CTX *ctx);
+
 // SSL_CTX_set_default_passwd_cb_userdata sets the userdata parameter for
 // |ctx|'s password callback.
 OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,
                                                            void *data);
 
+// SSL_CTX_get_default_passwd_cb_userdata returns the userdata parameter set by
+// |SSL_CTX_set_default_passwd_cb_userdata|.
+OPENSSL_EXPORT void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx);
+
 
 // Custom private keys.
 
@@ -1709,6 +1718,35 @@
                                                const uint8_t *sid_ctx,
                                                size_t sid_ctx_len);
 
+// SSL_SESSION_should_be_single_use returns one if |session| should be
+// single-use (TLS 1.3 and later) and zero otherwise.
+//
+// If this function returns one, clients retain multiple sessions and use each
+// only once. This prevents passive observers from correlating connections with
+// tickets. See draft-ietf-tls-tls13-18, appendix B.5. If it returns zero,
+// |session| cannot be used without leaking a correlator.
+OPENSSL_EXPORT int SSL_SESSION_should_be_single_use(const SSL_SESSION *session);
+
+// SSL_SESSION_is_resumable returns one if |session| is resumable and zero
+// otherwise.
+OPENSSL_EXPORT int SSL_SESSION_is_resumable(const SSL_SESSION *session);
+
+// SSL_SESSION_has_ticket returns one if |session| has a ticket and zero
+// otherwise.
+OPENSSL_EXPORT int SSL_SESSION_has_ticket(const SSL_SESSION *session);
+
+// SSL_SESSION_get0_ticket sets |*out_ticket| and |*out_len| to |session|'s
+// ticket, or NULL and zero if it does not have one. |out_ticket| may be NULL
+// if only the ticket length is needed.
+OPENSSL_EXPORT void SSL_SESSION_get0_ticket(const SSL_SESSION *session,
+                                            const uint8_t **out_ticket,
+                                            size_t *out_len);
+
+// SSL_SESSION_get_ticket_lifetime_hint returns ticket lifetime hint of
+// |session| in seconds or zero if none was set.
+OPENSSL_EXPORT uint32_t
+SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
+
 
 // Session caching.
 //
@@ -1745,6 +1783,12 @@
 // e.g., different cipher suite settings or client certificates should also use
 // separate session caches between those contexts. Servers should also partition
 // session caches between SNI hosts with |SSL_CTX_set_session_id_context|.
+//
+// Note also, in TLS 1.2 and earlier, offering sessions allows passive observers
+// to correlate different client connections. TLS 1.3 and later fix this,
+// provided clients use sessions at most once. Session caches are managed by the
+// caller in BoringSSL, so this must be implemented externally. See
+// |SSL_SESSION_should_be_single_use| for details.
 
 // SSL_SESS_CACHE_OFF disables all session caching.
 #define SSL_SESS_CACHE_OFF 0x0000
@@ -1854,9 +1898,6 @@
 // session cache.
 OPENSSL_EXPORT unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx);
 
-// SSL_CTX_sessions returns |ctx|'s internal session cache.
-OPENSSL_EXPORT LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
-
 // SSL_CTX_sess_number returns the number of sessions in |ctx|'s internal
 // session cache.
 OPENSSL_EXPORT size_t SSL_CTX_sess_number(const SSL_CTX *ctx);
@@ -1933,18 +1974,14 @@
 //
 // If the internal session cache is enabled, the callback is only consulted if
 // the internal cache does not return a match.
-//
-// The callback's |id| parameter is not const for historical reasons, but the
-// contents may not be modified.
 OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
-    SSL_CTX *ctx,
-    SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *id, int id_len,
-                                   int *out_copy));
+    SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(SSL *ssl, const uint8_t *id,
+                                                 int id_len, int *out_copy));
 
 // SSL_CTX_sess_get_get_cb returns the callback set by
 // |SSL_CTX_sess_set_get_cb|.
 OPENSSL_EXPORT SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
-    SSL *ssl, uint8_t *id, int id_len, int *out_copy);
+    SSL *ssl, const uint8_t *id, int id_len, int *out_copy);
 
 // SSL_magic_pending_session_ptr returns a magic |SSL_SESSION|* which indicates
 // that the session isn't currently unavailable. |SSL_get_error| will then
@@ -3973,6 +4010,24 @@
 // the session.
 OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
 
+#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0
+#define OPENSSL_INIT_LOAD_SSL_STRINGS 0
+#define OPENSSL_INIT_SSL_DEFAULT 0
+
+// OPENSSL_init_ssl calls |CRYPTO_library_init| and returns one.
+OPENSSL_EXPORT int OPENSSL_init_ssl(uint64_t opts,
+                                    const OPENSSL_INIT_SETTINGS *settings);
+
+#if !defined(BORINGSSL_NO_CXX)
+// SSL_CTX_sess_set_get_cb is a legacy C++ overload of |SSL_CTX_sess_set_get_cb|
+// which supports the old callback signature.
+//
+// TODO(davidben): Remove this once Node is compatible with OpenSSL 1.1.0.
+extern "C++" OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
+    SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *id,
+                                                 int id_len, int *out_copy));
+#endif
+
 
 // Private structures.
 //
@@ -4221,8 +4276,10 @@
   // it.
   int (*new_session_cb)(SSL *ssl, SSL_SESSION *sess);
   void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *sess);
-  SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *data, int len,
+  SSL_SESSION *(*get_session_cb)(SSL *ssl, const uint8_t *data, int len,
                                  int *copy);
+  SSL_SESSION *(*get_session_cb_legacy)(SSL *ssl, uint8_t *data, int len,
+                                        int *copy);
 
   CRYPTO_refcount_t references;
 
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index 62bd5f8..7db9466 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -575,7 +575,8 @@
 OPENSSL_EXPORT int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
 
 OPENSSL_EXPORT int X509_signature_dump(BIO *bp,const ASN1_STRING *sig, int indent);
-OPENSSL_EXPORT int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
+OPENSSL_EXPORT int X509_signature_print(BIO *bp, const X509_ALGOR *alg,
+                                        const ASN1_STRING *sig);
 
 OPENSSL_EXPORT int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
 OPENSSL_EXPORT int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
@@ -686,6 +687,7 @@
 
 OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn);
 OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+OPENSSL_EXPORT int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne);
 
 OPENSSL_EXPORT int		X509_cmp_time(const ASN1_TIME *s, time_t *t);
 OPENSSL_EXPORT int		X509_cmp_current_time(const ASN1_TIME *s);
@@ -756,8 +758,8 @@
 OPENSSL_EXPORT int		i2d_X509_AUX(X509 *a,unsigned char **pp);
 OPENSSL_EXPORT X509 *		d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
 
-OPENSSL_EXPORT void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
-								const X509 *x);
+OPENSSL_EXPORT void X509_get0_signature(const ASN1_BIT_STRING **psig,
+                                        const X509_ALGOR **palg, const X509 *x);
 OPENSSL_EXPORT int X509_get_signature_nid(const X509 *x);
 
 OPENSSL_EXPORT int X509_alias_set1(X509 *x, unsigned char *name, int len);
@@ -816,7 +818,9 @@
 OPENSSL_EXPORT int 		X509_set_subject_name(X509 *x, X509_NAME *name);
 OPENSSL_EXPORT X509_NAME *	X509_get_subject_name(X509 *a);
 OPENSSL_EXPORT int 		X509_set_notBefore(X509 *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT const ASN1_TIME *X509_get0_notBefore(const X509 *x);
 OPENSSL_EXPORT int 		X509_set_notAfter(X509 *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT const ASN1_TIME *X509_get0_notAfter(const X509 *x);
 OPENSSL_EXPORT int 		X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
 OPENSSL_EXPORT EVP_PKEY *	X509_get_pubkey(X509 *x);
 OPENSSL_EXPORT ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
diff --git a/src/include/openssl/x509_vfy.h b/src/include/openssl/x509_vfy.h
index 4abd9cd..991cbda 100644
--- a/src/include/openssl/x509_vfy.h
+++ b/src/include/openssl/x509_vfy.h
@@ -423,16 +423,20 @@
 OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
 OPENSSL_EXPORT int X509_OBJECT_up_ref_count(X509_OBJECT *a);
 OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a);
+OPENSSL_EXPORT int X509_OBJECT_get_type(const X509_OBJECT *a);
+OPENSSL_EXPORT X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a);
 OPENSSL_EXPORT X509_STORE *X509_STORE_new(void );
 OPENSSL_EXPORT int X509_STORE_up_ref(X509_STORE *store);
 OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v);
 
+OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st);
 OPENSSL_EXPORT STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
 OPENSSL_EXPORT STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm);
 OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
 OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
 OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *ctx, int trust);
 OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx);
 /* X509_STORE_set0_additional_untrusted sets a stack of additional, untrusted
  * certificates that are available for chain building. This function does not
  * take ownership of the stack. */
@@ -513,6 +517,8 @@
 OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
 OPENSSL_EXPORT void	X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
 OPENSSL_EXPORT void	X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
+OPENSSL_EXPORT STACK_OF(X509) *
+    X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx);
 OPENSSL_EXPORT void	X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk);
 OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
 OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index ab499df..c2f6479 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -535,19 +535,17 @@
   return 1;
 }
 
-int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
-                         size_t *out_len) {
-  *out_msg = NULL;
-  if (!CBB_finish(cbb, out_msg, out_len) ||
-      *out_len < DTLS1_HM_HEADER_LENGTH) {
+int dtls1_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg) {
+  if (!CBBFinishArray(cbb, out_msg) ||
+      out_msg->size() < DTLS1_HM_HEADER_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    OPENSSL_free(*out_msg);
     return 0;
   }
 
   // Fix up the header. Copy the fragment length into the total message
   // length.
-  OPENSSL_memcpy(*out_msg + 1, *out_msg + DTLS1_HM_HEADER_LENGTH - 3, 3);
+  OPENSSL_memcpy(out_msg->data() + 1,
+                 out_msg->data() + DTLS1_HM_HEADER_LENGTH - 3, 3);
   return 1;
 }
 
@@ -555,7 +553,7 @@
 // outgoing flight. It returns one on success and zero on error. In both cases,
 // it takes ownership of |data| and releases it with |OPENSSL_free| when
 // done.
-static int add_outgoing(SSL *ssl, int is_ccs, uint8_t *data, size_t len) {
+static int add_outgoing(SSL *ssl, int is_ccs, Array<uint8_t> data) {
   if (ssl->d1->outgoing_messages_complete) {
     // If we've begun writing a new flight, we received the peer flight. Discard
     // the timer and the our flight.
@@ -566,10 +564,10 @@
   static_assert(SSL_MAX_HANDSHAKE_FLIGHT <
                     (1 << 8 * sizeof(ssl->d1->outgoing_messages_len)),
                 "outgoing_messages_len is too small");
-  if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT) {
+  if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT ||
+      data.size() > 0xffffffff) {
     assert(0);
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    OPENSSL_free(data);
     return 0;
   }
 
@@ -577,9 +575,8 @@
     // TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript
     // on hs.
     if (ssl->s3->hs != NULL &&
-        !ssl->s3->hs->transcript.Update(data, len)) {
+        !ssl->s3->hs->transcript.Update(data.data(), data.size())) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      OPENSSL_free(data);
       return 0;
     }
     ssl->d1->handshake_write_seq++;
@@ -587,7 +584,8 @@
 
   DTLS_OUTGOING_MESSAGE *msg =
       &ssl->d1->outgoing_messages[ssl->d1->outgoing_messages_len];
-  msg->data = data;
+  size_t len;
+  data.Release(&msg->data, &len);
   msg->len = len;
   msg->epoch = ssl->d1->w_epoch;
   msg->is_ccs = is_ccs;
@@ -596,12 +594,12 @@
   return 1;
 }
 
-int dtls1_add_message(SSL *ssl, uint8_t *data, size_t len) {
-  return add_outgoing(ssl, 0 /* handshake */, data, len);
+int dtls1_add_message(SSL *ssl, Array<uint8_t> data) {
+  return add_outgoing(ssl, 0 /* handshake */, std::move(data));
 }
 
 int dtls1_add_change_cipher_spec(SSL *ssl) {
-  return add_outgoing(ssl, 1 /* ChangeCipherSpec */, NULL, 0);
+  return add_outgoing(ssl, 1 /* ChangeCipherSpec */, Array<uint8_t>());
 }
 
 int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc) {
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 6746582..c10c40f 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -114,6 +114,8 @@
 
 #include <assert.h>
 
+#include <utility>
+
 #include "../crypto/internal.h"
 #include "internal.h"
 
@@ -144,15 +146,7 @@
 }
 
 SSL_HANDSHAKE::~SSL_HANDSHAKE() {
-  OPENSSL_free(cookie);
-  OPENSSL_free(key_share_bytes);
-  OPENSSL_free(ecdh_public_key);
-  OPENSSL_free(peer_sigalgs);
-  OPENSSL_free(peer_supported_group_list);
-  OPENSSL_free(peer_key);
-  OPENSSL_free(server_params);
   ssl->ctx->x509_method->hs_flush_cached_ca_names(this);
-  OPENSSL_free(certificate_types);
   OPENSSL_free(key_block);
 }
 
@@ -179,10 +173,9 @@
 }
 
 int ssl_add_message_cbb(SSL *ssl, CBB *cbb) {
-  uint8_t *msg;
-  size_t len;
-  if (!ssl->method->finish_message(ssl, cbb, &msg, &len) ||
-      !ssl->method->add_message(ssl, msg, len)) {
+  Array<uint8_t> msg;
+  if (!ssl->method->finish_message(ssl, cbb, &msg) ||
+      !ssl->method->add_message(ssl, std::move(msg))) {
     return 0;
   }
 
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 3916692..b2d5384 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -338,21 +338,19 @@
     return 0;
   }
 
-  uint8_t *msg = NULL;
-  size_t len;
-  if (!ssl->method->finish_message(ssl, cbb.get(), &msg, &len)) {
+  Array<uint8_t> msg;
+  if (!ssl->method->finish_message(ssl, cbb.get(), &msg)) {
     return 0;
   }
 
   // Now that the length prefixes have been computed, fill in the placeholder
   // PSK binder.
   if (hs->needs_psk_binder &&
-      !tls13_write_psk_binder(hs, msg, len)) {
-    OPENSSL_free(msg);
+      !tls13_write_psk_binder(hs, msg.data(), msg.size())) {
     return 0;
   }
 
-  return ssl->method->add_message(ssl, msg, len);
+  return ssl->method->add_message(ssl, std::move(msg));
 }
 
 static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out,
@@ -602,14 +600,19 @@
     return ssl_hs_ok;
   }
 
+  // Clear some TLS 1.3 state that no longer needs to be retained.
+  hs->key_share.reset();
+  hs->key_share_bytes.Reset();
+
+  // A TLS 1.2 server would not know to skip the early data we offered. Report
+  // an error code sooner. The caller may use this error code to implement the
+  // fallback described in draft-ietf-tls-tls13-18 appendix C.3.
   if (hs->early_data_offered) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_ON_EARLY_DATA);
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
     return ssl_hs_error;
   }
 
-  ssl_clear_tls13_state(hs);
-
   if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
     return ssl_hs_error;
   }
@@ -977,7 +980,7 @@
     // Initialize ECDH and save the peer public key for later.
     hs->key_share = SSLKeyShare::Create(group_id);
     if (!hs->key_share ||
-        !CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
+        !hs->peer_key.CopyFrom(point)) {
       return ssl_hs_error;
     }
   } else if (!(alg_k & SSL_kPSK)) {
@@ -1106,8 +1109,7 @@
     return ssl_hs_error;
   }
 
-  if (!CBS_stow(&certificate_types, &hs->certificate_types,
-                &hs->num_certificate_types)) {
+  if (!hs->certificate_types.CopyFrom(certificate_types)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return ssl_hs_error;
   }
@@ -1229,8 +1231,7 @@
     return ssl_hs_error;
   }
 
-  uint8_t *pms = NULL;
-  size_t pms_len = 0;
+  Array<uint8_t> pms;
   uint32_t alg_k = hs->new_cipher->algorithm_mkey;
   uint32_t alg_a = hs->new_cipher->algorithm_auth;
 
@@ -1240,7 +1241,7 @@
   if (alg_a & SSL_aPSK) {
     if (ssl->psk_client_callback == NULL) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
-      goto err;
+      return ssl_hs_error;
     }
 
     char identity[PSK_MAX_IDENTITY_LEN + 1];
@@ -1251,7 +1252,7 @@
     if (psk_len == 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-      goto err;
+      return ssl_hs_error;
     }
     assert(psk_len <= PSK_MAX_PSK_LEN);
 
@@ -1259,7 +1260,7 @@
     hs->new_session->psk_identity = BUF_strdup(identity);
     if (hs->new_session->psk_identity == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return ssl_hs_error;
     }
 
     // Write out psk_identity.
@@ -1268,29 +1269,26 @@
         !CBB_add_bytes(&child, (const uint8_t *)identity,
                        OPENSSL_strnlen(identity, sizeof(identity))) ||
         !CBB_flush(&body)) {
-      goto err;
+      return ssl_hs_error;
     }
   }
 
-  // Depending on the key exchange method, compute |pms| and |pms_len|.
+  // Depending on the key exchange method, compute |pms|.
   if (alg_k & SSL_kRSA) {
-    pms_len = SSL_MAX_MASTER_KEY_LENGTH;
-    pms = (uint8_t *)OPENSSL_malloc(pms_len);
-    if (pms == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+    if (!pms.Init(SSL_MAX_MASTER_KEY_LENGTH)) {
+      return ssl_hs_error;
     }
 
     RSA *rsa = EVP_PKEY_get0_RSA(hs->peer_pubkey.get());
     if (rsa == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
 
     pms[0] = hs->client_version >> 8;
     pms[1] = hs->client_version & 0xff;
     if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
-      goto err;
+      return ssl_hs_error;
     }
 
     CBB child, *enc_pms = &body;
@@ -1298,56 +1296,50 @@
     // In TLS, there is a length prefix.
     if (ssl->version > SSL3_VERSION) {
       if (!CBB_add_u16_length_prefixed(&body, &child)) {
-        goto err;
+        return ssl_hs_error;
       }
       enc_pms = &child;
     }
 
     uint8_t *ptr;
     if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
-        !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
-                     RSA_PKCS1_PADDING) ||
+        !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms.data(),
+                     pms.size(), RSA_PKCS1_PADDING) ||
         !CBB_did_write(enc_pms, enc_pms_len) ||
         !CBB_flush(&body)) {
-      goto err;
+      return ssl_hs_error;
     }
   } else if (alg_k & SSL_kECDHE) {
     // Generate a keypair and serialize the public half.
     CBB child;
     if (!CBB_add_u8_length_prefixed(&body, &child)) {
-      goto err;
+      return ssl_hs_error;
     }
 
     // Compute the premaster.
     uint8_t alert = SSL_AD_DECODE_ERROR;
-    if (!hs->key_share->Accept(&child, &pms, &pms_len, &alert, hs->peer_key,
-                              hs->peer_key_len)) {
+    if (!hs->key_share->Accept(&child, &pms, &alert, hs->peer_key)) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
-      goto err;
+      return ssl_hs_error;
     }
     if (!CBB_flush(&body)) {
-      goto err;
+      return ssl_hs_error;
     }
 
     // The key exchange state may now be discarded.
     hs->key_share.reset();
-    OPENSSL_free(hs->peer_key);
-    hs->peer_key = NULL;
-    hs->peer_key_len = 0;
+    hs->peer_key.Reset();
   } else if (alg_k & SSL_kPSK) {
     // For plain PSK, other_secret is a block of 0s with the same length as
     // the pre-shared key.
-    pms_len = psk_len;
-    pms = (uint8_t *)OPENSSL_malloc(pms_len);
-    if (pms == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+    if (!pms.Init(psk_len)) {
+      return ssl_hs_error;
     }
-    OPENSSL_memset(pms, 0, pms_len);
+    OPENSSL_memset(pms.data(), 0, pms.size());
   } else {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    goto err;
+    return ssl_hs_error;
   }
 
   // For a PSK cipher suite, other_secret is combined with the pre-shared
@@ -1358,40 +1350,33 @@
     uint8_t *new_pms;
     size_t new_pms_len;
 
-    if (!CBB_init(pms_cbb.get(), 2 + psk_len + 2 + pms_len) ||
+    if (!CBB_init(pms_cbb.get(), 2 + psk_len + 2 + pms.size()) ||
         !CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
-        !CBB_add_bytes(&child, pms, pms_len) ||
+        !CBB_add_bytes(&child, pms.data(), pms.size()) ||
         !CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
         !CBB_add_bytes(&child, psk, psk_len) ||
         !CBB_finish(pms_cbb.get(), &new_pms, &new_pms_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return ssl_hs_error;
     }
-    OPENSSL_free(pms);
-    pms = new_pms;
-    pms_len = new_pms_len;
+    pms.Reset(new_pms, new_pms_len);
   }
 
   // The message must be added to the finished hash before calculating the
   // master secret.
   if (!ssl_add_message_cbb(ssl, cbb.get())) {
-    goto err;
+    return ssl_hs_error;
   }
 
   hs->new_session->master_key_length = tls1_generate_master_secret(
-      hs, hs->new_session->master_key, pms, pms_len);
+      hs, hs->new_session->master_key, pms.data(), pms.size());
   if (hs->new_session->master_key_length == 0) {
-    goto err;
+    return ssl_hs_error;
   }
   hs->new_session->extended_master_secret = hs->extended_master_secret;
-  OPENSSL_free(pms);
 
   hs->state = state_send_client_certificate_verify;
   return ssl_hs_ok;
-
-err:
-  OPENSSL_free(pms);
-  return ssl_hs_error;
 }
 
 static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index a38e25f..5507250 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -818,7 +818,7 @@
       assert(alg_k & SSL_kPSK);
     }
 
-    if (!CBB_finish(cbb.get(), &hs->server_params, &hs->server_params_len)) {
+    if (!CBBFinishArray(cbb.get(), &hs->server_params)) {
       return ssl_hs_error;
     }
   }
@@ -830,7 +830,7 @@
 static enum ssl_hs_wait_t do_send_server_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
 
-  if (hs->server_params_len == 0) {
+  if (hs->server_params.size() == 0) {
     hs->state = state_send_server_hello_done;
     return ssl_hs_ok;
   }
@@ -840,9 +840,9 @@
   if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_SERVER_KEY_EXCHANGE) ||
       // |hs->server_params| contains a prefix for signing.
-      hs->server_params_len < 2 * SSL3_RANDOM_SIZE ||
-      !CBB_add_bytes(&body, hs->server_params + 2 * SSL3_RANDOM_SIZE,
-                     hs->server_params_len - 2 * SSL3_RANDOM_SIZE)) {
+      hs->server_params.size() < 2 * SSL3_RANDOM_SIZE ||
+      !CBB_add_bytes(&body, hs->server_params.data() + 2 * SSL3_RANDOM_SIZE,
+                     hs->server_params.size() - 2 * SSL3_RANDOM_SIZE)) {
     return ssl_hs_error;
   }
 
@@ -876,8 +876,8 @@
 
     size_t sig_len;
     switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
-                                 signature_algorithm, hs->server_params,
-                                 hs->server_params_len)) {
+                                 signature_algorithm, hs->server_params.data(),
+                                 hs->server_params.size())) {
       case ssl_private_key_success:
         if (!CBB_did_write(&child, sig_len)) {
           return ssl_hs_error;
@@ -894,9 +894,7 @@
     return ssl_hs_error;
   }
 
-  OPENSSL_free(hs->server_params);
-  hs->server_params = NULL;
-  hs->server_params_len = 0;
+  hs->server_params.Reset();
 
   hs->state = state_send_server_hello_done;
   return ssl_hs_ok;
@@ -1048,12 +1046,6 @@
 
 static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-
-  ssl_hs_wait_t ret = ssl_hs_error;
-  uint8_t *premaster_secret = NULL;
-  size_t premaster_secret_len = 0;
-  uint8_t *decrypt_buf = NULL;
-
   SSLMessage msg;
   if (!ssl->method->get_message(ssl, &msg)) {
     return ssl_hs_read_message;
@@ -1077,25 +1069,25 @@
         ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
 
     if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
         CBS_contains_zero_byte(&psk_identity)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-      goto err;
+      return ssl_hs_error;
     }
 
     if (!CBS_strdup(&psk_identity, &hs->new_session->psk_identity)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
   }
 
-  // Depending on the key exchange method, compute |premaster_secret| and
-  // |premaster_secret_len|.
+  // Depending on the key exchange method, compute |premaster_secret|.
+  Array<uint8_t> premaster_secret;
   if (alg_k & SSL_kRSA) {
     CBS encrypted_premaster_secret;
     if (ssl->version > SSL3_VERSION) {
@@ -1104,63 +1096,56 @@
           CBS_len(&client_key_exchange) != 0) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-        goto err;
+        return ssl_hs_error;
       }
     } else {
       encrypted_premaster_secret = client_key_exchange;
     }
 
     // Allocate a buffer large enough for an RSA decryption.
-    const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey.get());
-    decrypt_buf = (uint8_t *)OPENSSL_malloc(rsa_size);
-    if (decrypt_buf == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+    Array<uint8_t> decrypt_buf;
+    if (!decrypt_buf.Init(EVP_PKEY_size(hs->local_pubkey.get()))) {
+      return ssl_hs_error;
     }
 
     // Decrypt with no padding. PKCS#1 padding will be removed as part of the
     // timing-sensitive code below.
     size_t decrypt_len;
-    switch (ssl_private_key_decrypt(hs, decrypt_buf, &decrypt_len, rsa_size,
+    switch (ssl_private_key_decrypt(hs, decrypt_buf.data(), &decrypt_len,
+                                    decrypt_buf.size(),
                                     CBS_data(&encrypted_premaster_secret),
                                     CBS_len(&encrypted_premaster_secret))) {
       case ssl_private_key_success:
         break;
       case ssl_private_key_failure:
-        goto err;
+        return ssl_hs_error;
       case ssl_private_key_retry:
-        ret = ssl_hs_private_key_operation;
-        goto err;
+        return ssl_hs_private_key_operation;
     }
 
-    if (decrypt_len != rsa_size) {
+    if (decrypt_len != decrypt_buf.size()) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
 
     // Prepare a random premaster, to be used on invalid padding. See RFC 5246,
     // section 7.4.7.1.
-    premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
-    premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len);
-    if (premaster_secret == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    if (!RAND_bytes(premaster_secret, premaster_secret_len)) {
-      goto err;
+    if (!premaster_secret.Init(SSL_MAX_MASTER_KEY_LENGTH) ||
+        !RAND_bytes(premaster_secret.data(), premaster_secret.size())) {
+      return ssl_hs_error;
     }
 
     // The smallest padded premaster is 11 bytes of overhead. Small keys are
     // publicly invalid.
-    if (decrypt_len < 11 + premaster_secret_len) {
+    if (decrypt_len < 11 + premaster_secret.size()) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
 
     // Check the padding. See RFC 3447, section 7.2.2.
-    size_t padding_len = decrypt_len - premaster_secret_len;
+    size_t padding_len = decrypt_len - premaster_secret.size();
     uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
                    constant_time_eq_int_8(decrypt_buf[1], 2);
     for (size_t i = 2; i < padding_len - 1; i++) {
@@ -1177,13 +1162,10 @@
 
     // Select, in constant time, either the decrypted premaster or the random
     // premaster based on |good|.
-    for (size_t i = 0; i < premaster_secret_len; i++) {
+    for (size_t i = 0; i < premaster_secret.size(); i++) {
       premaster_secret[i] = constant_time_select_8(
           good, decrypt_buf[padding_len + i], premaster_secret[i]);
     }
-
-    OPENSSL_free(decrypt_buf);
-    decrypt_buf = NULL;
   } else if (alg_k & SSL_kECDHE) {
     // Parse the ClientKeyExchange.
     CBS peer_key;
@@ -1191,15 +1173,14 @@
         CBS_len(&client_key_exchange) != 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
 
     // Compute the premaster.
     uint8_t alert = SSL_AD_DECODE_ERROR;
-    if (!hs->key_share->Finish(&premaster_secret, &premaster_secret_len, &alert,
-                               CBS_data(&peer_key), CBS_len(&peer_key))) {
+    if (!hs->key_share->Finish(&premaster_secret, &alert, peer_key)) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
-      goto err;
+      return ssl_hs_error;
     }
 
     // The key exchange state may now be discarded.
@@ -1207,7 +1188,7 @@
   } else if (!(alg_k & SSL_kPSK)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-    goto err;
+    return ssl_hs_error;
   }
 
   // For a PSK cipher suite, the actual pre-master secret is combined with the
@@ -1216,7 +1197,7 @@
     if (ssl->psk_server_callback == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
+      return ssl_hs_error;
     }
 
     // Look up the key for the identity.
@@ -1226,24 +1207,21 @@
     if (psk_len > PSK_MAX_PSK_LEN) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
+      return ssl_hs_error;
     } else if (psk_len == 0) {
       // PSK related to the given identity not found.
       OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_PSK_IDENTITY);
-      goto err;
+      return ssl_hs_error;
     }
 
     if (alg_k & SSL_kPSK) {
       // In plain PSK, other_secret is a block of 0s with the same length as the
       // pre-shared key.
-      premaster_secret_len = psk_len;
-      premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len);
-      if (premaster_secret == NULL) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-        goto err;
+      if (!premaster_secret.Init(psk_len)) {
+        return ssl_hs_error;
       }
-      OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
+      OPENSSL_memset(premaster_secret.data(), 0, premaster_secret.size());
     }
 
     ScopedCBB new_premaster;
@@ -1251,47 +1229,36 @@
     uint8_t *new_data;
     size_t new_len;
     if (!CBB_init(new_premaster.get(),
-                  2 + psk_len + 2 + premaster_secret_len) ||
+                  2 + psk_len + 2 + premaster_secret.size()) ||
         !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
-        !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
+        !CBB_add_bytes(&child, premaster_secret.data(),
+                       premaster_secret.size()) ||
         !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
         !CBB_add_bytes(&child, psk, psk_len) ||
         !CBB_finish(new_premaster.get(), &new_data, &new_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return ssl_hs_error;
     }
 
-    OPENSSL_cleanse(premaster_secret, premaster_secret_len);
-    OPENSSL_free(premaster_secret);
-    premaster_secret = new_data;
-    premaster_secret_len = new_len;
+    premaster_secret.Reset(new_data, new_len);
   }
 
   if (!ssl_hash_message(hs, msg)) {
-    goto err;
+    return ssl_hs_error;
   }
 
   // Compute the master secret.
   hs->new_session->master_key_length = tls1_generate_master_secret(
-      hs, hs->new_session->master_key, premaster_secret, premaster_secret_len);
+      hs, hs->new_session->master_key, premaster_secret.data(),
+      premaster_secret.size());
   if (hs->new_session->master_key_length == 0) {
-    goto err;
+    return ssl_hs_error;
   }
   hs->new_session->extended_master_secret = hs->extended_master_secret;
 
   ssl->method->next_message(ssl);
   hs->state = state_read_client_certificate_verify;
-  ret = ssl_hs_ok;
-
-err:
-  if (premaster_secret != NULL) {
-    OPENSSL_cleanse(premaster_secret, premaster_secret_len);
-    OPENSSL_free(premaster_secret);
-  }
-  OPENSSL_free(decrypt_buf);
-
-  return ret;
-
+  return ssl_hs_ok;
 }
 
 static enum ssl_hs_wait_t do_read_client_certificate_verify(SSL_HANDSHAKE *hs) {
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index d5500bb..13e6655 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -146,6 +146,7 @@
 
 #include <stdlib.h>
 
+#include <limits>
 #include <new>
 #include <type_traits>
 #include <utility>
@@ -154,8 +155,11 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 #include <openssl/ssl.h>
+#include <openssl/span.h>
 #include <openssl/stack.h>
 
+#include "../crypto/internal.h"
+
 
 #if defined(OPENSSL_WINDOWS)
 // Windows defines struct timeval in winsock2.h.
@@ -233,6 +237,103 @@
 #define PURE_VIRTUAL { abort(); }
 #endif
 
+// Array<T> is an owning array of elements of |T|.
+template <typename T>
+class Array {
+ public:
+  // Array's default constructor creates an empty array.
+  Array() {}
+  Array(const Array &) = delete;
+  Array(Array &&other) { *this = std::move(other); }
+
+  ~Array() { Reset(); }
+
+  Array &operator=(const Array &) = delete;
+  Array &operator=(Array &&other) {
+    Reset();
+    other.Release(&data_, &size_);
+    return *this;
+  }
+
+  const T *data() const { return data_; }
+  T *data() { return data_; }
+  size_t size() const { return size_; }
+
+  const T &operator[](size_t i) const { return data_[i]; }
+  T &operator[](size_t i) { return data_[i]; }
+
+  T *begin() { return data_; }
+  const T *cbegin() const { return data_; }
+  T *end() { return data_ + size_; }
+  const T *cend() const { return data_ + size_; }
+
+  void Reset() { Reset(nullptr, 0); }
+
+  // Reset releases the current contents of the array and takes ownership of the
+  // raw pointer supplied by the caller.
+  void Reset(T *new_data, size_t new_size) {
+    for (size_t i = 0; i < size_; i++) {
+      data_[i].~T();
+    }
+    OPENSSL_free(data_);
+    data_ = new_data;
+    size_ = new_size;
+  }
+
+  // Release releases ownership of the array to a raw pointer supplied by the
+  // caller.
+  void Release(T **out, size_t *out_size) {
+    *out = data_;
+    *out_size = size_;
+    data_ = nullptr;
+    size_ = 0;
+  }
+
+  // Init replaces the array with a newly-allocated array of |new_size|
+  // default-constructed copies of |T|. It returns true on success and false on
+  // error.
+  //
+  // Note that if |T| is a primitive type like |uint8_t|, it is uninitialized.
+  bool Init(size_t new_size) {
+    Reset();
+    if (new_size == 0) {
+      return true;
+    }
+
+    if (new_size > std::numeric_limits<size_t>::max() / sizeof(T)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+      return false;
+    }
+    data_ = reinterpret_cast<T*>(OPENSSL_malloc(new_size * sizeof(T)));
+    if (data_ == nullptr) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      return false;
+    }
+    size_ = new_size;
+    for (size_t i = 0; i < size_; i++) {
+      new (&data_[i]) T;
+    }
+    return true;
+  }
+
+  // CopyFrom replaces the array with a newly-allocated copy of |in|. It returns
+  // true on success and false on error.
+  bool CopyFrom(Span<const uint8_t> in) {
+    if (!Init(in.size())) {
+      return false;
+    }
+    OPENSSL_memcpy(data_, in.data(), in.size());
+    return true;
+  }
+
+ private:
+  T *data_ = nullptr;
+  size_t size_ = 0;
+};
+
+// CBBFinishArray behaves like |CBB_finish| but stores the result in an Array.
+bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out);
+
 
 // Protocol versions.
 //
@@ -839,30 +940,20 @@
 
   // Accept performs a key exchange against the |peer_key| generated by |offer|.
   // On success, it returns true, writes the public value to |out_public_key|,
-  // and sets |*out_secret| and |*out_secret_len| to a newly-allocated buffer
-  // containing the shared secret. The caller must release this buffer with
-  // |OPENSSL_free|. On failure, it returns false and sets |*out_alert| to an
-  // alert to send to the peer.
+  // and sets |*out_secret| the shared secret. On failure, it returns false and
+  // sets |*out_alert| to an alert to send to the peer.
   //
   // The default implementation calls |Offer| and then |Finish|, assuming a key
   // exchange protocol where the peers are symmetric.
-  //
-  // TODO(davidben): out_secret should be a smart pointer.
-  virtual bool Accept(CBB *out_public_key, uint8_t **out_secret,
-                      size_t *out_secret_len, uint8_t *out_alert,
-                      const uint8_t *peer_key, size_t peer_key_len);
+  virtual bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
+                      uint8_t *out_alert, Span<const uint8_t> peer_key);
 
   // Finish performs a key exchange against the |peer_key| generated by
-  // |Accept|. On success, it returns true and sets |*out_secret| and
-  // |*out_secret_len| to a newly-allocated buffer containing the shared
-  // secret. The caller must release this buffer with |OPENSSL_free|. On
-  // failure, it returns zero and sets |*out_alert| to an alert to send to the
-  // peer.
-  //
-  // TODO(davidben): out_secret should be a smart pointer.
-  virtual bool Finish(uint8_t **out_secret, size_t *out_secret_len,
-                      uint8_t *out_alert, const uint8_t *peer_key,
-                      size_t peer_key_len) PURE_VIRTUAL;
+  // |Accept|. On success, it returns true and sets |*out_secret| to the shared
+  // secret. On failure, it returns zero and sets |*out_alert| to an alert to
+  // send to the peer.
+  virtual bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+                      Span<const uint8_t> peer_key) PURE_VIRTUAL;
 };
 
 // ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
@@ -1208,41 +1299,33 @@
   SSLTranscript transcript;
 
   // cookie is the value of the cookie received from the server, if any.
-  uint8_t *cookie = nullptr;
-  size_t cookie_len = 0;
+  Array<uint8_t> cookie;
 
   // key_share_bytes is the value of the previously sent KeyShare extension by
   // the client in TLS 1.3.
-  uint8_t *key_share_bytes = nullptr;
-  size_t key_share_bytes_len = 0;
+  Array<uint8_t> key_share_bytes;
 
   // ecdh_public_key, for servers, is the key share to be sent to the client in
   // TLS 1.3.
-  uint8_t *ecdh_public_key = nullptr;
-  size_t ecdh_public_key_len = 0;
+  Array<uint8_t> ecdh_public_key;
 
   // peer_sigalgs are the signature algorithms that the peer supports. These are
   // taken from the contents of the signature algorithms extension for a server
   // or from the CertificateRequest for a client.
-  uint16_t *peer_sigalgs = nullptr;
-  // num_peer_sigalgs is the number of entries in |peer_sigalgs|.
-  size_t num_peer_sigalgs = 0;
+  Array<uint16_t> peer_sigalgs;
 
   // peer_supported_group_list contains the supported group IDs advertised by
   // the peer. This is only set on the server's end. The server does not
   // advertise this extension to the client.
-  uint16_t *peer_supported_group_list = nullptr;
-  size_t peer_supported_group_list_len = 0;
+  Array<uint16_t> peer_supported_group_list;
 
   // peer_key is the peer's ECDH key for a TLS 1.2 client.
-  uint8_t *peer_key = nullptr;
-  size_t peer_key_len = 0;
+  Array<uint8_t> peer_key;
 
   // server_params, in a TLS 1.2 server, stores the ServerKeyExchange
   // parameters. It has client and server randoms prepended for signing
   // convenience.
-  uint8_t *server_params = nullptr;
-  size_t server_params_len = 0;
+  Array<uint8_t> server_params;
 
   // peer_psk_identity_hint, on the client, is the psk_identity_hint sent by the
   // server when using a TLS 1.2 PSK key exchange.
@@ -1258,8 +1341,7 @@
 
   // certificate_types, on the client, contains the set of certificate types
   // received in a CertificateRequest message.
-  uint8_t *certificate_types = nullptr;
-  size_t num_certificate_types = 0;
+  Array<uint8_t> certificate_types;
 
   // local_pubkey is the public key we are authenticating as.
   UniquePtr<EVP_PKEY> local_pubkey;
@@ -1414,12 +1496,11 @@
 int tls13_add_finished(SSL_HANDSHAKE *hs);
 int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg);
 
-int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
-                                        size_t *out_secret_len,
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
+                                        Array<uint8_t> *out_secret,
                                         uint8_t *out_alert, CBS *contents);
 int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
-                                        uint8_t **out_secret,
-                                        size_t *out_secret_len,
+                                        Array<uint8_t> *out_secret,
                                         uint8_t *out_alert, CBS *contents);
 int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out);
 
@@ -1436,10 +1517,6 @@
 
 int ssl_write_client_hello(SSL_HANDSHAKE *hs);
 
-// ssl_clear_tls13_state releases client state only needed for TLS 1.3. It
-// should be called once the version is known to be TLS 1.2 or earlier.
-void ssl_clear_tls13_state(SSL_HANDSHAKE *hs);
-
 enum ssl_cert_verify_context_t {
   ssl_cert_verify_server,
   ssl_cert_verify_client,
@@ -1490,11 +1567,8 @@
 
 // ClientHello functions.
 
-// ssl_client_hello_init parses |msg| as a ClientHello and writes the result to
-// |*out|. It returns one on success and zero on error. This function is
-// exported for unit tests.
-OPENSSL_EXPORT int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
-                                         const SSLMessage &msg);
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+                          const SSLMessage &msg);
 
 int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
                                    CBS *out, uint16_t extension_type);
@@ -1502,10 +1576,6 @@
 int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
                                            uint16_t id);
 
-// ssl_is_probably_java returns true if |client_hello| looks like a Java
-// ClientHello and false otherwise. This function is exported for tests.
-OPENSSL_EXPORT bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello);
-
 
 // GREASE.
 
@@ -2234,16 +2304,15 @@
 void ssl3_free(SSL *ssl);
 
 int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
-int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
-int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int ssl3_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg);
+int ssl3_add_message(SSL *ssl, Array<uint8_t> msg);
 int ssl3_add_change_cipher_spec(SSL *ssl);
 int ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
 int ssl3_flush_flight(SSL *ssl);
 
 int dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
-int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
-                         size_t *out_len);
-int dtls1_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int dtls1_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg);
+int dtls1_add_message(SSL *ssl, Array<uint8_t> msg);
 int dtls1_add_change_cipher_spec(SSL *ssl);
 int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
 int dtls1_flush_flight(SSL *ssl);
@@ -2301,14 +2370,12 @@
 int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
                                 const uint8_t *premaster, size_t premaster_len);
 
-// tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
-// locally-configured group preference list.
-void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
-                        size_t *out_group_ids_len);
+// tls1_get_grouplist returns the locally-configured group preference list.
+Span<const uint16_t> tls1_get_grouplist(const SSL *ssl);
 
 // tls1_check_group_id returns one if |group_id| is consistent with
 // locally-configured group preferences.
-int tls1_check_group_id(SSL *ssl, uint16_t group_id);
+int tls1_check_group_id(const SSL *ssl, uint16_t group_id);
 
 // tls1_get_shared_group sets |*out_group_id| to the first preferred shared
 // group between client and server preferences and returns one. If none may be
@@ -2452,15 +2519,12 @@
   // root CBB to be passed into |finish_message|. |*body| is set to a child CBB
   // the caller should write to. It returns one on success and zero on error.
   int (*init_message)(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
-  // finish_message finishes a handshake message. It sets |*out_msg| to a
-  // newly-allocated buffer with the serialized message. The caller must
-  // release it with |OPENSSL_free| when done. It returns one on success and
-  // zero on error.
-  int (*finish_message)(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
+  // finish_message finishes a handshake message. It sets |*out_msg| to the
+  // serialized message. It returns one on success and zero on error.
+  int (*finish_message)(SSL *ssl, CBB *cbb, bssl::Array<uint8_t> *out_msg);
   // add_message adds a handshake message to the pending flight. It returns one
-  // on success and zero on error. In either case, it takes ownership of |msg|
-  // and releases it with |OPENSSL_free| when done.
-  int (*add_message)(SSL *ssl, uint8_t *msg, size_t len);
+  // on success and zero on error.
+  int (*add_message)(SSL *ssl, bssl::Array<uint8_t> msg);
   // add_change_cipher_spec adds a ChangeCipherSpec record to the pending
   // flight. It returns one on success and zero on error.
   int (*add_change_cipher_spec)(SSL *ssl);
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index dfa8bfa..f63ed26 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -176,23 +176,16 @@
   return 1;
 }
 
-int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
-                        size_t *out_len) {
-  if (!CBB_finish(cbb, out_msg, out_len)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-
-  return 1;
+int ssl3_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg) {
+  return CBBFinishArray(cbb, out_msg);
 }
 
-int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
+int ssl3_add_message(SSL *ssl, Array<uint8_t> msg) {
   // Add the message to the current flight, splitting into several records if
   // needed.
-  int ret = 0;
   size_t added = 0;
   do {
-    size_t todo = len - added;
+    size_t todo = msg.size() - added;
     if (todo > ssl->max_send_fragment) {
       todo = ssl->max_send_fragment;
     }
@@ -205,24 +198,21 @@
       type = SSL3_RT_PLAINTEXT_HANDSHAKE;
     }
 
-    if (!add_record_to_flight(ssl, type, msg + added, todo)) {
-      goto err;
+    if (!add_record_to_flight(ssl, type, msg.data() + added, todo)) {
+      return 0;
     }
     added += todo;
-  } while (added < len);
+  } while (added < msg.size());
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg.data(),
+                      msg.size());
   // TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript on
   // hs.
   if (ssl->s3->hs != NULL &&
-      !ssl->s3->hs->transcript.Update(msg, len)) {
-    goto err;
+      !ssl->s3->hs->transcript.Update(msg.data(), msg.size())) {
+    return 0;
   }
-  ret = 1;
-
-err:
-  OPENSSL_free(msg);
-  return ret;
+  return 1;
 }
 
 int ssl3_add_change_cipher_spec(SSL *ssl) {
diff --git a/src/ssl/ssl_file.cc b/src/ssl/ssl_file.cc
index 1bdc14f..bafa64a 100644
--- a/src/ssl/ssl_file.cc
+++ b/src/ssl/ssl_file.cc
@@ -570,6 +570,14 @@
   ctx->default_passwd_callback = cb;
 }
 
+pem_password_cb *SSL_CTX_get_default_passwd_cb(const SSL_CTX *ctx) {
+  return ctx->default_passwd_callback;
+}
+
 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
   ctx->default_passwd_callback_userdata = data;
 }
+
+void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx) {
+  return ctx->default_passwd_callback_userdata;
+}
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 207f11e..3ceb180 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -17,6 +17,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <utility>
+
 #include <openssl/bn.h>
 #include <openssl/bytestring.h>
 #include <openssl/curve25519.h>
@@ -71,8 +73,8 @@
     return true;
   }
 
-  bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
-              const uint8_t *peer_key, size_t peer_key_len) override {
+  bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+              Span<const uint8_t> peer_key) override {
     assert(private_key_);
     *out_alert = SSL_AD_INTERNAL_ERROR;
 
@@ -95,8 +97,8 @@
       return false;
     }
 
-    if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key,
-                            peer_key_len, bn_ctx.get())) {
+    if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key.data(),
+                            peer_key.size(), bn_ctx.get())) {
       *out_alert = SSL_AD_DECODE_ERROR;
       return false;
     }
@@ -110,14 +112,13 @@
     }
 
     // Encode the x-coordinate left-padded with zeros.
-    size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
-    UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
-    if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
+    Array<uint8_t> secret;
+    if (!secret.Init((EC_GROUP_get_degree(group.get()) + 7) / 8) ||
+        !BN_bn2bin_padded(secret.data(), secret.size(), x)) {
       return false;
     }
 
-    *out_secret = secret.release();
-    *out_secret_len = secret_len;
+    *out_secret = std::move(secret);
     return true;
   }
 
@@ -142,24 +143,24 @@
     return !!CBB_add_bytes(out, public_key, sizeof(public_key));
   }
 
-  bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
-              const uint8_t *peer_key, size_t peer_key_len) override {
+  bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+              Span<const uint8_t> peer_key) override {
     *out_alert = SSL_AD_INTERNAL_ERROR;
 
-    UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(32));
-    if (!secret) {
+    Array<uint8_t> secret;
+    if (!secret.Init(32)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return false;
     }
 
-    if (peer_key_len != 32 || !X25519(secret.get(), private_key_, peer_key)) {
+    if (peer_key.size() != 32 ||
+        !X25519(secret.data(), private_key_, peer_key.data())) {
       *out_alert = SSL_AD_DECODE_ERROR;
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
       return false;
     }
 
-    *out_secret = secret.release();
-    *out_secret_len = 32;
+    *out_secret = std::move(secret);
     return true;
   }
 
@@ -202,12 +203,11 @@
   }
 }
 
-bool SSLKeyShare::Accept(CBB *out_public_key, uint8_t **out_secret,
-                         size_t *out_secret_len, uint8_t *out_alert,
-                         const uint8_t *peer_key, size_t peer_key_len) {
+bool SSLKeyShare::Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
+                         uint8_t *out_alert, Span<const uint8_t> peer_key) {
   *out_alert = SSL_AD_INTERNAL_ERROR;
   return Offer(out_public_key) &&
-         Finish(out_secret, out_secret_len, out_alert, peer_key, peer_key_len);
+         Finish(out_secret, out_alert, peer_key);
 }
 
 int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 7a75776..b864f8d 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -187,6 +187,17 @@
 static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx =
     CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
 
+bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out) {
+  uint8_t *ptr;
+  size_t len;
+  if (!CBB_finish(cbb, &ptr, &len)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return false;
+  }
+  out->Reset(ptr, len);
+  return true;
+}
+
 void ssl_reset_error_state(SSL *ssl) {
   // Functions which use |SSL_get_error| must reset I/O and error state on
   // entry.
@@ -418,6 +429,11 @@
   return 1;
 }
 
+int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) {
+  CRYPTO_library_init();
+  return 1;
+}
+
 static uint32_t ssl_session_hash(const SSL_SESSION *sess) {
   const uint8_t *session_id = sess->session_id;
 
@@ -1555,9 +1571,8 @@
          ssl->s3->send_connection_binding;
 }
 
-LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; }
-
 size_t SSL_CTX_sess_number(const SSL_CTX *ctx) {
+  MutexReadLock lock(const_cast<CRYPTO_MUTEX *>(&ctx->lock));
   return lh_SSL_SESSION_num_items(ctx->sessions);
 }
 
@@ -2022,8 +2037,8 @@
     *out_types = NULL;
     return 0;
   }
-  *out_types = ssl->s3->hs->certificate_types;
-  return ssl->s3->hs->num_certificate_types;
+  *out_types = ssl->s3->hs->certificate_types.data();
+  return ssl->s3->hs->certificate_types.size();
 }
 
 EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 0e6c66c..ed4c779 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -672,21 +672,26 @@
     data.session_id_length = session_id_len;
     OPENSSL_memcpy(data.session_id, session_id, session_id_len);
 
-    CRYPTO_MUTEX_lock_read(&ssl->session_ctx->lock);
+    MutexReadLock lock(&ssl->session_ctx->lock);
     session.reset(lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &data));
     if (session) {
       // |lh_SSL_SESSION_retrieve| returns a non-owning pointer.
       SSL_SESSION_up_ref(session.get());
     }
     // TODO(davidben): This should probably move it to the front of the list.
-    CRYPTO_MUTEX_unlock_read(&ssl->session_ctx->lock);
   }
 
   // Fall back to the external cache, if it exists.
-  if (!session && ssl->session_ctx->get_session_cb != NULL) {
+  if (!session && (ssl->session_ctx->get_session_cb != nullptr ||
+                   ssl->session_ctx->get_session_cb_legacy != nullptr)) {
     int copy = 1;
-    session.reset(ssl->session_ctx->get_session_cb(ssl, (uint8_t *)session_id,
-                                                   session_id_len, &copy));
+    if (ssl->session_ctx->get_session_cb != nullptr) {
+      session.reset(ssl->session_ctx->get_session_cb(ssl, session_id,
+                                                     session_id_len, &copy));
+    } else {
+      session.reset(ssl->session_ctx->get_session_cb_legacy(
+          ssl, const_cast<uint8_t *>(session_id), session_id_len, &copy));
+    }
 
     if (!session) {
       return ssl_hs_ok;
@@ -722,72 +727,6 @@
   return ssl_hs_ok;
 }
 
-bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello) {
-  CBS extension, groups;
-  if (SSL_is_dtls(client_hello->ssl) ||
-      !ssl_client_hello_get_extension(client_hello, &extension,
-                                      TLSEXT_TYPE_supported_groups) ||
-      !CBS_get_u16_length_prefixed(&extension, &groups) ||
-      CBS_len(&extension) != 0) {
-    return false;
-  }
-
-  // Original Java curve list.
-  static const uint8_t kCurveList1[] = {
-      0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00, 0x15,
-      0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18,
-      0x00, 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e,
-      0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12,
-      0x00, 0x04, 0x00, 0x05, 0x00, 0x14, 0x00, 0x08, 0x00, 0x16};
-
-  // Newer Java curve list.
-  static const uint8_t kCurveList2[] = {
-      0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a,
-      0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16};
-
-  // IcedTea curve list.
-  static const uint8_t kCurveList3[] = {0x00, 0x17, 0x00, 0x18, 0x00, 0x19};
-
-  auto groups_span = MakeConstSpan(CBS_data(&groups), CBS_len(&groups));
-  if (groups_span != kCurveList1 && groups_span != kCurveList2 &&
-      groups_span != kCurveList3) {
-    return false;
-  }
-
-  // Java has a very distinctive curve list, but IcedTea patches it to a more
-  // standard [P-256, P-384, P-521]. Additionally check the extension
-  // order. This may still flag other clients, but false positives only mean a
-  // loss of resumption. Any client new enough to support one of X25519,
-  // extended master secret, session tickets, or TLS 1.3 will be unaffected.
-  //
-  // Java sends different extensions depending on configuration and version, but
-  // those which are present are always in the same order. Check if the
-  // extensions are an ordered subset of |kJavaExtensions|.
-  static const uint16_t kJavaExtensions[] = {
-      TLSEXT_TYPE_supported_groups,
-      TLSEXT_TYPE_ec_point_formats,
-      TLSEXT_TYPE_signature_algorithms,
-      TLSEXT_TYPE_server_name,
-      17 /* status_request_v2 */,
-      TLSEXT_TYPE_status_request,
-      TLSEXT_TYPE_application_layer_protocol_negotiation,
-      TLSEXT_TYPE_renegotiate,
-  };
-  CBS extensions;
-  CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
-  for (uint16_t expected : kJavaExtensions) {
-    CBS extensions_copy = extensions, body;
-    uint16_t type;
-    // Peek at the next extension.
-    if (CBS_get_u16(&extensions_copy, &type) &&
-        CBS_get_u16_length_prefixed(&extensions_copy, &body) &&
-        type == expected) {
-      extensions = extensions_copy;
-    }
-  }
-  return CBS_len(&extensions) == 0;
-}
-
 enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
                                         UniquePtr<SSL_SESSION> *out_session,
                                         bool *out_tickets_supported,
@@ -795,6 +734,8 @@
                                         const SSL_CLIENT_HELLO *client_hello) {
   // This is used only by servers.
   assert(ssl->server);
+  UniquePtr<SSL_SESSION> session;
+  bool renew_ticket = false;
 
   // If tickets are disabled, always behave as if no tickets are present.
   const uint8_t *ticket = NULL;
@@ -804,37 +745,6 @@
       ssl->version > SSL3_VERSION &&
       SSL_early_callback_ctx_extension_get(
           client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
-
-  if (ssl_is_probably_java(client_hello)) {
-    // The Java client implementation of the 3SHAKE mitigation incorrectly
-    // rejects initial handshakes when all of the following are true:
-    //
-    // 1. The ClientHello offered a session.
-    // 2. The session was successfully resumed previously.
-    // 3. The server declines the session.
-    // 4. The server sends a certificate with a different (see below) SAN list
-    //    than in the previous session.
-    //
-    // (Note the 3SHAKE mitigation is to reject certificates changes on
-    // renegotiation, while Java's logic applies to initial handshakes as well.)
-    //
-    // The end result is long-lived Java clients break on certificate rotations
-    // where the SAN list changes too much. Older versions of Java break if the
-    // first DNS name of the two certificates is different. Newer ones will
-    // break if there is no intersection. The new logic mostly mitigates this,
-    // but this can still cause problems if switching to or from wildcards.
-    //
-    // Thus, fingerprint Java clients and decline all offered sessions. This
-    // avoids (2) while still introducing new sessions to clear any existing
-    // problematic sessions.
-    *out_session = nullptr;
-    *out_tickets_supported = tickets_supported;
-    *out_renew_ticket = false;
-    return ssl_hs_ok;
-  }
-
-  UniquePtr<SSL_SESSION> session;
-  bool renew_ticket = false;
   if (tickets_supported && ticket_len > 0) {
     switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
                                client_hello->session_id,
@@ -1056,6 +966,30 @@
   return 1;
 }
 
+int SSL_SESSION_should_be_single_use(const SSL_SESSION *session) {
+  return SSL_SESSION_protocol_version(session) >= TLS1_3_VERSION;
+}
+
+int SSL_SESSION_is_resumable(const SSL_SESSION *session) {
+  return !session->not_resumable;
+}
+
+int SSL_SESSION_has_ticket(const SSL_SESSION *session) {
+  return session->tlsext_ticklen > 0;
+}
+
+void SSL_SESSION_get0_ticket(const SSL_SESSION *session,
+                             const uint8_t **out_ticket, size_t *out_len) {
+  if (out_ticket != nullptr) {
+    *out_ticket = session->tlsext_tick;
+  }
+  *out_len = session->tlsext_ticklen;
+}
+
+uint32_t SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session) {
+  return session->tlsext_tick_lifetime_hint;
+}
+
 SSL_SESSION *SSL_magic_pending_session_ptr(void) {
   return (SSL_SESSION *)&g_pending_session_magic;
 }
@@ -1109,41 +1043,44 @@
   // Although |session| is inserted into two structures (a doubly-linked list
   // and the hash table), |ctx| only takes one reference.
   SSL_SESSION_up_ref(session);
+  UniquePtr<SSL_SESSION> owned_session(session);
 
   SSL_SESSION *old_session;
-  CRYPTO_MUTEX_lock_write(&ctx->lock);
+  MutexWriteLock lock(&ctx->lock);
   if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
-    CRYPTO_MUTEX_unlock_write(&ctx->lock);
-    SSL_SESSION_free(session);
     return 0;
   }
+  // |ctx->sessions| took ownership of |session| and gave us back a reference to
+  // |old_session|. (|old_session| may be the same as |session|, in which case
+  // we traded identical references with |ctx->sessions|.)
+  owned_session.release();
+  owned_session.reset(old_session);
 
   if (old_session != NULL) {
     if (old_session == session) {
-      // |session| was already in the cache.
-      CRYPTO_MUTEX_unlock_write(&ctx->lock);
-      SSL_SESSION_free(old_session);
+      // |session| was already in the cache. There are no linked list pointers
+      // to update.
       return 0;
     }
 
-    // There was a session ID collision. |old_session| must be removed from
-    // the linked list and released.
+    // There was a session ID collision. |old_session| was replaced with
+    // |session| in the hash table, so |old_session| must be removed from the
+    // linked list to match.
     SSL_SESSION_list_remove(ctx, old_session);
-    SSL_SESSION_free(old_session);
   }
 
   SSL_SESSION_list_add(ctx, session);
 
   // Enforce any cache size limits.
   if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
-    while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
+    while (lh_SSL_SESSION_num_items(ctx->sessions) >
+           SSL_CTX_sess_get_cache_size(ctx)) {
       if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
         break;
       }
     }
   }
 
-  CRYPTO_MUTEX_unlock_write(&ctx->lock);
   return 1;
 }
 
@@ -1222,9 +1159,8 @@
     return;
   }
   tp.time = time;
-  CRYPTO_MUTEX_lock_write(&ctx->lock);
+  MutexWriteLock lock(&ctx->lock);
   lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
-  CRYPTO_MUTEX_unlock_write(&ctx->lock);
 }
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
@@ -1247,14 +1183,21 @@
 }
 
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
-                             SSL_SESSION *(*cb)(SSL *ssl,
-                                                uint8_t *id, int id_len,
-                                                int *out_copy)) {
+                             SSL_SESSION *(*cb)(SSL *ssl, const uint8_t *id,
+                                                int id_len, int *out_copy)) {
   ctx->get_session_cb = cb;
 }
 
-SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
-    SSL *ssl, uint8_t *id, int id_len, int *out_copy) {
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+                             SSL_SESSION *(*cb)(SSL *ssl, uint8_t *id,
+                                                int id_len, int *out_copy)) {
+  ctx->get_session_cb_legacy = cb;
+}
+
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
+                                                      const uint8_t *id,
+                                                      int id_len,
+                                                      int *out_copy) {
   return ctx->get_session_cb;
 }
 
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 10bc215..4653f73 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1399,7 +1399,7 @@
 
   // Check the hash table.
   std::vector<SSL_SESSION*> actual, expected_copy;
-  lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual);
+  lh_SSL_SESSION_doall_arg(ctx->sessions, AppendSession, &actual);
   expected_copy = expected;
 
   std::sort(actual.begin(), actual.end());
@@ -1941,197 +1941,106 @@
   EXPECT_EQ(Bytes(cert_sha256), Bytes(session->peer_sha256));
 }
 
-static bool ClientHelloMatches(uint16_t version, const uint8_t *expected,
-                               size_t expected_len) {
-  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
-  // Our default cipher list varies by CPU capabilities, so manually place the
-  // ChaCha20 ciphers in front.
-  const char* cipher_list = "CHACHA20:ALL";
-  if (!ctx ||
-      // SSLv3 is off by default.
-      !SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION) ||
-      !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
-      !SSL_CTX_set_strict_cipher_list(ctx.get(), cipher_list)) {
-    return false;
-  }
-
-  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
-  if (!ssl) {
-    return false;
-  }
-  std::vector<uint8_t> client_hello;
-  if (!GetClientHello(ssl.get(), &client_hello)) {
-    return false;
-  }
-
-  // Zero the client_random.
-  constexpr size_t kRandomOffset = 1 + 2 + 2 +  // record header
-                                   1 + 3 +      // handshake message header
-                                   2;           // client_version
-  if (client_hello.size() < kRandomOffset + SSL3_RANDOM_SIZE) {
-    fprintf(stderr, "ClientHello for version %04x too short.\n", version);
-    return false;
-  }
-  OPENSSL_memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
-
-  if (client_hello.size() != expected_len ||
-      OPENSSL_memcmp(client_hello.data(), expected, expected_len) != 0) {
-    fprintf(stderr, "ClientHello for version %04x did not match:\n", version);
-    fprintf(stderr, "Got:\n\t");
-    for (size_t i = 0; i < client_hello.size(); i++) {
-      fprintf(stderr, "0x%02x, ", client_hello[i]);
-    }
-    fprintf(stderr, "\nWanted:\n\t");
-    for (size_t i = 0; i < expected_len; i++) {
-      fprintf(stderr, "0x%02x, ", expected[i]);
-    }
-    fprintf(stderr, "\n");
-    return false;
-  }
-
-  return true;
-}
-
-// Tests that our ClientHellos do not change unexpectedly.
-static bool TestClientHello() {
-  static const uint8_t kSSL3ClientHello[] = {
-    0x16,
-    0x03, 0x00,
-    0x00, 0x3b,
-    0x01,
-    0x00, 0x00, 0x37,
-    0x03, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00,
-    0x00, 0x10,
-    0xc0, 0x09,
-    0xc0, 0x13,
-    0xc0, 0x0a,
-    0xc0, 0x14,
-    0x00, 0x2f,
-    0x00, 0x35,
-    0x00, 0x0a,
-    0x00, 0xff, 0x01, 0x00,
-  };
-  if (!ClientHelloMatches(SSL3_VERSION, kSSL3ClientHello,
-                          sizeof(kSSL3ClientHello))) {
-    return false;
-  }
-
-  static const uint8_t kTLS1ClientHello[] = {
-      0x16,
-      0x03, 0x01,
-      0x00, 0x5a,
-      0x01,
-      0x00, 0x00, 0x56,
-      0x03, 0x01,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00,
-      0x00, 0x0e,
-      0xc0, 0x09,
-      0xc0, 0x13,
-      0xc0, 0x0a,
-      0xc0, 0x14,
-      0x00, 0x2f,
-      0x00, 0x35,
-      0x00, 0x0a,
+// Tests that our ClientHellos do not change unexpectedly. These are purely
+// change detection tests. If they fail as part of an intentional ClientHello
+// change, update the test vector.
+TEST(SSLTest, ClientHello) {
+  struct {
+    uint16_t max_version;
+    std::vector<uint8_t> expected;
+  } kTests[] = {
+    {SSL3_VERSION,
+     {0x16, 0x03, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x37, 0x03, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x10, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
+      0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00}},
+    {TLS1_VERSION,
+     {0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x56, 0x03, 0x01, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xc0, 0x09,
+      0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
       0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
       0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
-      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
-  };
-  if (!ClientHelloMatches(TLS1_VERSION, kTLS1ClientHello,
-                          sizeof(kTLS1ClientHello))) {
-    return false;
-  }
-
-  static const uint8_t kTLS11ClientHello[] = {
-      0x16,
-      0x03, 0x01,
-      0x00, 0x5a,
-      0x01,
-      0x00, 0x00, 0x56,
-      0x03, 0x02,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00,
-      0x00, 0x0e,
-      0xc0, 0x09,
-      0xc0, 0x13,
-      0xc0, 0x0a,
-      0xc0, 0x14,
-      0x00, 0x2f,
-      0x00, 0x35,
-      0x00, 0x0a,
+      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18}},
+    {TLS1_1_VERSION,
+     {0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x56, 0x03, 0x02, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xc0, 0x09,
+      0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
       0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
       0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
-      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
-  };
-  if (!ClientHelloMatches(TLS1_1_VERSION, kTLS11ClientHello,
-                          sizeof(kTLS11ClientHello))) {
-    return false;
-  }
-
-  // kTLS12ClientHello assumes RSA-PSS, which is disabled for Android system
-  // builds.
-#if defined(BORINGSSL_ANDROID_SYSTEM)
-  return true;
+      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18}},
+  // This test assumes RSA-PSS, which is disabled for Android system builds.
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    {TLS1_2_VERSION,
+     {0x16, 0x03, 0x01, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x8a, 0x03, 0x03, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xcc, 0xa9,
+      0xcc, 0xa8, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xc0, 0x09,
+      0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x27, 0xc0, 0x0a, 0xc0, 0x24, 0xc0, 0x14,
+      0xc0, 0x28, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x35,
+      0x00, 0x3d, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37, 0xff, 0x01, 0x00, 0x01,
+      0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00,
+      0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08,
+      0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x0b, 0x00,
+      0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00,
+      0x17, 0x00, 0x18}},
 #endif
-
-  static const uint8_t kTLS12ClientHello[] = {
-      0x16,
-      0x03, 0x01,
-      0x00, 0x8e,
-      0x01,
-      0x00, 0x00, 0x8a,
-      0x03, 0x03,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x2a,
-      0xcc, 0xa9,
-      0xcc, 0xa8,
-      0xc0, 0x2b,
-      0xc0, 0x2f,
-      0xc0, 0x2c,
-      0xc0, 0x30,
-      0xc0, 0x09,
-      0xc0, 0x23,
-      0xc0, 0x13,
-      0xc0, 0x27,
-      0xc0, 0x0a,
-      0xc0, 0x24,
-      0xc0, 0x14,
-      0xc0, 0x28,
-      0x00, 0x9c,
-      0x00, 0x9d,
-      0x00, 0x2f,
-      0x00, 0x3c,
-      0x00, 0x35,
-      0x00, 0x3d,
-      0x00, 0x0a,
-      0x01, 0x00, 0x00, 0x37, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
-      0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04,
-      0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08,
-      0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
-      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+    // TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
+    // implementation has settled enough that it won't change.
   };
-  if (!ClientHelloMatches(TLS1_2_VERSION, kTLS12ClientHello,
-                          sizeof(kTLS12ClientHello))) {
-    return false;
+
+  for (const auto &t : kTests) {
+    SCOPED_TRACE(t.max_version);
+
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+    ASSERT_TRUE(ctx);
+    // Our default cipher list varies by CPU capabilities, so manually place the
+    // ChaCha20 ciphers in front.
+    const char *cipher_list = "CHACHA20:ALL";
+    // SSLv3 is off by default.
+    ASSERT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION));
+    ASSERT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), t.max_version));
+    ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), cipher_list));
+
+    bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+    ASSERT_TRUE(ssl);
+    std::vector<uint8_t> client_hello;
+    ASSERT_TRUE(GetClientHello(ssl.get(), &client_hello));
+
+    // Zero the client_random.
+    constexpr size_t kRandomOffset = 1 + 2 + 2 +  // record header
+                                     1 + 3 +      // handshake message header
+                                     2;           // client_version
+    ASSERT_GE(client_hello.size(), kRandomOffset + SSL3_RANDOM_SIZE);
+    OPENSSL_memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
+
+    if (client_hello != t.expected) {
+      ADD_FAILURE() << "ClientHellos did not match.";
+      // Print the value manually so it is easier to update the test vector.
+      for (size_t i = 0; i < client_hello.size(); i += 12) {
+        printf("     %c", i == 0 ? '{' : ' ');
+        for (size_t j = i; j < client_hello.size() && j < i + 12; j++) {
+          if (j > i) {
+            printf(" ");
+          }
+          printf("0x%02x", client_hello[j]);
+          if (j < client_hello.size() - 1) {
+            printf(",");
+          }
+        }
+        if (i + 12 >= client_hello.size()) {
+          printf("}}");
+        }
+        printf("\n");
+      }
+    }
   }
-
-  // TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
-  // implementation has settled enough that it won't change.
-
-  return true;
 }
 
 static bssl::UniquePtr<SSL_SESSION> g_last_session;
@@ -3831,179 +3740,6 @@
   EXPECT_EQ(SSL_R_NO_CIPHERS_AVAILABLE, ERR_GET_REASON(err));
 }
 
-TEST(SSLTest, IsProbablyJava) {
-  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
-  ASSERT_TRUE(ctx);
-  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
-  ASSERT_TRUE(ssl);
-
-  const struct {
-    const char *name;
-    std::vector<uint8_t> in;
-    bool is_probably_java;
-  } kTests[] = {
-      {"JDK 6 with IcedTea curve list",
-       {0x03, 0x01, 0x59, 0xb3, 0x10, 0xea, 0x17, 0xfe, 0x9e, 0x69, 0x7e, 0x79,
-        0xc7, 0x33, 0x10, 0x81, 0x73, 0x9e, 0xe7, 0xbf, 0x78, 0x4a, 0x33, 0x76,
-        0x12, 0x1f, 0xc5, 0x6d, 0x28, 0x8d, 0xd7, 0x60, 0xf0, 0x5e, 0x00, 0x00,
-        0x2c, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00,
-        0x39, 0x00, 0x38, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0,
-        0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0,
-        0x03, 0xc0, 0x0d, 0x00, 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00,
-        0x12, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
-        0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00},
-       true},
-      {"JDK 7 with IcedTea curve list",
-       {0x03, 0x03, 0x59, 0xb3, 0x10, 0xc8, 0x03, 0x7d, 0x10, 0x5a, 0x6b, 0x6e,
-        0x84, 0xa5, 0xbe, 0x6e, 0xe2, 0xd0, 0xb4, 0xb5, 0xcf, 0x6d, 0xa1, 0x58,
-        0xb5, 0xc0, 0x05, 0x63, 0xf6, 0x81, 0xda, 0xc2, 0xa0, 0xb0, 0x00, 0x00,
-        0x48, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0, 0x26, 0xc0, 0x2a, 0x00,
-        0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0,
-        0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x3c, 0xc0,
-        0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0, 0x09, 0xc0, 0x13, 0x00,
-        0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x08, 0xc0,
-        0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00, 0x16, 0x00, 0x13, 0x00,
-        0xff, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00,
-        0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
-        0x0d, 0x00, 0x18, 0x00, 0x16, 0x06, 0x03, 0x06, 0x01, 0x05, 0x03, 0x05,
-        0x01, 0x04, 0x03, 0x04, 0x01, 0x03, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02,
-        0x01, 0x02, 0x02},
-       true},
-      {"JDK 8",
-       {0x03, 0x03, 0x59, 0xb3, 0x10, 0xfc, 0xc7, 0xcb, 0x36, 0x85, 0x8c, 0x00,
-        0xd6, 0xa7, 0x5b, 0xfb, 0x98, 0xbe, 0xf9, 0xa3, 0xa0, 0x01, 0xff, 0x35,
-        0xb9, 0x1a, 0xc1, 0x72, 0xf1, 0x51, 0x4b, 0x49, 0x96, 0x1a, 0x00, 0x00,
-        0x70, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0, 0x26, 0xc0, 0x2a, 0x00,
-        0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0,
-        0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x3c, 0xc0,
-        0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0, 0x09, 0xc0, 0x13, 0x00,
-        0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x2c, 0xc0,
-        0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0, 0x32, 0x00, 0x9f, 0x00,
-        0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0, 0x31, 0x00, 0x9e, 0x00,
-        0xa2, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
-        0x16, 0x00, 0x13, 0xc0, 0x07, 0xc0, 0x11, 0x00, 0x05, 0xc0, 0x02, 0xc0,
-        0x0c, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x0a, 0x00,
-        0x34, 0x00, 0x32, 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00,
-        0x15, 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18, 0x00,
-        0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00,
-        0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12, 0x00, 0x04, 0x00, 0x05, 0x00,
-        0x14, 0x00, 0x08, 0x00, 0x16, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
-        0x0d, 0x00, 0x1a, 0x00, 0x18, 0x06, 0x03, 0x06, 0x01, 0x05, 0x03, 0x05,
-        0x01, 0x04, 0x03, 0x04, 0x01, 0x03, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02,
-        0x01, 0x02, 0x02, 0x01, 0x01},
-       true},
-      {"JDK 9",
-       {0x03, 0x03, 0x0c, 0xe6, 0x06, 0xc6, 0x5d, 0x38, 0xb4, 0x5e, 0x3a, 0xd5,
-        0xb0, 0x5f, 0x5b, 0x84, 0x3b, 0xff, 0x86, 0x4f, 0xb0, 0x3f, 0xc1, 0xfd,
-        0x08, 0xf0, 0x97, 0xf3, 0x56, 0x44, 0x08, 0xe2, 0xdd, 0x2a, 0x00, 0x00,
-        0x64, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0,
-        0x32, 0x00, 0x9f, 0x00, 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0,
-        0x31, 0x00, 0x9e, 0x00, 0xa2, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0,
-        0x26, 0xc0, 0x2a, 0x00, 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
-        0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0,
-        0x27, 0x00, 0x3c, 0xc0, 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0,
-        0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00,
-        0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
-        0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00, 0x5d, 0x00, 0x0a, 0x00,
-        0x16, 0x00, 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00,
-        0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00,
-        0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06,
-        0x03, 0x06, 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04,
-        0x02, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02,
-        0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00,
-        0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
-        0x05, 0x01, 0x00, 0x00, 0x00, 0x00},
-       true},
-      {"JDK 9 with SNI and ALPN enabled and no SCSV cipher",
-       {0x03, 0x03, 0x37, 0xa6, 0x4b, 0x58, 0x02, 0xd0, 0x77, 0xe4, 0x48, 0xaf,
-        0x90, 0x50, 0x45, 0xd5, 0x2f, 0xe7, 0x98, 0x5d, 0x54, 0x93, 0x85, 0x3a,
-        0xde, 0xb6, 0xaa, 0x47, 0xef, 0x7f, 0xb5, 0x52, 0xe6, 0xf8, 0x00, 0x00,
-        0x02, 0xc0, 0x24, 0x01, 0x00, 0x00, 0x87, 0x00, 0x0a, 0x00, 0x16, 0x00,
-        0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00,
-        0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x0b, 0x00,
-        0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06, 0x03, 0x06,
-        0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04, 0x02, 0x03,
-        0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02, 0x02, 0x00,
-        0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d,
-        0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x11, 0x00, 0x10, 0x00,
-        0x0e, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x10, 0x00, 0x0d, 0x00, 0x0b, 0x07, 0x68, 0x74, 0x74, 0x70, 0x31,
-        0x2e, 0x31, 0x02, 0x68, 0x32, 0xff, 0x01, 0x00, 0x01, 0x00},
-       true},
-      {"JDK 9 with EMS extension appended",
-       {0x03, 0x03, 0x0c, 0xe6, 0x06, 0xc6, 0x5d, 0x38, 0xb4, 0x5e, 0x3a, 0xd5,
-        0xb0, 0x5f, 0x5b, 0x84, 0x3b, 0xff, 0x86, 0x4f, 0xb0, 0x3f, 0xc1, 0xfd,
-        0x08, 0xf0, 0x97, 0xf3, 0x56, 0x44, 0x08, 0xe2, 0xdd, 0x2a, 0x00, 0x00,
-        0x64, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0,
-        0x32, 0x00, 0x9f, 0x00, 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0,
-        0x31, 0x00, 0x9e, 0x00, 0xa2, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0,
-        0x26, 0xc0, 0x2a, 0x00, 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
-        0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0,
-        0x27, 0x00, 0x3c, 0xc0, 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0,
-        0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00,
-        0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
-        0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00, 0x61, 0x00, 0x0a, 0x00,
-        0x16, 0x00, 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00,
-        0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00,
-        0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06,
-        0x03, 0x06, 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04,
-        0x02, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02,
-        0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00,
-        0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
-        0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00},
-       false},
-      {"Chrome 61",
-       {0x03, 0x03, 0x33, 0x43, 0x8a, 0x6f, 0x76, 0xdd, 0x84, 0x3f, 0x8d, 0xaa,
-        0x43, 0xf1, 0x86, 0xee, 0xdd, 0x97, 0x96, 0x54, 0xf6, 0x17, 0x2c, 0xde,
-        0x69, 0xfe, 0x5e, 0x53, 0xaa, 0x47, 0xee, 0xad, 0xd7, 0x47, 0x00, 0x00,
-        0x1c, 0x3a, 0x3a, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xcc,
-        0xa9, 0xcc, 0xa8, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00,
-        0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x77, 0x8a, 0x8a, 0x00,
-        0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0c,
-        0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
-        0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14,
-        0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05,
-        0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x05, 0x00, 0x05,
-        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00,
-        0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f,
-        0x31, 0x2e, 0x31, 0x75, 0x50, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01,
-        0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x4a, 0x4a, 0x00, 0x1d, 0x00,
-        0x17, 0x00, 0x18, 0x6a, 0x6a, 0x00, 0x01, 0x00},
-       false},
-      {"Firefox 55",
-       {0x03, 0x03, 0x06, 0x8e, 0xf8, 0xf7, 0x7a, 0xfd, 0xce, 0x45, 0xb0, 0x39,
-        0xbe, 0xa4, 0x55, 0x27, 0xe2, 0x80, 0xc4, 0x0a, 0xbd, 0xce, 0x56, 0x7a,
-        0xbc, 0x1f, 0x26, 0x2f, 0xfa, 0xb9, 0xa1, 0x7e, 0xe6, 0xde, 0x00, 0x00,
-        0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x2c, 0xc0,
-        0x30, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x33, 0x00,
-        0x39, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x6a, 0x00,
-        0x00, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61,
-        0x6c, 0x68, 0x6f, 0x73, 0x74, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00,
-        0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17,
-        0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23,
-        0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08,
-        0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05,
-        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, 0x04,
-        0x03, 0x05, 0x03, 0x06, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04,
-        0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x03, 0x02, 0x01},
-       false},
-  };
-  for (const auto &t : kTests) {
-    SCOPED_TRACE(t.name);
-
-    bssl::SSLMessage msg;
-    msg.is_v2_hello = false;
-    msg.type = SSL3_MT_CLIENT_HELLO;
-    CBS_init(&msg.body, t.in.data(), t.in.size());
-    CBS_init(&msg.raw, nullptr, 0);  // unused
-
-    SSL_CLIENT_HELLO client_hello;
-    ASSERT_TRUE(bssl::ssl_client_hello_init(ssl.get(), &client_hello, msg));
-    EXPECT_EQ(t.is_probably_java, bssl::ssl_is_probably_java(&client_hello));
-  }
-}
-
 // TODO(davidben): Convert this file to GTest properly.
 TEST(SSLTest, AllTests) {
   if (!TestSSL_SESSIONEncoding(kOpenSSLSession) ||
@@ -4019,8 +3755,7 @@
       !TestPaddingExtension(TLS1_3_VERSION, TLS1_2_VERSION) ||
       // Test the padding extension at TLS 1.3 with a TLS 1.3 session, so there
       // will be a PSK binder after the padding extension.
-      !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT_VERSION) ||
-      !TestClientHello()) {
+      !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT_VERSION)) {
     ADD_FAILURE() << "Tests failed";
   }
 }
diff --git a/src/ssl/ssl_x509.cc b/src/ssl/ssl_x509.cc
index 7ff6a89..2b7ba83 100644
--- a/src/ssl/ssl_x509.cc
+++ b/src/ssl/ssl_x509.cc
@@ -835,10 +835,8 @@
 
 X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
   check_ssl_ctx_x509_method(ctx);
-  CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
-  X509 *ret = ssl_cert_get0_leaf(ctx->cert);
-  CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
-  return ret;
+  MutexWriteLock lock(const_cast<CRYPTO_MUTEX*>(&ctx->lock));
+  return ssl_cert_get0_leaf(ctx->cert);
 }
 
 static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
@@ -994,11 +992,8 @@
 
 int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
   check_ssl_ctx_x509_method(ctx);
-  CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
-  const int ret = ssl_cert_cache_chain_certs(ctx->cert);
-  CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
-
-  if (!ret) {
+  MutexWriteLock lock(const_cast<CRYPTO_MUTEX*>(&ctx->lock));
+  if (!ssl_cert_cache_chain_certs(ctx->cert)) {
     *out_chain = NULL;
     return 0;
   }
@@ -1165,11 +1160,10 @@
   check_ssl_ctx_x509_method(ctx);
   // This is a logically const operation that may be called on multiple threads,
   // so it needs to lock around updating |cached_x509_client_CA|.
-  CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
-  STACK_OF(X509_NAME) *ret = buffer_names_to_x509(
-      ctx->client_CA, (STACK_OF(X509_NAME) **)&ctx->cached_x509_client_CA);
-  CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
-  return ret;
+  MutexWriteLock lock(const_cast<CRYPTO_MUTEX *>(&ctx->lock));
+  return buffer_names_to_x509(
+      ctx->client_CA,
+      const_cast<STACK_OF(X509_NAME) **>(&ctx->cached_x509_client_CA));
 }
 
 static int add_client_CA(STACK_OF(CRYPTO_BUFFER) **names, X509 *x509,
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index ec70d27..1fe360b 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -113,6 +113,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <utility>
+
 #include <openssl/bytestring.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
@@ -147,19 +149,16 @@
 // This function does an initial scan over the extensions block to filter those
 // out.
 static int tls1_check_duplicate_extensions(const CBS *cbs) {
-  CBS extensions = *cbs;
-  size_t num_extensions = 0, i = 0;
-  uint16_t *extension_types = NULL;
-  int ret = 0;
-
   // First pass: count the extensions.
+  size_t num_extensions = 0;
+  CBS extensions = *cbs;
   while (CBS_len(&extensions) > 0) {
     uint16_t type;
     CBS extension;
 
     if (!CBS_get_u16(&extensions, &type) ||
         !CBS_get_u16_length_prefixed(&extensions, &extension)) {
-      goto done;
+      return 0;
     }
 
     num_extensions++;
@@ -169,39 +168,34 @@
     return 1;
   }
 
-  extension_types =
-      (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * num_extensions);
-  if (extension_types == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto done;
+  Array<uint16_t> extension_types;
+  if (!extension_types.Init(num_extensions)) {
+    return 0;
   }
 
   // Second pass: gather the extension types.
   extensions = *cbs;
-  for (i = 0; i < num_extensions; i++) {
+  for (size_t i = 0; i < extension_types.size(); i++) {
     CBS extension;
 
     if (!CBS_get_u16(&extensions, &extension_types[i]) ||
         !CBS_get_u16_length_prefixed(&extensions, &extension)) {
       // This should not happen.
-      goto done;
+      return 0;
     }
   }
   assert(CBS_len(&extensions) == 0);
 
   // Sort the extensions and make sure there are no duplicates.
-  qsort(extension_types, num_extensions, sizeof(uint16_t), compare_uint16_t);
-  for (i = 1; i < num_extensions; i++) {
+  qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t),
+        compare_uint16_t);
+  for (size_t i = 1; i < num_extensions; i++) {
     if (extension_types[i - 1] == extension_types[i]) {
-      goto done;
+      return 0;
     }
   }
 
-  ret = 1;
-
-done:
-  OPENSSL_free(extension_types);
-  return ret;
+  return 1;
 }
 
 int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
@@ -297,24 +291,18 @@
     SSL_CURVE_SECP384R1,
 };
 
-void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
-                        size_t *out_group_ids_len) {
-  *out_group_ids = ssl->supported_group_list;
-  *out_group_ids_len = ssl->supported_group_list_len;
-  if (!*out_group_ids) {
-    *out_group_ids = kDefaultGroups;
-    *out_group_ids_len = OPENSSL_ARRAY_SIZE(kDefaultGroups);
+Span<const uint16_t> tls1_get_grouplist(const SSL *ssl) {
+  if (ssl->supported_group_list != nullptr) {
+    return MakeConstSpan(ssl->supported_group_list,
+                         ssl->supported_group_list_len);
   }
+  return Span<const uint16_t>(kDefaultGroups);
 }
 
 int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
   SSL *const ssl = hs->ssl;
   assert(ssl->server);
 
-  const uint16_t *groups, *pref, *supp;
-  size_t groups_len, pref_len, supp_len;
-  tls1_get_grouplist(ssl, &groups, &groups_len);
-
   // Clients are not required to send a supported_groups extension. In this
   // case, the server is free to pick any group it likes. See RFC 4492,
   // section 4, paragraph 3.
@@ -324,22 +312,20 @@
   // support our favoured group. Thus we do not special-case an emtpy
   // |peer_supported_group_list|.
 
+  Span<const uint16_t> groups = tls1_get_grouplist(ssl);
+  Span<const uint16_t> pref, supp;
   if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
     pref = groups;
-    pref_len = groups_len;
     supp = hs->peer_supported_group_list;
-    supp_len = hs->peer_supported_group_list_len;
   } else {
     pref = hs->peer_supported_group_list;
-    pref_len = hs->peer_supported_group_list_len;
     supp = groups;
-    supp_len = groups_len;
   }
 
-  for (size_t i = 0; i < pref_len; i++) {
-    for (size_t j = 0; j < supp_len; j++) {
-      if (pref[i] == supp[j]) {
-        *out_group_id = pref[i];
+  for (uint16_t pref_group : pref) {
+    for (uint16_t supp_group : supp) {
+      if (pref_group == supp_group) {
+        *out_group_id = pref_group;
         return 1;
       }
     }
@@ -412,12 +398,9 @@
   return 0;
 }
 
-int tls1_check_group_id(SSL *ssl, uint16_t group_id) {
-  const uint16_t *groups;
-  size_t groups_len;
-  tls1_get_grouplist(ssl, &groups, &groups_len);
-  for (size_t i = 0; i < groups_len; i++) {
-    if (groups[i] == group_id) {
+int tls1_check_group_id(const SSL *ssl, uint16_t group_id) {
+  for (uint16_t supported : tls1_get_grouplist(ssl)) {
+    if (supported == group_id) {
       return 1;
     }
   }
@@ -1028,10 +1011,7 @@
 
 static int ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                          CBS *contents) {
-  OPENSSL_free(hs->peer_sigalgs);
-  hs->peer_sigalgs = NULL;
-  hs->num_peer_sigalgs = 0;
-
+  hs->peer_sigalgs.Reset();
   if (contents == NULL) {
     return 1;
   }
@@ -2111,13 +2091,11 @@
     // We received a HelloRetryRequest without a new curve, so there is no new
     // share to append. Leave |hs->key_share| as-is.
     if (group_id == 0 &&
-        !CBB_add_bytes(&kse_bytes, hs->key_share_bytes,
-                       hs->key_share_bytes_len)) {
+        !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(),
+                       hs->key_share_bytes.size())) {
       return 0;
     }
-    OPENSSL_free(hs->key_share_bytes);
-    hs->key_share_bytes = NULL;
-    hs->key_share_bytes_len = 0;
+    hs->key_share_bytes.Reset();
     if (group_id == 0) {
       return CBB_flush(out);
     }
@@ -2132,10 +2110,8 @@
     }
 
     // Predict the most preferred group.
-    const uint16_t *groups;
-    size_t groups_len;
-    tls1_get_grouplist(ssl, &groups, &groups_len);
-    if (groups_len == 0) {
+    Span<const uint16_t> groups = tls1_get_grouplist(ssl);
+    if (groups.size() == 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
       return 0;
     }
@@ -2153,22 +2129,18 @@
     return 0;
   }
 
-  if (!hs->received_hello_retry_request) {
-    // Save the contents of the extension to repeat it in the second
-    // ClientHello.
-    hs->key_share_bytes_len = CBB_len(&kse_bytes);
-    hs->key_share_bytes =
-        (uint8_t *)BUF_memdup(CBB_data(&kse_bytes), CBB_len(&kse_bytes));
-    if (hs->key_share_bytes == NULL) {
-      return 0;
-    }
+  // Save the contents of the extension to repeat it in the second ClientHello.
+  if (!hs->received_hello_retry_request &&
+      !hs->key_share_bytes.CopyFrom(
+          MakeConstSpan(CBB_data(&kse_bytes), CBB_len(&kse_bytes)))) {
+    return 0;
   }
 
   return CBB_flush(out);
 }
 
-int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
-                                        size_t *out_secret_len,
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
+                                        Array<uint8_t> *out_secret,
                                         uint8_t *out_alert, CBS *contents) {
   CBS peer_key;
   uint16_t group_id;
@@ -2185,8 +2157,7 @@
     return 0;
   }
 
-  if (!hs->key_share->Finish(out_secret, out_secret_len, out_alert,
-                             CBS_data(&peer_key), CBS_len(&peer_key))) {
+  if (!hs->key_share->Finish(out_secret, out_alert, peer_key)) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
@@ -2197,8 +2168,7 @@
 }
 
 int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
-                                        uint8_t **out_secret,
-                                        size_t *out_secret_len,
+                                        Array<uint8_t> *out_secret,
                                         uint8_t *out_alert, CBS *contents) {
   uint16_t group_id;
   CBS key_shares;
@@ -2241,29 +2211,23 @@
 
   if (!found) {
     *out_found = false;
-    *out_secret = NULL;
-    *out_secret_len = 0;
+    out_secret->Reset();
     return 1;
   }
 
   // Compute the DH secret.
-  uint8_t *secret = NULL;
-  size_t secret_len;
+  Array<uint8_t> secret;
   ScopedCBB public_key;
   UniquePtr<SSLKeyShare> key_share = SSLKeyShare::Create(group_id);
   if (!key_share ||
       !CBB_init(public_key.get(), 32) ||
-      !key_share->Accept(public_key.get(), &secret, &secret_len, out_alert,
-                         CBS_data(&peer_key), CBS_len(&peer_key)) ||
-      !CBB_finish(public_key.get(), &hs->ecdh_public_key,
-                  &hs->ecdh_public_key_len)) {
-    OPENSSL_free(secret);
+      !key_share->Accept(public_key.get(), &secret, out_alert, peer_key) ||
+      !CBBFinishArray(public_key.get(), &hs->ecdh_public_key)) {
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     return 0;
   }
 
-  *out_secret = secret;
-  *out_secret_len = secret_len;
+  *out_secret = std::move(secret);
   *out_found = true;
   return 1;
 }
@@ -2276,15 +2240,13 @@
       !CBB_add_u16_length_prefixed(out, &kse_bytes) ||
       !CBB_add_u16(&kse_bytes, group_id) ||
       !CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
-      !CBB_add_bytes(&public_key, hs->ecdh_public_key,
-                     hs->ecdh_public_key_len) ||
+      !CBB_add_bytes(&public_key, hs->ecdh_public_key.data(),
+                     hs->ecdh_public_key.size()) ||
       !CBB_flush(out)) {
     return 0;
   }
 
-  OPENSSL_free(hs->ecdh_public_key);
-  hs->ecdh_public_key = NULL;
-  hs->ecdh_public_key_len = 0;
+  hs->ecdh_public_key.Reset();
 
   hs->new_session->group_id = group_id;
   return 1;
@@ -2328,7 +2290,7 @@
 // https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.2
 
 static int ext_cookie_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
-  if (hs->cookie == NULL) {
+  if (hs->cookie.size() == 0) {
     return 1;
   }
 
@@ -2336,15 +2298,13 @@
   if (!CBB_add_u16(out, TLSEXT_TYPE_cookie) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
       !CBB_add_u16_length_prefixed(&contents, &cookie) ||
-      !CBB_add_bytes(&cookie, hs->cookie, hs->cookie_len) ||
+      !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) ||
       !CBB_flush(out)) {
     return 0;
   }
 
   // The cookie is no longer needed in memory.
-  OPENSSL_free(hs->cookie);
-  hs->cookie = NULL;
-  hs->cookie_len = 0;
+  hs->cookie.Reset();
   return 1;
 }
 
@@ -2370,12 +2330,8 @@
     return 0;
   }
 
-  const uint16_t *groups;
-  size_t groups_len;
-  tls1_get_grouplist(ssl, &groups, &groups_len);
-
-  for (size_t i = 0; i < groups_len; i++) {
-    if (!CBB_add_u16(&groups_bytes, groups[i])) {
+  for (uint16_t group : tls1_get_grouplist(ssl)) {
+    if (!CBB_add_u16(&groups_bytes, group)) {
       return 0;
     }
   }
@@ -2391,6 +2347,29 @@
   return 1;
 }
 
+static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
+  CBS copy = *cbs;
+  if ((CBS_len(&copy) & 1) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return false;
+  }
+
+  Array<uint16_t> ret;
+  if (!ret.Init(CBS_len(&copy) / 2)) {
+    return false;
+  }
+  for (size_t i = 0; i < ret.size(); i++) {
+    if (!CBS_get_u16(&copy, &ret[i])) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return false;
+    }
+  }
+
+  assert(CBS_len(&copy) == 0);
+  *out = std::move(ret);
+  return 1;
+}
+
 static int ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
                                                   uint8_t *out_alert,
                                                   CBS *contents) {
@@ -2401,36 +2380,12 @@
   CBS supported_group_list;
   if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
       CBS_len(&supported_group_list) == 0 ||
-      (CBS_len(&supported_group_list) & 1) != 0 ||
-      CBS_len(contents) != 0) {
+      CBS_len(contents) != 0 ||
+      !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) {
     return 0;
   }
 
-  hs->peer_supported_group_list =
-      (uint16_t *)OPENSSL_malloc(CBS_len(&supported_group_list));
-  if (hs->peer_supported_group_list == NULL) {
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-    return 0;
-  }
-
-  const size_t num_groups = CBS_len(&supported_group_list) / 2;
-  for (size_t i = 0; i < num_groups; i++) {
-    if (!CBS_get_u16(&supported_group_list,
-                     &hs->peer_supported_group_list[i])) {
-      goto err;
-    }
-  }
-
-  assert(CBS_len(&supported_group_list) == 0);
-  hs->peer_supported_group_list_len = num_groups;
-
   return 1;
-
-err:
-  OPENSSL_free(hs->peer_supported_group_list);
-  hs->peer_supported_group_list = NULL;
-  *out_alert = SSL_AD_INTERNAL_ERROR;
-  return 0;
 }
 
 static int ext_supported_groups_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
@@ -3193,39 +3148,7 @@
     return 1;
   }
 
-  OPENSSL_free(hs->peer_sigalgs);
-  hs->peer_sigalgs = NULL;
-  hs->num_peer_sigalgs = 0;
-
-  size_t num_sigalgs = CBS_len(in_sigalgs);
-  if (num_sigalgs % 2 != 0) {
-    return 0;
-  }
-  num_sigalgs /= 2;
-
-  // supported_signature_algorithms in the certificate request is
-  // allowed to be empty.
-  if (num_sigalgs == 0) {
-    return 1;
-  }
-
-  // This multiplication doesn't overflow because sizeof(uint16_t) is two
-  // and we just divided |num_sigalgs| by two.
-  hs->peer_sigalgs = (uint16_t *)OPENSSL_malloc(num_sigalgs * sizeof(uint16_t));
-  if (hs->peer_sigalgs == NULL) {
-    return 0;
-  }
-  hs->num_peer_sigalgs = num_sigalgs;
-
-  CBS sigalgs;
-  CBS_init(&sigalgs, CBS_data(in_sigalgs), CBS_len(in_sigalgs));
-  for (size_t i = 0; i < num_sigalgs; i++) {
-    if (!CBS_get_u16(&sigalgs, &hs->peer_sigalgs[i])) {
-      return 0;
-    }
-  }
-
-  return 1;
+  return parse_u16_array(in_sigalgs, &hs->peer_sigalgs);
 }
 
 int tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) {
@@ -3255,36 +3178,31 @@
     return 1;
   }
 
-  const uint16_t *sigalgs = cert->sigalgs;
-  size_t num_sigalgs = cert->num_sigalgs;
-  if (sigalgs == NULL) {
-    sigalgs = kSignSignatureAlgorithms;
-    num_sigalgs = OPENSSL_ARRAY_SIZE(kSignSignatureAlgorithms);
+  Span<const uint16_t> sigalgs = kSignSignatureAlgorithms;
+  if (cert->sigalgs != nullptr) {
+    sigalgs = MakeConstSpan(cert->sigalgs, cert->num_sigalgs);
   }
 
-  const uint16_t *peer_sigalgs = hs->peer_sigalgs;
-  size_t num_peer_sigalgs = hs->num_peer_sigalgs;
-  if (num_peer_sigalgs == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+  Span<const uint16_t> peer_sigalgs = hs->peer_sigalgs;
+  if (peer_sigalgs.size() == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
     // If the client didn't specify any signature_algorithms extension then
     // we can assume that it supports SHA1. See
     // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
     static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1,
                                                       SSL_SIGN_ECDSA_SHA1};
     peer_sigalgs = kDefaultPeerAlgorithms;
-    num_peer_sigalgs = OPENSSL_ARRAY_SIZE(kDefaultPeerAlgorithms);
   }
 
-  for (size_t i = 0; i < num_sigalgs; i++) {
-    uint16_t sigalg = sigalgs[i];
+  for (uint16_t sigalg : sigalgs) {
     // SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal value and should never be
     // negotiated.
     if (sigalg == SSL_SIGN_RSA_PKCS1_MD5_SHA1 ||
-        !ssl_private_key_supports_signature_algorithm(hs, sigalgs[i])) {
+        !ssl_private_key_supports_signature_algorithm(hs, sigalg)) {
       continue;
     }
 
-    for (size_t j = 0; j < num_peer_sigalgs; j++) {
-      if (sigalg == peer_sigalgs[j]) {
+    for (uint16_t peer_sigalg : peer_sigalgs) {
+      if (sigalg == peer_sigalg) {
         *out = sigalg;
         return 1;
       }
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 316ae01..5f83910 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -854,7 +854,7 @@
   *out_pkey = GetTestState(ssl)->channel_id.release();
 }
 
-static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len,
+static SSL_SESSION *GetSessionCallback(SSL *ssl, const uint8_t *data, int len,
                                        int *copy) {
   TestState *async_state = GetTestState(ssl);
   if (async_state->session) {
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 19edb7f..8404d52 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -1446,11 +1446,6 @@
 	// PadClientHello, if non-zero, pads the ClientHello to a multiple of
 	// that many bytes.
 	PadClientHello int
-
-	// SendOnlyECExtensions omits all extensions except supported_groups and
-	// ec_point_formats, in order to trigger the Java ClientHello
-	// fingerprint.
-	SendOnlyECExtensions bool
 }
 
 func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index a04ffd0..0c23793 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -97,7 +97,6 @@
 		pskBinderFirst:          c.config.Bugs.PSKBinderFirst,
 		omitExtensions:          c.config.Bugs.OmitExtensions,
 		emptyExtensions:         c.config.Bugs.EmptyExtensions,
-		sendOnlyECExtensions:    c.config.Bugs.SendOnlyECExtensions,
 	}
 
 	if maxVersion >= VersionTLS13 {
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 2e6d286..5dbcab9 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -176,7 +176,6 @@
 	omitExtensions          bool
 	emptyExtensions         bool
 	pad                     int
-	sendOnlyECExtensions    bool
 }
 
 func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -225,8 +224,7 @@
 		m.pskBinderFirst == m1.pskBinderFirst &&
 		m.omitExtensions == m1.omitExtensions &&
 		m.emptyExtensions == m1.emptyExtensions &&
-		m.pad == m1.pad &&
-		m.sendOnlyECExtensions == m1.sendOnlyECExtensions
+		m.pad == m1.pad
 }
 
 func (m *clientHelloMsg) marshal() []byte {
@@ -314,6 +312,22 @@
 		certificateStatusRequest.addU16(0) // ResponderID length
 		certificateStatusRequest.addU16(0) // Extensions length
 	}
+	if len(m.supportedCurves) > 0 {
+		// http://tools.ietf.org/html/rfc4492#section-5.1.1
+		extensions.addU16(extensionSupportedCurves)
+		supportedCurvesList := extensions.addU16LengthPrefixed()
+		supportedCurves := supportedCurvesList.addU16LengthPrefixed()
+		for _, curve := range m.supportedCurves {
+			supportedCurves.addU16(uint16(curve))
+		}
+	}
+	if len(m.supportedPoints) > 0 {
+		// http://tools.ietf.org/html/rfc4492#section-5.1.2
+		extensions.addU16(extensionSupportedPoints)
+		supportedPointsList := extensions.addU16LengthPrefixed()
+		supportedPoints := supportedPointsList.addU8LengthPrefixed()
+		supportedPoints.addBytes(m.supportedPoints)
+	}
 	if m.hasKeyShares {
 		extensions.addU16(extensionKeyShare)
 		keyShareList := extensions.addU16LengthPrefixed()
@@ -426,30 +440,6 @@
 		customExt := extensions.addU16LengthPrefixed()
 		customExt.addBytes([]byte(m.customExtension))
 	}
-
-	// Discard all extensions but the curve-related ones to trigger the Java
-	// fingerprinter.
-	if m.sendOnlyECExtensions {
-		hello.discardChild()
-		extensions = hello.addU16LengthPrefixed()
-	}
-	if len(m.supportedCurves) > 0 {
-		// http://tools.ietf.org/html/rfc4492#section-5.1.1
-		extensions.addU16(extensionSupportedCurves)
-		supportedCurvesList := extensions.addU16LengthPrefixed()
-		supportedCurves := supportedCurvesList.addU16LengthPrefixed()
-		for _, curve := range m.supportedCurves {
-			supportedCurves.addU16(uint16(curve))
-		}
-	}
-	if len(m.supportedPoints) > 0 {
-		// http://tools.ietf.org/html/rfc4492#section-5.1.2
-		extensions.addU16(extensionSupportedPoints)
-		supportedPointsList := extensions.addU16LengthPrefixed()
-		supportedPoints := supportedPointsList.addU8LengthPrefixed()
-		supportedPoints.addBytes(m.supportedPoints)
-	}
-
 	// The PSK extension must be last (draft-ietf-tls-tls13-18 section 4.2.6).
 	if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
 		extensions.addU16(extensionPreSharedKey)
@@ -466,8 +456,6 @@
 		}
 	}
 
-	// This must be swapped with PSK (with some length computation) if we
-	// ever need to support PadClientHello and TLS 1.3.
 	if m.pad != 0 && hello.len()%m.pad != 0 {
 		extensions.addU16(extensionPadding)
 		padding := extensions.addU16LengthPrefixed()
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index ee72c2e..5415aa5 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -2797,25 +2797,6 @@
 			shouldFail:         true,
 			expectedLocalError: "local error: record overflow",
 		},
-		{
-			// Test that Java-like ClientHellos are provided session
-			// IDs but resumption is always declined. This is to
-			// workaround a bug that causes connection failures when
-			// certificates rotate.
-			testType: serverTest,
-			name:     "JavaWorkaround",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				CurvePreferences:       []CurveID{CurveP256, CurveP384, CurveP521},
-				SessionTicketsDisabled: true,
-				Bugs: ProtocolBugs{
-					SendOnlyECExtensions: true,
-				},
-			},
-			flags:                []string{"-expect-session-id"},
-			resumeSession:        true,
-			expectResumeRejected: true,
-		},
 	}
 	testCases = append(testCases, basicTests...)
 
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index f50b077..7ed9fad 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -99,7 +99,7 @@
       return ssl_hs_error;
     }
 
-    if (!CBS_stow(&cookie_value, &hs->cookie, &hs->cookie_len)) {
+    if (!hs->cookie.CopyFrom(cookie_value)) {
       return ssl_hs_error;
     }
   }
@@ -113,18 +113,7 @@
     }
 
     // The group must be supported.
-    const uint16_t *groups;
-    size_t groups_len;
-    tls1_get_grouplist(ssl, &groups, &groups_len);
-    int found = 0;
-    for (size_t i = 0; i < groups_len; i++) {
-      if (groups[i] == group_id) {
-        found = 1;
-        break;
-      }
-    }
-
-    if (!found) {
+    if (!tls1_check_group_id(ssl, group_id)) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
       OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
       return ssl_hs_error;
@@ -336,22 +325,16 @@
   }
 
   // Resolve ECDHE and incorporate it into the secret.
-  uint8_t *dhe_secret;
-  size_t dhe_secret_len;
+  Array<uint8_t> dhe_secret;
   alert = SSL_AD_DECODE_ERROR;
-  if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &dhe_secret_len,
-                                           &alert, &key_share)) {
+  if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &alert,
+                                           &key_share)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
     return ssl_hs_error;
   }
 
-  if (!tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len)) {
-    OPENSSL_free(dhe_secret);
-    return ssl_hs_error;
-  }
-  OPENSSL_free(dhe_secret);
-
-  if (!ssl_hash_message(hs, msg) ||
+  if (!tls13_advance_key_schedule(hs, dhe_secret.data(), dhe_secret.size()) ||
+      !ssl_hash_message(hs, msg) ||
       !tls13_derive_handshake_secrets(hs)) {
     return ssl_hs_error;
   }
@@ -856,12 +839,4 @@
   return 1;
 }
 
-void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) {
-  hs->key_share.reset();
-
-  OPENSSL_free(hs->key_share_bytes);
-  hs->key_share_bytes = NULL;
-  hs->key_share_bytes_len = 0;
-}
-
 }  // namespace bssl
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 550f3b5..ea1beae 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -74,12 +74,10 @@
   }
 
   bool found_key_share;
-  uint8_t *dhe_secret;
-  size_t dhe_secret_len;
+  Array<uint8_t> dhe_secret;
   uint8_t alert = SSL_AD_DECODE_ERROR;
   if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret,
-                                           &dhe_secret_len, &alert,
-                                           &key_share)) {
+                                           &alert, &key_share)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
     return 0;
   }
@@ -89,9 +87,7 @@
     return 0;
   }
 
-  int ok = tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len);
-  OPENSSL_free(dhe_secret);
-  return ok;
+  return tls13_advance_key_schedule(hs, dhe_secret.data(), dhe_secret.size());
 }
 
 static int ssl_ext_supported_versions_add_serverhello(SSL_HANDSHAKE *hs,
diff --git a/src/util/all_tests.go b/src/util/all_tests.go
index ef23080..d5794fc 100644
--- a/src/util/all_tests.go
+++ b/src/util/all_tests.go
@@ -48,7 +48,8 @@
 )
 
 type test struct {
-	args []string
+	args             []string
+	shard, numShards int
 	// cpu, if not empty, contains an Intel CPU code to simulate. Run
 	// `sde64 -help` to get a list of these codes.
 	cpu string
@@ -259,19 +260,6 @@
 	}
 }
 
-// shortTestName returns the short name of a test. Except for evp_test and
-// cipher_test, it assumes that any argument which ends in .txt is a path to a
-// data file and not relevant to the test's uniqueness.
-func shortTestName(test test) string {
-	var args []string
-	for _, arg := range test.args {
-		if test.args[0] == "crypto/evp/evp_test" || test.args[0] == "crypto/cipher_extra/cipher_test" || test.args[0] == "crypto/cipher_extra/aead_test" || !strings.HasSuffix(arg, ".txt") || strings.HasPrefix(arg, "--gtest_filter=") {
-			args = append(args, arg)
-		}
-	}
-	return strings.Join(args, " ") + test.cpuMsg()
-}
-
 // setWorkingDirectory walks up directories as needed until the current working
 // directory is the top of a BoringSSL checkout.
 func setWorkingDirectory() {
@@ -313,6 +301,22 @@
 	}
 }
 
+func (t test) shortName() string {
+	return t.args[0] + t.shardMsg() + t.cpuMsg()
+}
+
+func (t test) longName() string {
+	return strings.Join(t.args, " ") + t.cpuMsg()
+}
+
+func (t test) shardMsg() string {
+	if t.numShards == 0 {
+		return ""
+	}
+
+	return fmt.Sprintf(" [shard %d/%d]", t.shard+1, t.numShards)
+}
+
 func (t test) cpuMsg() string {
 	if len(t.cpu) == 0 {
 		return ""
@@ -389,9 +393,14 @@
 		}
 		shard := t
 		shard.args = []string{shard.args[0], "--gtest_filter=" + strings.Join(shuffled[i:i+n], ":")}
+		shard.shard = len(shards)
 		shards = append(shards, shard)
 	}
 
+	for i := range shards {
+		shards[i].numShards = len(shards)
+	}
+
 	return shards, nil
 }
 
@@ -447,18 +456,19 @@
 		test := testResult.Test
 		args := test.args
 
-		fmt.Printf("%s%s\n", strings.Join(args, " "), test.cpuMsg())
-		name := shortTestName(test)
 		if testResult.Error != nil {
+			fmt.Printf("%s\n", test.longName())
 			fmt.Printf("%s failed to complete: %s\n", args[0], testResult.Error)
 			failed = append(failed, test)
-			testOutput.addResult(name, "CRASHED")
+			testOutput.addResult(test.longName(), "CRASHED")
 		} else if !testResult.Passed {
+			fmt.Printf("%s\n", test.longName())
 			fmt.Printf("%s failed to print PASS on the last line.\n", args[0])
 			failed = append(failed, test)
-			testOutput.addResult(name, "FAIL")
+			testOutput.addResult(test.longName(), "FAIL")
 		} else {
-			testOutput.addResult(name, "PASS")
+			fmt.Printf("%s\n", test.shortName())
+			testOutput.addResult(test.longName(), "PASS")
 		}
 	}