external/boringssl: Sync to c9827e073f64e353c4891ecc2c73721882543ee0.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/387b07b78dac785a341eeb2ff86e29393ffe8627..c9827e073f64e353c4891ecc2c73721882543ee0

Test: atest CtsLibcoreTestCases (TODO)
Change-Id: Ie7c2899ac4ea374113e0fe3b76f9a4dce36ea8de
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fd35326..4cfbcc5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -204,6 +204,7 @@
               # copy constructor is inaccessible or deleted
       "C4626" # assignment operator could not be generated because a base class
               # assignment operator is inaccessible or deleted
+      "C4628" # digraphs not supported with -Ze
       "C4668" # 'symbol' is not defined as a preprocessor macro, replacing with
               # '0' for 'directives'
               # Disable this because GTest uses it everywhere.
diff --git a/src/crypto/base64/base64_test.cc b/src/crypto/base64/base64_test.cc
index 28b5c8e..9122dee 100644
--- a/src/crypto/base64/base64_test.cc
+++ b/src/crypto/base64/base64_test.cc
@@ -105,7 +105,7 @@
 
 class Base64Test : public testing::TestWithParam<TestVector> {};
 
-INSTANTIATE_TEST_CASE_P(, Base64Test, testing::ValuesIn(kTestVectors));
+INSTANTIATE_TEST_SUITE_P(, Base64Test, testing::ValuesIn(kTestVectors));
 
 // RemoveNewlines returns a copy of |in| with all '\n' characters removed.
 static std::string RemoveNewlines(const char *in) {
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 8479c8e..797a733 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -220,7 +220,7 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
+INSTANTIATE_TEST_SUITE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
 
 // Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
 class BIOPairTest : public testing::TestWithParam<bool> {};
@@ -322,4 +322,4 @@
   EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
 }
 
-INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(, BIOPairTest, testing::Values(false, true));
diff --git a/src/crypto/bytestring/cbb.c b/src/crypto/bytestring/cbb.c
index 7998a48..1ddc73c 100644
--- a/src/crypto/bytestring/cbb.c
+++ b/src/crypto/bytestring/cbb.c
@@ -44,7 +44,7 @@
   base->error = 0;
 
   cbb->base = base;
-  cbb->is_top_level = 1;
+  cbb->is_child = 0;
   return 1;
 }
 
@@ -76,11 +76,14 @@
 }
 
 void CBB_cleanup(CBB *cbb) {
-  if (cbb->base) {
-    // Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
-    // are implicitly discarded when the parent is flushed or cleaned up.
-    assert(cbb->is_top_level);
+  // Child |CBB|s are non-owning. They are implicitly discarded and should not
+  // be used with |CBB_cleanup| or |ScopedCBB|.
+  assert(!cbb->is_child);
+  if (cbb->is_child) {
+    return;
+  }
 
+  if (cbb->base) {
     if (cbb->base->can_resize) {
       OPENSSL_free(cbb->base->buf);
     }
@@ -169,7 +172,7 @@
 }
 
 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
-  if (!cbb->is_top_level) {
+  if (cbb->is_child) {
     return 0;
   }
 
@@ -310,6 +313,7 @@
   OPENSSL_memset(prefix_bytes, 0, len_len);
   OPENSSL_memset(out_contents, 0, sizeof(CBB));
   out_contents->base = cbb->base;
+  out_contents->is_child = 1;
   cbb->child = out_contents;
   cbb->child->offset = offset;
   cbb->child->pending_len_len = len_len;
@@ -381,6 +385,7 @@
 
   OPENSSL_memset(out_contents, 0, sizeof(CBB));
   out_contents->base = cbb->base;
+  out_contents->is_child = 1;
   cbb->child = out_contents;
   cbb->child->offset = offset;
   cbb->child->pending_len_len = 1;
diff --git a/src/crypto/cipher_extra/aead_test.cc b/src/crypto/cipher_extra/aead_test.cc
index fff7d43..25924bd 100644
--- a/src/crypto/cipher_extra/aead_test.cc
+++ b/src/crypto/cipher_extra/aead_test.cc
@@ -42,58 +42,58 @@
   // truncated_tags is true if the AEAD supports truncating tags to arbitrary
   // lengths.
   bool truncated_tags;
+  // variable_nonce is true if the AEAD supports a variable nonce length.
+  bool variable_nonce;
   // ad_len, if non-zero, is the required length of the AD.
   size_t ad_len;
 };
 
 static const struct KnownAEAD kAEADs[] = {
     {"AES_128_GCM", EVP_aead_aes_128_gcm, "aes_128_gcm_tests.txt", false, true,
-     0},
+     true, 0},
     {"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
-     false, true, 0},
+     false, true, true, 0},
     {"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true,
-     0},
+     true, 0},
     {"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
-     false, true, 0},
-#if !defined(OPENSSL_SMALL)
+     false, true, true, 0},
     {"AES_128_GCM_SIV", EVP_aead_aes_128_gcm_siv, "aes_128_gcm_siv_tests.txt",
-     false, false, 0},
+     false, false, false, 0},
     {"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
-     false, false, 0},
-#endif
+     false, false, false, 0},
     {"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
-     "chacha20_poly1305_tests.txt", false, true, 0},
+     "chacha20_poly1305_tests.txt", false, true, false, 0},
     {"XChaCha20Poly1305", EVP_aead_xchacha20_poly1305,
-     "xchacha20_poly1305_tests.txt", false, true, 0},
+     "xchacha20_poly1305_tests.txt", false, true, false, 0},
     {"AES_128_CBC_SHA1_TLS", EVP_aead_aes_128_cbc_sha1_tls,
-     "aes_128_cbc_sha1_tls_tests.txt", true, false, 11},
+     "aes_128_cbc_sha1_tls_tests.txt", true, false, false, 11},
     {"AES_128_CBC_SHA1_TLSImplicitIV",
      EVP_aead_aes_128_cbc_sha1_tls_implicit_iv,
-     "aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
+     "aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
     {"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
-     "aes_128_cbc_sha256_tls_tests.txt", true, false, 11},
+     "aes_128_cbc_sha256_tls_tests.txt", true, false, false, 11},
     {"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
-     "aes_256_cbc_sha1_tls_tests.txt", true, false, 11},
+     "aes_256_cbc_sha1_tls_tests.txt", true, false, false, 11},
     {"AES_256_CBC_SHA1_TLSImplicitIV",
      EVP_aead_aes_256_cbc_sha1_tls_implicit_iv,
-     "aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
+     "aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
     {"AES_256_CBC_SHA256_TLS", EVP_aead_aes_256_cbc_sha256_tls,
-     "aes_256_cbc_sha256_tls_tests.txt", true, false, 11},
+     "aes_256_cbc_sha256_tls_tests.txt", true, false, false, 11},
     {"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
-     "aes_256_cbc_sha384_tls_tests.txt", true, false, 11},
+     "aes_256_cbc_sha384_tls_tests.txt", true, false, false, 11},
     {"DES_EDE3_CBC_SHA1_TLS", EVP_aead_des_ede3_cbc_sha1_tls,
-     "des_ede3_cbc_sha1_tls_tests.txt", true, false, 11},
+     "des_ede3_cbc_sha1_tls_tests.txt", true, false, false, 11},
     {"DES_EDE3_CBC_SHA1_TLSImplicitIV",
      EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv,
-     "des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
+     "des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, false, 11},
     {"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256,
-     "aes_128_ctr_hmac_sha256.txt", false, true, 0},
+     "aes_128_ctr_hmac_sha256.txt", false, true, false, 0},
     {"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
-     "aes_256_ctr_hmac_sha256.txt", false, true, 0},
+     "aes_256_ctr_hmac_sha256.txt", false, true, false, 0},
     {"AES_128_CCM_BLUETOOTH", EVP_aead_aes_128_ccm_bluetooth,
-     "aes_128_ccm_bluetooth_tests.txt", false, false, 0},
+     "aes_128_ccm_bluetooth_tests.txt", false, false, false, 0},
     {"AES_128_CCM_BLUETOOTH_8", EVP_aead_aes_128_ccm_bluetooth_8,
-     "aes_128_ccm_bluetooth_8_tests.txt", false, false, 0},
+     "aes_128_ccm_bluetooth_8_tests.txt", false, false, false, 0},
 };
 
 class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
@@ -101,9 +101,9 @@
   const EVP_AEAD *aead() { return GetParam().func(); }
 };
 
-INSTANTIATE_TEST_CASE_P(, PerAEADTest, testing::ValuesIn(kAEADs),
-                        [](const testing::TestParamInfo<KnownAEAD> &params)
-                            -> std::string { return params.param.name; });
+INSTANTIATE_TEST_SUITE_P(, PerAEADTest, testing::ValuesIn(kAEADs),
+                         [](const testing::TestParamInfo<KnownAEAD> &params)
+                             -> std::string { return params.param.name; });
 
 // Tests an AEAD against a series of test vectors from a file, using the
 // FileTest format. As an example, here's a valid test case:
@@ -607,50 +607,59 @@
   // as the input.)
 }
 
-// Test that EVP_aead_aes_128_gcm and EVP_aead_aes_256_gcm reject empty nonces.
-// AES-GCM is not defined for those.
-TEST(AEADTest, AESGCMEmptyNonce) {
-  static const uint8_t kZeros[32] = {0};
+TEST_P(PerAEADTest, InvalidNonceLength) {
+  size_t valid_nonce_len = EVP_AEAD_nonce_length(aead());
+  std::vector<size_t> nonce_lens;
+  if (valid_nonce_len != 0) {
+    // Other than the implicit IV TLS "AEAD"s, none of our AEADs allow empty
+    // nonces. In particular, although AES-GCM was incorrectly specified with
+    // variable-length nonces, it does not allow the empty nonce.
+    nonce_lens.push_back(0);
+  }
+  if (!GetParam().variable_nonce) {
+    nonce_lens.push_back(valid_nonce_len + 1);
+    if (valid_nonce_len != 0) {
+      nonce_lens.push_back(valid_nonce_len - 1);
+    }
+  }
 
-  // Test AES-128-GCM.
-  uint8_t buf[16];
-  size_t len;
-  bssl::ScopedEVP_AEAD_CTX ctx;
-  ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), kZeros, 16,
-                                EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
+  static const uint8_t kZeros[EVP_AEAD_MAX_KEY_LENGTH] = {0};
+  const size_t ad_len = GetParam().ad_len != 0 ? GetParam().ad_len : 16;
+  ASSERT_LE(ad_len, sizeof(kZeros));
 
-  EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
-                                 nullptr /* nonce */, 0, nullptr /* in */, 0,
-                                 nullptr /* ad */, 0));
-  uint32_t err = ERR_get_error();
-  EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
-  EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
+  for (size_t nonce_len : nonce_lens) {
+    SCOPED_TRACE(nonce_len);
+    uint8_t buf[256];
+    size_t len;
+    std::vector<uint8_t> nonce(nonce_len);
+    bssl::ScopedEVP_AEAD_CTX ctx;
+    ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
+        ctx.get(), aead(), kZeros, EVP_AEAD_key_length(aead()),
+        EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_seal));
 
-  EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
-                                 nullptr /* nonce */, 0, kZeros /* in */,
-                                 sizeof(kZeros), nullptr /* ad */, 0));
-  err = ERR_get_error();
-  EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
-  EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
+    EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
+                                   nonce.data(), nonce.size(), nullptr /* in */,
+                                   0, kZeros /* ad */, ad_len));
+    uint32_t err = ERR_get_error();
+    EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
+    // TODO(davidben): Merge these errors. https://crbug.com/boringssl/129.
+    if (ERR_GET_REASON(err) != CIPHER_R_UNSUPPORTED_NONCE_SIZE) {
+      EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
+    }
 
-  // Test AES-256-GCM.
-  ctx.Reset();
-  ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(), kZeros, 32,
-                                EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
-
-  EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
-                                 nullptr /* nonce */, 0, nullptr /* in */, 0,
-                                 nullptr /* ad */, 0));
-  err = ERR_get_error();
-  EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
-  EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
-
-  EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
-                                 nullptr /* nonce */, 0, kZeros /* in */,
-                                 sizeof(kZeros), nullptr /* ad */, 0));
-  err = ERR_get_error();
-  EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
-  EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
+    ctx.Reset();
+    ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
+        ctx.get(), aead(), kZeros, EVP_AEAD_key_length(aead()),
+        EVP_AEAD_DEFAULT_TAG_LENGTH, evp_aead_open));
+    EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
+                                   nonce.data(), nonce.size(), kZeros /* in */,
+                                   sizeof(kZeros), kZeros /* ad */, ad_len));
+    err = ERR_get_error();
+    EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
+    if (ERR_GET_REASON(err) != CIPHER_R_UNSUPPORTED_NONCE_SIZE) {
+      EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
+    }
+  }
 }
 
 TEST(AEADTest, AESCCMLargeAD) {
diff --git a/src/crypto/cipher_extra/cipher_test.cc b/src/crypto/cipher_extra/cipher_test.cc
index 62ef939..0a96bf3 100644
--- a/src/crypto/cipher_extra/cipher_test.cc
+++ b/src/crypto/cipher_extra/cipher_test.cc
@@ -150,7 +150,8 @@
 }
 
 static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
-                          size_t chunk_size, const std::vector<uint8_t> &key,
+                          bool copy, size_t chunk_size,
+                          const std::vector<uint8_t> &key,
                           const std::vector<uint8_t> &iv,
                           const std::vector<uint8_t> &plaintext,
                           const std::vector<uint8_t> &ciphertext,
@@ -167,45 +168,52 @@
 
   bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
 
-  bssl::ScopedEVP_CIPHER_CTX ctx;
-  ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
-                         encrypt ? 1 : 0));
+  bssl::ScopedEVP_CIPHER_CTX ctx1;
+  ASSERT_TRUE(EVP_CipherInit_ex(ctx1.get(), cipher, nullptr, nullptr, nullptr,
+                                encrypt ? 1 : 0));
   if (t->HasAttribute("IV")) {
     if (is_aead) {
-      ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_IVLEN,
+      ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx1.get(), EVP_CTRL_AEAD_SET_IVLEN,
                                       iv.size(), 0));
     } else {
-      ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get()));
+      ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx1.get()));
     }
   }
+
+  bssl::ScopedEVP_CIPHER_CTX ctx2;
+  EVP_CIPHER_CTX *ctx = ctx1.get();
+  if (copy) {
+    ASSERT_TRUE(EVP_CIPHER_CTX_copy(ctx2.get(), ctx1.get()));
+    ctx = ctx2.get();
+  }
+
   if (is_aead && !encrypt) {
-    ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_TAG,
-                                    tag.size(),
+    ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size(),
                                     const_cast<uint8_t *>(tag.data())));
   }
   // The ciphers are run with no padding. For each of the ciphers we test, the
   // output size matches the input size.
   ASSERT_EQ(in->size(), out->size());
-  ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()));
-  ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(),
-                                iv.data(), -1));
+  ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx, key.size()));
+  ASSERT_TRUE(
+      EVP_CipherInit_ex(ctx, nullptr, nullptr, key.data(), iv.data(), -1));
   // Note: the deprecated |EVP_CIPHER|-based AEAD API is sensitive to whether
   // parameters are NULL, so it is important to skip the |in| and |aad|
   // |EVP_CipherUpdate| calls when empty.
   if (!aad.empty()) {
     int unused;
     ASSERT_TRUE(
-        EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(), aad.size()));
+        EVP_CipherUpdate(ctx, nullptr, &unused, aad.data(), aad.size()));
   }
-  ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0));
+  ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx, 0));
   std::vector<uint8_t> result;
-  ASSERT_TRUE(DoCipher(ctx.get(), &result, *in, chunk_size));
+  ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size));
   EXPECT_EQ(Bytes(*out), Bytes(result));
   if (encrypt && is_aead) {
     uint8_t rtag[16];
     ASSERT_LE(tag.size(), sizeof(rtag));
-    ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG,
-                                    tag.size(), rtag));
+    ASSERT_TRUE(
+        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag.size(), rtag));
     EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size()));
   }
 }
@@ -252,14 +260,18 @@
     // By default, both directions are run, unless overridden by the operation.
     if (operation != kDecrypt) {
       SCOPED_TRACE("encrypt");
-      TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
-                    plaintext, ciphertext, aad, tag);
+      TestOperation(t, cipher, true /* encrypt */, false /* no copy */,
+                    chunk_size, key, iv, plaintext, ciphertext, aad, tag);
+      TestOperation(t, cipher, true /* encrypt */, true /* copy */, chunk_size,
+                    key, iv, plaintext, ciphertext, aad, tag);
     }
 
     if (operation != kEncrypt) {
       SCOPED_TRACE("decrypt");
-      TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
-                    plaintext, ciphertext, aad, tag);
+      TestOperation(t, cipher, false /* decrypt */, false /* no copy */,
+                    chunk_size, key, iv, plaintext, ciphertext, aad, tag);
+      TestOperation(t, cipher, false /* decrypt */, true /* copy */, chunk_size,
+                    key, iv, plaintext, ciphertext, aad, tag);
     }
   }
 }
diff --git a/src/crypto/cipher_extra/e_aesgcmsiv.c b/src/crypto/cipher_extra/e_aesgcmsiv.c
index 71a71fa..64febae 100644
--- a/src/crypto/cipher_extra/e_aesgcmsiv.c
+++ b/src/crypto/cipher_extra/e_aesgcmsiv.c
@@ -426,6 +426,11 @@
     return 0;
   }
 
+  if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
   const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx);
   const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
   const uint8_t *const given_tag = in + plaintext_len;
diff --git a/src/crypto/digest_extra/digest_test.cc b/src/crypto/digest_extra/digest_test.cc
index de2e9d1..7d07c04 100644
--- a/src/crypto/digest_extra/digest_test.cc
+++ b/src/crypto/digest_extra/digest_test.cc
@@ -198,6 +198,28 @@
   ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len));
   CompareDigest(test, digest.get(), digest_len);
 
+  // Make a copy of the digest in the initial state.
+  ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL));
+  bssl::ScopedEVP_MD_CTX copy;
+  ASSERT_TRUE(EVP_MD_CTX_copy_ex(copy.get(), ctx.get()));
+  for (size_t i = 0; i < test->repeat; i++) {
+    ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input)));
+  }
+  ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len));
+  CompareDigest(test, digest.get(), digest_len);
+
+  // Make a copy of the digest with half the input provided.
+  size_t half = strlen(test->input) / 2;
+  ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), test->input, half));
+  ASSERT_TRUE(EVP_MD_CTX_copy_ex(copy.get(), ctx.get()));
+  ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input + half,
+                               strlen(test->input) - half));
+  for (size_t i = 1; i < test->repeat; i++) {
+    ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input)));
+  }
+  ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len));
+  CompareDigest(test, digest.get(), digest_len);
+
   // Test the one-shot function.
   if (test->md.one_shot_func && test->repeat == 1) {
     uint8_t *out = test->md.one_shot_func((const uint8_t *)test->input,
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc
index 6571c30..4d74292 100644
--- a/src/crypto/evp/evp_test.cc
+++ b/src/crypto/evp/evp_test.cc
@@ -297,16 +297,19 @@
   }
 
   if (md_op_init) {
-    bssl::ScopedEVP_MD_CTX ctx;
+    bssl::ScopedEVP_MD_CTX ctx, copy;
     EVP_PKEY_CTX *pctx;
     if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) ||
-        !SetupContext(t, pctx)) {
+        !SetupContext(t, pctx) ||
+        !EVP_MD_CTX_copy_ex(copy.get(), ctx.get())) {
       return false;
     }
 
     if (is_verify) {
-      return !!EVP_DigestVerify(ctx.get(), output.data(), output.size(),
-                                input.data(), input.size());
+      return EVP_DigestVerify(ctx.get(), output.data(), output.size(),
+                              input.data(), input.size()) &&
+             EVP_DigestVerify(copy.get(), output.data(), output.size(),
+                              input.data(), input.size());
     }
 
     size_t len;
@@ -321,6 +324,21 @@
     }
     actual.resize(len);
     EXPECT_EQ(Bytes(output), Bytes(actual));
+
+    // Repeat the test with |copy|, to check |EVP_MD_CTX_copy_ex| duplicated
+    // everything.
+    if (!EVP_DigestSign(copy.get(), nullptr, &len, input.data(),
+                        input.size())) {
+      return false;
+    }
+    actual.resize(len);
+    if (!EVP_DigestSign(copy.get(), actual.data(), &len, input.data(),
+                        input.size()) ||
+        !t->GetBytes(&output, "Output")) {
+      return false;
+    }
+    actual.resize(len);
+    EXPECT_EQ(Bytes(output), Bytes(actual));
     return true;
   }
 
@@ -333,72 +351,78 @@
     return false;
   }
 
+  bssl::UniquePtr<EVP_PKEY_CTX> copy(EVP_PKEY_CTX_dup(ctx.get()));
+  if (!copy) {
+    return false;
+  }
+
   if (is_verify) {
-    return !!EVP_PKEY_verify(ctx.get(), output.data(), output.size(),
-                             input.data(), input.size());
+    return EVP_PKEY_verify(ctx.get(), output.data(), output.size(),
+                           input.data(), input.size()) &&
+           EVP_PKEY_verify(copy.get(), output.data(), output.size(),
+                           input.data(), input.size());
   }
 
-  size_t len;
-  if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
-    return false;
-  }
-  actual.resize(len);
-  if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) {
-    return false;
-  }
+  for (EVP_PKEY_CTX *pctx : {ctx.get(), copy.get()}) {
+    size_t len;
+    if (!key_op(pctx, nullptr, &len, input.data(), input.size())) {
+      return false;
+    }
+    actual.resize(len);
+    if (!key_op(pctx, actual.data(), &len, input.data(), input.size())) {
+      return false;
+    }
 
-  // Encryption is non-deterministic, so we check by decrypting.
-  if (t->HasAttribute("CheckDecrypt")) {
-    size_t plaintext_len;
-    ctx.reset(EVP_PKEY_CTX_new(key, nullptr));
-    if (!ctx ||
-        !EVP_PKEY_decrypt_init(ctx.get()) ||
-        (digest != nullptr &&
-         !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) ||
-        !SetupContext(t, ctx.get()) ||
-        !EVP_PKEY_decrypt(ctx.get(), nullptr, &plaintext_len, actual.data(),
-                          actual.size())) {
-      return false;
+    if (t->HasAttribute("CheckDecrypt")) {
+      // Encryption is non-deterministic, so we check by decrypting.
+      size_t plaintext_len;
+      bssl::UniquePtr<EVP_PKEY_CTX> decrypt_ctx(EVP_PKEY_CTX_new(key, nullptr));
+      if (!decrypt_ctx ||
+          !EVP_PKEY_decrypt_init(decrypt_ctx.get()) ||
+          (digest != nullptr &&
+           !EVP_PKEY_CTX_set_signature_md(decrypt_ctx.get(), digest)) ||
+          !SetupContext(t, decrypt_ctx.get()) ||
+          !EVP_PKEY_decrypt(decrypt_ctx.get(), nullptr, &plaintext_len,
+                            actual.data(), actual.size())) {
+        return false;
+      }
+      output.resize(plaintext_len);
+      if (!EVP_PKEY_decrypt(decrypt_ctx.get(), output.data(), &plaintext_len,
+                            actual.data(), actual.size())) {
+        ADD_FAILURE() << "Could not decrypt result.";
+        return false;
+      }
+      output.resize(plaintext_len);
+      EXPECT_EQ(Bytes(input), Bytes(output)) << "Decrypted result mismatch.";
+    } else if (t->HasAttribute("CheckVerify")) {
+      // Some signature schemes are non-deterministic, so we check by verifying.
+      bssl::UniquePtr<EVP_PKEY_CTX> verify_ctx(EVP_PKEY_CTX_new(key, nullptr));
+      if (!verify_ctx ||
+          !EVP_PKEY_verify_init(verify_ctx.get()) ||
+          (digest != nullptr &&
+           !EVP_PKEY_CTX_set_signature_md(verify_ctx.get(), digest)) ||
+          !SetupContext(t, verify_ctx.get())) {
+        return false;
+      }
+      if (t->HasAttribute("VerifyPSSSaltLength")) {
+        if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(
+                verify_ctx.get(),
+                atoi(t->GetAttributeOrDie("VerifyPSSSaltLength").c_str()))) {
+          return false;
+        }
+      }
+      EXPECT_TRUE(EVP_PKEY_verify(verify_ctx.get(), actual.data(),
+                                  actual.size(), input.data(), input.size()))
+          << "Could not verify result.";
+    } else {
+      // By default, check by comparing the result against Output.
+      if (!t->GetBytes(&output, "Output")) {
+        return false;
+      }
+      actual.resize(len);
+      EXPECT_EQ(Bytes(output), Bytes(actual));
     }
-    output.resize(plaintext_len);
-    if (!EVP_PKEY_decrypt(ctx.get(), output.data(), &plaintext_len,
-                          actual.data(), actual.size())) {
-      ADD_FAILURE() << "Could not decrypt result.";
-      return false;
-    }
-    output.resize(plaintext_len);
-    EXPECT_EQ(Bytes(input), Bytes(output)) << "Decrypted result mismatch.";
-    return true;
   }
-
-  // Some signature schemes are non-deterministic, so we check by verifying.
-  if (t->HasAttribute("CheckVerify")) {
-    ctx.reset(EVP_PKEY_CTX_new(key, nullptr));
-    if (!ctx ||
-        !EVP_PKEY_verify_init(ctx.get()) ||
-        (digest != nullptr &&
-         !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) ||
-        !SetupContext(t, ctx.get())) {
-      return false;
-    }
-    if (t->HasAttribute("VerifyPSSSaltLength") &&
-        !EVP_PKEY_CTX_set_rsa_pss_saltlen(
-            ctx.get(),
-            atoi(t->GetAttributeOrDie("VerifyPSSSaltLength").c_str()))) {
-      return false;
-    }
-    EXPECT_TRUE(EVP_PKEY_verify(ctx.get(), actual.data(), actual.size(),
-                                input.data(), input.size()))
-        << "Could not verify result.";
-    return true;
-  }
-
-  // By default, check by comparing the result against Output.
-  if (!t->GetBytes(&output, "Output")) {
-    return false;
-  }
-  actual.resize(len);
-  EXPECT_EQ(Bytes(output), Bytes(actual));
   return true;
 }
 
diff --git a/src/crypto/evp/evp_tests.txt b/src/crypto/evp/evp_tests.txt
index ff08ee7..9dbe1cb 100644
--- a/src/crypto/evp/evp_tests.txt
+++ b/src/crypto/evp/evp_tests.txt
@@ -274,6 +274,17 @@
 Input = "0123456789ABCDEF0123456789ABCDEF"
 CheckVerify
 
+# Check a salt length with a non-standard digest length, to verify things are
+# not just working due to defaults. (The current default is a maximum salt
+# length, but the ecosystem has converged on matching the digest length, so we
+# may change this in the future.)
+Sign = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 42
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+CheckVerify
+
 # Auto-detected salt length
 Verify = RSA-2048-SPKI
 RSAPadding = PSS
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
index eb59901..865b36a 100644
--- a/src/crypto/evp/p_rsa.c
+++ b/src/crypto/evp/p_rsa.c
@@ -132,6 +132,7 @@
   dctx->pad_mode = sctx->pad_mode;
   dctx->md = sctx->md;
   dctx->mgf1md = sctx->mgf1md;
+  dctx->saltlen = sctx->saltlen;
   if (sctx->oaep_label) {
     OPENSSL_free(dctx->oaep_label);
     dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
diff --git a/src/crypto/fipsmodule/aes/aes.c b/src/crypto/fipsmodule/aes/aes.c
index 8a1ca31..48d60ee 100644
--- a/src/crypto/fipsmodule/aes/aes.c
+++ b/src/crypto/fipsmodule/aes/aes.c
@@ -834,6 +834,9 @@
 }
 
 int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+  if (bits != 128 && bits != 192 && bits != 256) {
+    return -2;
+  }
   if (hwaes_capable()) {
     return aes_hw_set_encrypt_key(key, bits, aeskey);
   } else if (vpaes_capable()) {
@@ -844,6 +847,9 @@
 }
 
 int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+  if (bits != 128 && bits != 192 && bits != 256) {
+    return -2;
+  }
   if (hwaes_capable()) {
     return aes_hw_set_decrypt_key(key, bits, aeskey);
   } else if (vpaes_capable()) {
diff --git a/src/crypto/fipsmodule/aes/aes_test.cc b/src/crypto/fipsmodule/aes/aes_test.cc
index 2222b63..1f9a491 100644
--- a/src/crypto/fipsmodule/aes/aes_test.cc
+++ b/src/crypto/fipsmodule/aes/aes_test.cc
@@ -189,6 +189,13 @@
   }
 }
 
+TEST(AESTest, InvalidKeySize) {
+  static const uint8_t kZero[8] = {0};
+  AES_KEY key;
+  EXPECT_LT(AES_set_encrypt_key(kZero, 42, &key), 0);
+  EXPECT_LT(AES_set_decrypt_key(kZero, 42, &key), 0);
+}
+
 #if defined(SUPPORTS_ABI_TEST)
 TEST(AESTest, ABI) {
   for (int bits : {128, 192, 256}) {
diff --git a/src/crypto/fipsmodule/cipher/e_aes.c b/src/crypto/fipsmodule/cipher/e_aes.c
index dc94166..1ea012d 100644
--- a/src/crypto/fipsmodule/cipher/e_aes.c
+++ b/src/crypto/fipsmodule/cipher/e_aes.c
@@ -456,6 +456,9 @@
     case EVP_CTRL_COPY: {
       EVP_CIPHER_CTX *out = ptr;
       EVP_AES_GCM_CTX *gctx_out = aes_gcm_from_cipher_ctx(out);
+      // |EVP_CIPHER_CTX_copy| copies this generically, but we must redo it in
+      // case |out->cipher_data| and |in->cipher_data| are differently aligned.
+      OPENSSL_memcpy(gctx_out, gctx, sizeof(EVP_AES_GCM_CTX));
       if (gctx->iv == c->iv) {
         gctx_out->iv = out->iv;
       } else {
@@ -590,7 +593,7 @@
   out->key_len = 16;
   out->iv_len = 12;
   out->ctx_size = sizeof(EVP_AES_GCM_CTX) + EVP_AES_GCM_CTX_PADDING;
-  out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
+  out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_CUSTOM_COPY |
                EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
                EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
   out->init = aes_gcm_init_key;
@@ -658,7 +661,7 @@
   out->key_len = 24;
   out->iv_len = 12;
   out->ctx_size = sizeof(EVP_AES_GCM_CTX) + EVP_AES_GCM_CTX_PADDING;
-  out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
+  out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_CUSTOM_COPY |
                EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
                EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
   out->init = aes_gcm_init_key;
@@ -726,7 +729,7 @@
   out->key_len = 32;
   out->iv_len = 12;
   out->ctx_size = sizeof(EVP_AES_GCM_CTX) + EVP_AES_GCM_CTX_PADDING;
-  out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
+  out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_CUSTOM_COPY |
                EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
                EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
   out->init = aes_gcm_init_key;
diff --git a/src/crypto/fipsmodule/digest/digest.c b/src/crypto/fipsmodule/digest/digest.c
index e49d552..6705867 100644
--- a/src/crypto/fipsmodule/digest/digest.c
+++ b/src/crypto/fipsmodule/digest/digest.c
@@ -116,7 +116,9 @@
 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) {
+  // |in->digest| may be NULL if this is a signing |EVP_MD_CTX| for, e.g.,
+  // Ed25519 which does not hash with |EVP_MD_CTX|.
+  if (in == NULL || (in->pctx == NULL && in->digest == NULL)) {
     OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED);
     return 0;
   }
@@ -131,29 +133,34 @@
     }
   }
 
-  uint8_t *tmp_buf;
-  if (out->digest != in->digest) {
-    assert(in->digest->ctx_size != 0);
-    tmp_buf = OPENSSL_malloc(in->digest->ctx_size);
-    if (tmp_buf == NULL) {
-      if (pctx) {
-        in->pctx_ops->free(pctx);
+  uint8_t *tmp_buf = NULL;
+  if (in->digest != NULL) {
+    if (out->digest != in->digest) {
+      assert(in->digest->ctx_size != 0);
+      tmp_buf = OPENSSL_malloc(in->digest->ctx_size);
+      if (tmp_buf == NULL) {
+        if (pctx) {
+          in->pctx_ops->free(pctx);
+        }
+        OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+        return 0;
       }
-      OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
-      return 0;
+    } else {
+      // |md_data| will be the correct size in this case. It's removed from
+      // |out| so that |EVP_MD_CTX_cleanup| doesn't free it, and then it's
+      // reused.
+      tmp_buf = out->md_data;
+      out->md_data = NULL;
     }
-  } else {
-    // |md_data| will be the correct size in this case. It's removed from |out|
-    // so that |EVP_MD_CTX_cleanup| doesn't free it, and then it's reused.
-    tmp_buf = out->md_data;
-    out->md_data = NULL;
   }
 
   EVP_MD_CTX_cleanup(out);
 
   out->digest = in->digest;
   out->md_data = tmp_buf;
-  OPENSSL_memcpy(out->md_data, in->md_data, in->digest->ctx_size);
+  if (in->digest != NULL) {
+    OPENSSL_memcpy(out->md_data, in->md_data, in->digest->ctx_size);
+  }
   out->pctx = pctx;
   out->pctx_ops = in->pctx_ops;
   assert(out->pctx == NULL || out->pctx_ops != NULL);
diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc
index dd4c75a..1219e2b 100644
--- a/src/crypto/fipsmodule/ec/ec_test.cc
+++ b/src/crypto/fipsmodule/ec/ec_test.cc
@@ -792,8 +792,8 @@
   return OBJ_nid2sn(params.param.nid);
 }
 
-INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
-                        CurveToString);
+INSTANTIATE_TEST_SUITE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
+                         CurveToString);
 
 static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
   std::string curve_name;
diff --git a/src/crypto/rsa_extra/rsa_test.cc b/src/crypto/rsa_extra/rsa_test.cc
index 9bd47b1..ed1630d 100644
--- a/src/crypto/rsa_extra/rsa_test.cc
+++ b/src/crypto/rsa_extra/rsa_test.cc
@@ -461,7 +461,8 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(, RSAEncryptTest, testing::ValuesIn(kRSAEncryptParams));
+INSTANTIATE_TEST_SUITE_P(, RSAEncryptTest,
+                         testing::ValuesIn(kRSAEncryptParams));
 
 TEST(RSATest, TestDecrypt) {
   bssl::UniquePtr<RSA> rsa(
diff --git a/src/include/openssl/aes.h b/src/include/openssl/aes.h
index 1156585..3606bfc 100644
--- a/src/include/openssl/aes.h
+++ b/src/include/openssl/aes.h
@@ -76,18 +76,18 @@
 typedef struct aes_key_st AES_KEY;
 
 // AES_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit key,
-// |key|.
+// |key|. |key| must point to |bits|/8 bytes. It returns zero on success and a
+// negative number if |bits| is an invalid AES key size.
 //
-// WARNING: unlike other OpenSSL functions, this returns zero on success and a
-// negative number on error.
+// WARNING: this function breaks the usual return value convention.
 OPENSSL_EXPORT int AES_set_encrypt_key(const uint8_t *key, unsigned bits,
                                        AES_KEY *aeskey);
 
 // AES_set_decrypt_key configures |aeskey| to decrypt with the |bits|-bit key,
-// |key|.
+// |key|. |key| must point to |bits|/8 bytes. It returns zero on success and a
+// negative number if |bits| is an invalid AES key size.
 //
-// WARNING: unlike other OpenSSL functions, this returns zero on success and a
-// negative number on error.
+// WARNING: this function breaks the usual return value convention.
 OPENSSL_EXPORT int AES_set_decrypt_key(const uint8_t *key, unsigned bits,
                                        AES_KEY *aeskey);
 
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
index 75b8434..029c2be 100644
--- a/src/include/openssl/bytestring.h
+++ b/src/include/openssl/bytestring.h
@@ -345,9 +345,9 @@
   // length-prefix, or zero if no length-prefix is pending.
   uint8_t pending_len_len;
   char pending_is_asn1;
-  // is_top_level is true iff this is a top-level |CBB| (as opposed to a child
+  // is_child is true iff this is a child |CBB| (as opposed to a top-level
   // |CBB|). Top-level objects are valid arguments for |CBB_finish|.
-  char is_top_level;
+  char is_child;
 };
 
 // CBB_zero sets an uninitialised |cbb| to the zero state. It must be
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 629f006..4240c29 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -4757,7 +4757,8 @@
 
 OPENSSL_EXPORT void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on);
 OPENSSL_EXPORT void SSL_set_handoff_mode(SSL *SSL, bool on);
-OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out);
+OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out,
+                                          SSL_CLIENT_HELLO *out_hello);
 OPENSSL_EXPORT bool SSL_decline_handoff(SSL *ssl);
 OPENSSL_EXPORT bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff);
 OPENSSL_EXPORT bool SSL_serialize_handback(const SSL *ssl, CBB *out);
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index d82852d..f68cd1c 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -405,7 +405,7 @@
   return ssl_open_record_success;
 }
 
-bool dtls1_get_message(SSL *ssl, SSLMessage *out) {
+bool dtls1_get_message(const SSL *ssl, SSLMessage *out) {
   if (!dtls1_is_current_message_complete(ssl)) {
     return false;
   }
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
index f9dbd13..0928015 100644
--- a/src/ssl/handoff.cc
+++ b/src/ssl/handoff.cc
@@ -49,7 +49,8 @@
   return CBB_flush(out);
 }
 
-bool SSL_serialize_handoff(const SSL *ssl, CBB *out) {
+bool SSL_serialize_handoff(const SSL *ssl, CBB *out,
+                           SSL_CLIENT_HELLO *out_hello) {
   const SSL3_STATE *const s3 = ssl->s3;
   if (!ssl->server ||
       s3->hs == nullptr ||
@@ -58,6 +59,7 @@
   }
 
   CBB seq;
+  SSLMessage msg;
   Span<const uint8_t> transcript = s3->hs->transcript.buffer();
   if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&seq, kHandoffVersion) ||
@@ -66,7 +68,9 @@
                                  reinterpret_cast<uint8_t *>(s3->hs_buf->data),
                                  s3->hs_buf->length) ||
       !serialize_features(&seq) ||
-      !CBB_flush(out)) {
+      !CBB_flush(out) ||
+      !ssl->method->get_message(ssl, &msg) ||
+      !ssl_client_hello_init(ssl, out_hello, msg)) {
     return false;
   }
 
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index cb4e9d1..4622ad0 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -515,10 +515,6 @@
     return ssl_hs_error;
   }
 
-  if (hs->config->handoff) {
-    return ssl_hs_handoff;
-  }
-
   SSL_CLIENT_HELLO client_hello;
   if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
@@ -526,6 +522,10 @@
     return ssl_hs_error;
   }
 
+  if (hs->config->handoff) {
+    return ssl_hs_handoff;
+  }
+
   // Run the early callback.
   if (ssl->ctx->select_certificate_cb != NULL) {
     switch (ssl->ctx->select_certificate_cb(&client_hello)) {
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 16b2866..ee2952a 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -1081,7 +1081,7 @@
 void ssl_do_info_callback(const SSL *ssl, int type, int value);
 
 // ssl_do_msg_callback calls |ssl|'s message callback, if set.
-void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+void ssl_do_msg_callback(const SSL *ssl, int is_write, int content_type,
                          Span<const uint8_t> in);
 
 
@@ -1798,7 +1798,7 @@
 
 // ClientHello functions.
 
-bool ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
                            const SSLMessage &msg);
 
 bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
@@ -1958,7 +1958,7 @@
   void (*ssl_free)(SSL *ssl);
   // get_message sets |*out| to the current handshake message and returns true
   // if one has been received. It returns false if more input is needed.
-  bool (*get_message)(SSL *ssl, SSLMessage *out);
+  bool (*get_message)(const SSL *ssl, SSLMessage *out);
   // next_message is called to release the current handshake message.
   void (*next_message)(SSL *ssl);
   // Use the |ssl_open_handshake| wrapper.
@@ -2675,7 +2675,7 @@
 void ssl_update_cache(SSL_HANDSHAKE *hs, int mode);
 
 int ssl_send_alert(SSL *ssl, int level, int desc);
-bool ssl3_get_message(SSL *ssl, SSLMessage *out);
+bool ssl3_get_message(const SSL *ssl, SSLMessage *out);
 ssl_open_record_t ssl3_open_handshake(SSL *ssl, size_t *out_consumed,
                                       uint8_t *out_alert, Span<uint8_t> in);
 void ssl3_next_message(SSL *ssl);
@@ -2741,7 +2741,7 @@
 bool dtls1_new(SSL *ssl);
 void dtls1_free(SSL *ssl);
 
-bool dtls1_get_message(SSL *ssl, SSLMessage *out);
+bool dtls1_get_message(const SSL *ssl, SSLMessage *out);
 ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed,
                                        uint8_t *out_alert, Span<uint8_t> in);
 void dtls1_next_message(SSL *ssl);
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index aec6cae..27e9454 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -494,7 +494,7 @@
   return true;
 }
 
-bool ssl3_get_message(SSL *ssl, SSLMessage *out) {
+bool ssl3_get_message(const SSL *ssl, SSLMessage *out) {
   size_t unused;
   if (!parse_message(ssl, out, &unused)) {
     return false;
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index d3e76d0..f9910f7 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -378,7 +378,7 @@
   }
 }
 
-void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+void ssl_do_msg_callback(const SSL *ssl, int is_write, int content_type,
                          Span<const uint8_t> in) {
   if (ssl->msg_callback == NULL) {
     return;
@@ -399,8 +399,8 @@
       version = SSL_version(ssl);
   }
 
-  ssl->msg_callback(is_write, version, content_type, in.data(), in.size(), ssl,
-                    ssl->msg_callback_arg);
+  ssl->msg_callback(is_write, version, content_type, in.data(), in.size(),
+                    const_cast<SSL *>(ssl), ssl->msg_callback_arg);
 }
 
 void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index af5d795..d01b649 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1650,11 +1650,11 @@
   bssl::UniquePtr<EVP_PKEY> key_;
 };
 
-INSTANTIATE_TEST_CASE_P(WithVersion, SSLVersionTest,
-                        testing::ValuesIn(kAllVersions),
-                        [](const testing::TestParamInfo<VersionParam> &i) {
-                          return i.param.name;
-                        });
+INSTANTIATE_TEST_SUITE_P(WithVersion, SSLVersionTest,
+                         testing::ValuesIn(kAllVersions),
+                         [](const testing::TestParamInfo<VersionParam> &i) {
+                           return i.param.name;
+                         });
 
 TEST_P(SSLVersionTest, SequenceNumber) {
   ASSERT_TRUE(Connect());
@@ -3574,7 +3574,7 @@
   return ret;
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     TicketAEADMethodTests, TicketAEADMethodTest,
     testing::Combine(testing::Values(TLS1_2_VERSION, TLS1_3_VERSION),
                      testing::Values(0, 1, 2),
@@ -4050,8 +4050,9 @@
 
   ScopedCBB cbb;
   Array<uint8_t> handoff;
+  SSL_CLIENT_HELLO hello;
   ASSERT_TRUE(CBB_init(cbb.get(), 256));
-  ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get()));
+  ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get(), &hello));
   ASSERT_TRUE(CBBFinishArray(cbb.get(), &handoff));
 
   bssl::UniquePtr<SSL> handshaker(SSL_new(handshaker_ctx.get()));
@@ -4122,8 +4123,9 @@
   ASSERT_EQ(server_err, SSL_ERROR_HANDOFF);
 
   ScopedCBB cbb;
+  SSL_CLIENT_HELLO hello;
   ASSERT_TRUE(CBB_init(cbb.get(), 256));
-  ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get()));
+  ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get(), &hello));
 
   ASSERT_TRUE(SSL_decline_handoff(server.get()));
 
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index c0452dc..87f1888 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -199,10 +199,10 @@
   return true;
 }
 
-bool ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
                            const SSLMessage &msg) {
   OPENSSL_memset(out, 0, sizeof(*out));
-  out->ssl = ssl;
+  out->ssl = const_cast<SSL *>(ssl);
   out->client_hello = CBS_data(&msg.body);
   out->client_hello_len = CBS_len(&msg.body);
 
diff --git a/src/ssl/test/handshake_util.cc b/src/ssl/test/handshake_util.cc
index a36b41a..afead7f 100644
--- a/src/ssl/test/handshake_util.cc
+++ b/src/ssl/test/handshake_util.cc
@@ -413,8 +413,9 @@
   }
 
   ScopedCBB cbb;
+  SSL_CLIENT_HELLO hello;
   if (!CBB_init(cbb.get(), 512) ||
-      !SSL_serialize_handoff(ssl, cbb.get()) ||
+      !SSL_serialize_handoff(ssl, cbb.get(), &hello) ||
       !writer->WriteHandoff({CBB_data(cbb.get()), CBB_len(cbb.get())}) ||
       !SerializeContextState(ssl->ctx.get(), cbb.get()) ||
       !GetTestState(ssl)->Serialize(cbb.get())) {