external/boringssl: Sync to 9f0e7cb314ae64234b928fd379381ae9760a9a5f.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/f11ea19043f2b3ee42e4a76d0645914347e1a36e..9f0e7cb314ae64234b928fd379381ae9760a9a5f

Test: BoringSSL CTS Presubmits.
Change-Id: I9296845fe9db4baae2afc03328c5bc17f76a752f
diff --git a/src/ssl/dtls_record.cc b/src/ssl/dtls_record.cc
index 5e795fa..d348601 100644
--- a/src/ssl/dtls_record.cc
+++ b/src/ssl/dtls_record.cc
@@ -219,8 +219,8 @@
     return ssl_open_record_discard;
   }
 
-  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER,
-                      in.subspan(0, DTLS1_RT_HEADER_LENGTH));
+  Span<const uint8_t> header = in.subspan(0, DTLS1_RT_HEADER_LENGTH);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, header);
 
   uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1];
   if (epoch != ssl->d1->r_epoch ||
@@ -235,7 +235,7 @@
 
   // discard the body in-place.
   if (!ssl->s3->aead_read_ctx->Open(
-          out, type, version, sequence,
+          out, type, version, sequence, header,
           MakeSpan(const_cast<uint8_t *>(CBS_data(&body)), CBS_len(&body)))) {
     // Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347.
     // Clear the error queue of any errors decryption may have added. Drop the
@@ -328,25 +328,25 @@
   OPENSSL_memcpy(&out[5], &seq[2], 6);
 
   size_t ciphertext_len;
-  if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len,
-                  max_out - DTLS1_RT_HEADER_LENGTH, type, record_version,
-                  &out[3] /* seq */, in, in_len) ||
-      !ssl_record_sequence_update(&seq[2], 6)) {
-    return 0;
-  }
-
-  if (ciphertext_len >= 1 << 16) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+  if (!aead->CiphertextLen(&ciphertext_len, in_len, 0)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
     return 0;
   }
   out[11] = ciphertext_len >> 8;
   out[12] = ciphertext_len & 0xff;
+  Span<const uint8_t> header = MakeConstSpan(out, DTLS1_RT_HEADER_LENGTH);
+
+  size_t len_copy;
+  if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &len_copy,
+                  max_out - DTLS1_RT_HEADER_LENGTH, type, record_version,
+                  &out[3] /* seq */, header, in, in_len) ||
+      !ssl_record_sequence_update(&seq[2], 6)) {
+    return 0;
+  }
+  assert(ciphertext_len == len_copy);
 
   *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len;
-
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER,
-                      MakeSpan(out, DTLS1_RT_HEADER_LENGTH));
-
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header);
   return 1;
 }
 
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
index dd73c83..2cbbaeb 100644
--- a/src/ssl/handoff.cc
+++ b/src/ssl/handoff.cc
@@ -133,10 +133,6 @@
       s3->session_reused ? ssl->session : s3->hs->new_session.get();
   if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&seq, kHandbackVersion) ||
-      !CBB_add_asn1_uint64(&seq, ssl->version) ||
-      !CBB_add_asn1_uint64(&seq, ssl->conf_max_version) ||
-      !CBB_add_asn1_uint64(&seq, ssl->conf_min_version) ||
-      !CBB_add_asn1_uint64(&seq, ssl->max_send_fragment) ||
       !CBB_add_asn1_octet_string(&seq, s3->read_sequence,
                                  sizeof(s3->read_sequence)) ||
       !CBB_add_asn1_octet_string(&seq, s3->write_sequence,
@@ -148,7 +144,6 @@
       !CBB_add_asn1_octet_string(&seq, read_iv, iv_len) ||
       !CBB_add_asn1_octet_string(&seq, write_iv, iv_len) ||
       !CBB_add_asn1_bool(&seq, s3->session_reused) ||
-      !CBB_add_asn1_bool(&seq, s3->send_connection_binding) ||
       !CBB_add_asn1_bool(&seq, s3->tlsext_channel_id_valid) ||
       !ssl_session_serialize(session, &seq) ||
       !CBB_add_asn1_octet_string(&seq, s3->next_proto_negotiated.data(),
@@ -160,14 +155,8 @@
           hostname_len) ||
       !CBB_add_asn1_octet_string(&seq, s3->tlsext_channel_id,
                                  sizeof(s3->tlsext_channel_id)) ||
-      !CBB_add_asn1_uint64(&seq, ssl->options) ||
-      !CBB_add_asn1_uint64(&seq, ssl->mode) ||
-      !CBB_add_asn1_uint64(&seq, ssl->max_cert_list) ||
-      !CBB_add_asn1_bool(&seq, ssl->quiet_shutdown) ||
-      !CBB_add_asn1_bool(&seq, ssl->tlsext_channel_id_enabled) ||
-      !CBB_add_asn1_bool(&seq, ssl->retain_only_sha256_of_client_certs) ||
-      !CBB_add_asn1_bool(&seq, ssl->token_binding_negotiated) ||
-      !CBB_add_asn1_uint64(&seq, ssl->negotiated_token_binding_param) ||
+      !CBB_add_asn1_bool(&seq, ssl->s3->token_binding_negotiated) ||
+      !CBB_add_asn1_uint64(&seq, ssl->s3->negotiated_token_binding_param) ||
       !CBB_add_asn1_bool(&seq, s3->hs->next_proto_neg_seen) ||
       !CBB_add_asn1_bool(&seq, s3->hs->cert_request) ||
       !CBB_add_asn1_bool(&seq, s3->hs->extended_master_secret) ||
@@ -191,16 +180,12 @@
   }
 
   SSL3_STATE *const s3 = ssl->s3;
-  uint64_t handback_version, version, conf_max_version, conf_min_version,
-      max_send_fragment, options, mode, max_cert_list,
-      negotiated_token_binding_param, cipher;
+  uint64_t handback_version, negotiated_token_binding_param, cipher;
 
   CBS seq, read_seq, write_seq, server_rand, client_rand, read_iv, write_iv,
       next_proto, alpn, hostname, channel_id, transcript, key_share;
-  int session_reused, send_connection_binding, channel_id_valid, quiet_shutdown,
-      channel_id_enabled, retain_only_sha256, cert_request,
-      extended_master_secret, ticket_expected, token_binding_negotiated,
-      next_proto_neg_seen;
+  int session_reused, channel_id_valid, cert_request, extended_master_secret,
+      ticket_expected, token_binding_negotiated, next_proto_neg_seen;
   SSL_SESSION *session = nullptr;
 
   CBS handback_cbs(handback);
@@ -210,11 +195,7 @@
     return false;
   }
 
-  if (!CBS_get_asn1_uint64(&seq, &version) ||
-      !CBS_get_asn1_uint64(&seq, &conf_max_version) ||
-      !CBS_get_asn1_uint64(&seq, &conf_min_version) ||
-      !CBS_get_asn1_uint64(&seq, &max_send_fragment) ||
-      !CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) ||
+  if (!CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) ||
       CBS_len(&read_seq) != sizeof(s3->read_sequence) ||
       !CBS_get_asn1(&seq, &write_seq, CBS_ASN1_OCTETSTRING) ||
       CBS_len(&write_seq) != sizeof(s3->write_sequence) ||
@@ -229,7 +210,6 @@
       !CBS_get_asn1(&seq, &read_iv, CBS_ASN1_OCTETSTRING) ||
       !CBS_get_asn1(&seq, &write_iv, CBS_ASN1_OCTETSTRING) ||
       !CBS_get_asn1_bool(&seq, &session_reused) ||
-      !CBS_get_asn1_bool(&seq, &send_connection_binding) ||
       !CBS_get_asn1_bool(&seq, &channel_id_valid)) {
     return false;
   }
@@ -253,12 +233,6 @@
       CBS_len(&channel_id) != sizeof(s3->tlsext_channel_id) ||
       !CBS_copy_bytes(&channel_id, s3->tlsext_channel_id,
                       sizeof(s3->tlsext_channel_id)) ||
-      !CBS_get_asn1_uint64(&seq, &options) ||
-      !CBS_get_asn1_uint64(&seq, &mode) ||
-      !CBS_get_asn1_uint64(&seq, &max_cert_list) ||
-      !CBS_get_asn1_bool(&seq, &quiet_shutdown) ||
-      !CBS_get_asn1_bool(&seq, &channel_id_enabled) ||
-      !CBS_get_asn1_bool(&seq, &retain_only_sha256) ||
       !CBS_get_asn1_bool(&seq, &token_binding_negotiated) ||
       !CBS_get_asn1_uint64(&seq, &negotiated_token_binding_param) ||
       !CBS_get_asn1_bool(&seq, &next_proto_neg_seen) ||
@@ -277,21 +251,14 @@
     return false;
   }
 
-  ssl->version = version;
-  ssl->conf_max_version = conf_max_version;
-  ssl->conf_min_version = conf_min_version;
-  ssl->max_send_fragment = max_send_fragment;
+  ssl->version = session->ssl_version;
   ssl->do_handshake = ssl_server_handshake;
   ssl->server = true;
-  ssl->options = options;
-  ssl->mode = mode;
-  ssl->max_cert_list = max_cert_list;
 
   s3->have_version = true;
   s3->hs->state = CBS_len(&transcript) == 0 ? state12_finish_server_handshake
                                             : state12_read_client_certificate;
   s3->session_reused = session_reused;
-  s3->send_connection_binding = send_connection_binding;
   s3->tlsext_channel_id_valid = channel_id_valid;
   s3->next_proto_negotiated.CopyFrom(next_proto);
   s3->alpn_selected.CopyFrom(alpn);
@@ -307,11 +274,8 @@
     s3->hostname.reset(hostname_str);
   }
 
-  ssl->quiet_shutdown = quiet_shutdown;
-  ssl->tlsext_channel_id_enabled = channel_id_enabled;
-  ssl->retain_only_sha256_of_client_certs = retain_only_sha256;
-  ssl->token_binding_negotiated = token_binding_negotiated;
-  ssl->negotiated_token_binding_param =
+  s3->token_binding_negotiated = token_binding_negotiated;
+  s3->negotiated_token_binding_param =
       static_cast<uint8_t>(negotiated_token_binding_param);
   s3->hs->next_proto_neg_seen = next_proto_neg_seen;
   s3->hs->wait = ssl_hs_flush;
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 0b352c2..087645d 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -740,7 +740,7 @@
     return ssl_hs_error;
   }
 
-  if (ssl->token_binding_negotiated &&
+  if (ssl->s3->token_binding_negotiated &&
       (!hs->extended_master_secret || !ssl->s3->send_connection_binding)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI);
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 5f2f41f..7ade8fc 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -334,7 +334,7 @@
     SSL_HANDSHAKE *hs, const SSL_CLIENT_HELLO *client_hello,
     const struct ssl_cipher_preference_list_st *server_pref) {
   SSL *const ssl = hs->ssl;
-  STACK_OF(SSL_CIPHER) *prio, *allow;
+  const STACK_OF(SSL_CIPHER) *prio, *allow;
   // in_group_flags will either be NULL, or will point to an array of bytes
   // which indicate equal-preference groups in the |prio| stack. See the
   // comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index e884b63..f4dc96f 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -657,19 +657,26 @@
   bool SuffixLen(size_t *out_suffix_len, size_t in_len,
                  size_t extra_in_len) const;
 
+  // CiphertextLen calculates the total ciphertext length written by
+  // |SealScatter| and writes it to |*out_len|. It returns true on success and
+  // false on error. |in_len| and |extra_in_len| should equal the argument of
+  // the same names passed to |SealScatter|.
+  bool CiphertextLen(size_t *out_len, size_t in_len, size_t extra_in_len) const;
+
   // Open authenticates and decrypts |in| in-place. On success, it sets |*out|
   // to the plaintext in |in| and returns true.  Otherwise, it returns
   // false. The output will always be |ExplicitNonceLen| bytes ahead of |in|.
   bool Open(Span<uint8_t> *out, uint8_t type, uint16_t record_version,
-            const uint8_t seqnum[8], Span<uint8_t> in);
+            const uint8_t seqnum[8], Span<const uint8_t> header,
+            Span<uint8_t> in);
 
   // Seal encrypts and authenticates |in_len| bytes from |in| and writes the
   // result to |out|. It returns true on success and false on error.
   //
   // If |in| and |out| alias then |out| + |ExplicitNonceLen| must be == |in|.
   bool Seal(uint8_t *out, size_t *out_len, size_t max_out, uint8_t type,
-            uint16_t record_version, const uint8_t seqnum[8], const uint8_t *in,
-            size_t in_len);
+            uint16_t record_version, const uint8_t seqnum[8],
+            Span<const uint8_t> header, const uint8_t *in, size_t in_len);
 
   // SealScatter encrypts and authenticates |in_len| bytes from |in| and splits
   // the result between |out_prefix|, |out| and |out_suffix|. It returns one on
@@ -688,17 +695,20 @@
   // alias anything.
   bool SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix,
                    uint8_t type, uint16_t record_version,
-                   const uint8_t seqnum[8], const uint8_t *in, size_t in_len,
-                   const uint8_t *extra_in, size_t extra_in_len);
+                   const uint8_t seqnum[8], Span<const uint8_t> header,
+                   const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+                   size_t extra_in_len);
 
   bool GetIV(const uint8_t **out_iv, size_t *out_iv_len) const;
 
  private:
-  // GetAdditionalData writes the additional data into |out| and returns the
-  // number of bytes written.
-  size_t GetAdditionalData(uint8_t out[13], uint8_t type,
-                           uint16_t record_version, const uint8_t seqnum[8],
-                           size_t plaintext_len, size_t ciphertext_len);
+  // GetAdditionalData returns the additional data, writing into |storage| if
+  // necessary.
+  Span<const uint8_t> GetAdditionalData(uint8_t storage[13], uint8_t type,
+                                        uint16_t record_version,
+                                        const uint8_t seqnum[8],
+                                        size_t plaintext_len,
+                                        Span<const uint8_t> header);
 
   const SSL_CIPHER *cipher_;
   ScopedEVP_AEAD_CTX ctx_;
@@ -717,6 +727,9 @@
   // randomly generated, rather than derived from the sequence
   // number.
   bool random_variable_nonce_ : 1;
+  // xor_fixed_nonce_ is true if the fixed nonce should be XOR'd into the
+  // variable nonce rather than prepended.
+  bool xor_fixed_nonce_ : 1;
   // omit_length_in_ad_ is true if the length should be omitted in the
   // AEAD's ad parameter.
   bool omit_length_in_ad_ : 1;
@@ -725,12 +738,8 @@
   bool omit_version_in_ad_ : 1;
   // omit_ad_ is true if the AEAD's ad parameter should be omitted.
   bool omit_ad_ : 1;
-  // tls13_ad_ is true if the AEAD's ad parameter should be based on the
-  // TLS 1.3 format.
-  bool tls13_ad_ : 1;
-  // xor_fixed_nonce_ is true if the fixed nonce should be XOR'd into the
-  // variable nonce rather than prepended.
-  bool xor_fixed_nonce_ : 1;
+  // ad_is_header_ is true if the AEAD's ad parameter is the record header.
+  bool ad_is_header_ : 1;
 };
 
 
@@ -2299,6 +2308,10 @@
   // key_update_count is the number of consecutive KeyUpdates received.
   uint8_t key_update_count = 0;
 
+  // The negotiated Token Binding key parameter. Only valid if
+  // |token_binding_negotiated| is set.
+  uint8_t negotiated_token_binding_param = 0;
+
   // skip_early_data instructs the record layer to skip unexpected early data
   // messages when 0RTT is rejected.
   bool skip_early_data:1;
@@ -2348,6 +2361,9 @@
   // fired, were it not a draft.
   bool draft_downgrade:1;
 
+  // token_binding_negotiated is set if Token Binding was negotiated.
+  bool token_binding_negotiated:1;
+
   // hs_buf is the buffer of handshake data to process.
   UniquePtr<BUF_MEM> hs_buf;
 
@@ -2671,10 +2687,6 @@
   uint8_t *token_binding_params;
   size_t token_binding_params_len;
 
-  // The negotiated Token Binding key parameter. Only valid if
-  // |token_binding_negotiated| is set.
-  uint8_t negotiated_token_binding_param;
-
   // Contains the QUIC transport params that this endpoint will send.
   uint8_t *quic_transport_params;
   size_t quic_transport_params_len;
@@ -2706,9 +2718,6 @@
   // we'll advertise support.
   bool tlsext_channel_id_enabled:1;
 
-  // token_binding_negotiated is set if Token Binding was negotiated.
-  bool token_binding_negotiated:1;
-
   // retain_only_sha256_of_client_certs is true if we should compute the SHA256
   // hash of the peer's certificate and then discard it to save memory and
   // session space. Only effective on the server side.
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index a3fc8d7..baa5a17 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -177,7 +177,8 @@
       key_update_pending(false),
       wpend_pending(false),
       early_data_accepted(false),
-      draft_downgrade(false) {}
+      draft_downgrade(false),
+      token_binding_negotiated(false) {}
 
 SSL3_STATE::~SSL3_STATE() {}
 
diff --git a/src/ssl/ssl_aead_ctx.cc b/src/ssl/ssl_aead_ctx.cc
index e6b3ee9..363c959 100644
--- a/src/ssl/ssl_aead_ctx.cc
+++ b/src/ssl/ssl_aead_ctx.cc
@@ -40,11 +40,11 @@
       is_dtls_(is_dtls_arg),
       variable_nonce_included_in_record_(false),
       random_variable_nonce_(false),
+      xor_fixed_nonce_(false),
       omit_length_in_ad_(false),
       omit_version_in_ad_(false),
       omit_ad_(false),
-      tls13_ad_(false),
-      xor_fixed_nonce_(false) {
+      ad_is_header_(false) {
   OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_));
 }
 
@@ -136,7 +136,7 @@
       aead_ctx->variable_nonce_len_ = 8;
       aead_ctx->variable_nonce_included_in_record_ = false;
       if (ssl_is_draft28(version)) {
-        aead_ctx->tls13_ad_ = true;
+        aead_ctx->ad_is_header_ = true;
       } else {
         aead_ctx->omit_ad_ = true;
       }
@@ -198,6 +198,22 @@
                                 extra_in_len);
 }
 
+bool SSLAEADContext::CiphertextLen(size_t *out_len, const size_t in_len,
+                                   const size_t extra_in_len) const {
+  size_t len;
+  if (!SuffixLen(&len, in_len, extra_in_len)) {
+    return false;
+  }
+  len += ExplicitNonceLen();
+  len += in_len;
+  if (len < in_len || len >= 0xffff) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return false;
+  }
+  *out_len = len;
+  return true;
+}
+
 size_t SSLAEADContext::MaxOverhead() const {
   return ExplicitNonceLen() +
          (is_null_cipher() || FUZZER_MODE
@@ -205,38 +221,34 @@
               : EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(ctx_.get())));
 }
 
-size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
-                                         uint16_t record_version,
-                                         const uint8_t seqnum[8],
-                                         size_t plaintext_len,
-                                         size_t ciphertext_len) {
-  if (omit_ad_) {
-    return 0;
+Span<const uint8_t> SSLAEADContext::GetAdditionalData(
+    uint8_t storage[13], uint8_t type, uint16_t record_version,
+    const uint8_t seqnum[8], size_t plaintext_len, Span<const uint8_t> header) {
+  if (ad_is_header_) {
+    return header;
   }
 
-  size_t len = 0;
-  if (!tls13_ad_) {
-    OPENSSL_memcpy(out, seqnum, 8);
-    len += 8;
+  if (omit_ad_) {
+    return {};
   }
-  out[len++] = type;
+
+  OPENSSL_memcpy(storage, seqnum, 8);
+  size_t len = 8;
+  storage[len++] = type;
   if (!omit_version_in_ad_) {
-    out[len++] = static_cast<uint8_t>((record_version >> 8));
-    out[len++] = static_cast<uint8_t>(record_version);
+    storage[len++] = static_cast<uint8_t>((record_version >> 8));
+    storage[len++] = static_cast<uint8_t>(record_version);
   }
-  if (tls13_ad_) {
-    out[len++] = static_cast<uint8_t>((ciphertext_len >> 8));
-    out[len++] = static_cast<uint8_t>(ciphertext_len);
-  } else if (!omit_length_in_ad_) {
-    out[len++] = static_cast<uint8_t>((plaintext_len >> 8));
-    out[len++] = static_cast<uint8_t>(plaintext_len);
+  if (!omit_length_in_ad_) {
+    storage[len++] = static_cast<uint8_t>((plaintext_len >> 8));
+    storage[len++] = static_cast<uint8_t>(plaintext_len);
   }
-  return len;
+  return MakeConstSpan(storage, len);
 }
 
 bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type,
                           uint16_t record_version, const uint8_t seqnum[8],
-                          Span<uint8_t> in) {
+                          Span<const uint8_t> header, Span<uint8_t> in) {
   if (is_null_cipher() || FUZZER_MODE) {
     // Handle the initial NULL cipher.
     *out = in;
@@ -255,9 +267,10 @@
     }
     plaintext_len = in.size() - overhead;
   }
-  uint8_t ad[13];
-  size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum,
-                                    plaintext_len, in.size());
+
+  uint8_t ad_storage[13];
+  Span<const uint8_t> ad = GetAdditionalData(ad_storage, type, record_version,
+                                             seqnum, plaintext_len, header);
 
   // Assemble the nonce.
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
@@ -298,7 +311,8 @@
   // Decrypt in-place.
   size_t len;
   if (!EVP_AEAD_CTX_open(ctx_.get(), in.data(), &len, in.size(), nonce,
-                         nonce_len, in.data(), in.size(), ad, ad_len)) {
+                         nonce_len, in.data(), in.size(), ad.data(),
+                         ad.size())) {
     return false;
   }
   *out = in.subspan(0, len);
@@ -308,7 +322,8 @@
 bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out,
                                  uint8_t *out_suffix, uint8_t type,
                                  uint16_t record_version,
-                                 const uint8_t seqnum[8], const uint8_t *in,
+                                 const uint8_t seqnum[8],
+                                 Span<const uint8_t> header, const uint8_t *in,
                                  size_t in_len, const uint8_t *extra_in,
                                  size_t extra_in_len) {
   const size_t prefix_len = ExplicitNonceLen();
@@ -331,9 +346,9 @@
     return true;
   }
 
-  uint8_t ad[13];
-  size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum, in_len,
-                                    in_len + suffix_len);
+  uint8_t ad_storage[13];
+  Span<const uint8_t> ad = GetAdditionalData(ad_storage, type, record_version,
+                                             seqnum, in_len, header);
 
   // Assemble the nonce.
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
@@ -384,15 +399,15 @@
   size_t written_suffix_len;
   bool result = !!EVP_AEAD_CTX_seal_scatter(
       ctx_.get(), out, out_suffix, &written_suffix_len, suffix_len, nonce,
-      nonce_len, in, in_len, extra_in, extra_in_len, ad, ad_len);
+      nonce_len, in, in_len, extra_in, extra_in_len, ad.data(), ad.size());
   assert(!result || written_suffix_len == suffix_len);
   return result;
 }
 
 bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len,
                           uint8_t type, uint16_t record_version,
-                          const uint8_t seqnum[8], const uint8_t *in,
-                          size_t in_len) {
+                          const uint8_t seqnum[8], Span<const uint8_t> header,
+                          const uint8_t *in, size_t in_len) {
   const size_t prefix_len = ExplicitNonceLen();
   size_t suffix_len;
   if (!SuffixLen(&suffix_len, in_len, 0)) {
@@ -410,7 +425,7 @@
   }
 
   if (!SealScatter(out, out + prefix_len, out + prefix_len + in_len, type,
-                   record_version, seqnum, in, in_len, 0, 0)) {
+                   record_version, seqnum, header, in, in_len, 0, 0)) {
     return false;
   }
   *out_len = prefix_len + in_len + suffix_len;
diff --git a/src/ssl/ssl_file.cc b/src/ssl/ssl_file.cc
index bafa64a..ca4b0be 100644
--- a/src/ssl/ssl_file.cc
+++ b/src/ssl/ssl_file.cc
@@ -165,6 +165,7 @@
     }
 
     // Check for duplicates.
+    sk_X509_NAME_sort(sk);
     if (sk_X509_NAME_find(sk, NULL, xn)) {
       continue;
     }
@@ -223,6 +224,7 @@
     }
 
     // Check for duplicates.
+    sk_X509_NAME_sort(stack);
     if (sk_X509_NAME_find(stack, NULL, xn)) {
       continue;
     }
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 2a076c3..c7f6f88 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -248,11 +248,11 @@
 
 UniquePtr<SSLKeyShare> SSLKeyShare::Create(CBS *in) {
   uint64_t group;
-  if (!CBS_get_asn1_uint64(in, &group)) {
+  if (!CBS_get_asn1_uint64(in, &group) || group > 0xffff) {
     return nullptr;
   }
-  UniquePtr<SSLKeyShare> key_share = Create(static_cast<uint64_t>(group));
-  if (!key_share->Deserialize(in)) {
+  UniquePtr<SSLKeyShare> key_share = Create(static_cast<uint16_t>(group));
+  if (!key_share || !key_share->Deserialize(in)) {
     return nullptr;
   }
   return key_share;
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 6312504..14fb0ff 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -2164,11 +2164,11 @@
 }
 
 int SSL_is_token_binding_negotiated(const SSL *ssl) {
-  return ssl->token_binding_negotiated;
+  return ssl->s3->token_binding_negotiated;
 }
 
 uint8_t SSL_get_negotiated_token_binding_param(const SSL *ssl) {
-  return ssl->negotiated_token_binding_param;
+  return ssl->s3->negotiated_token_binding_param;
 }
 
 size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 34e7b31..bc2c14c 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -990,6 +990,10 @@
   return session->tlsext_tick_lifetime_hint;
 }
 
+const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *session) {
+  return session->cipher;
+}
+
 SSL_SESSION *SSL_magic_pending_session_ptr(void) {
   return (SSL_SESSION *)&g_pending_session_magic;
 }
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 97c0c4b..2d3a664 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -2528,8 +2528,8 @@
 
   for (size_t i = 0; i < ssl->token_binding_params_len; ++i) {
     if (param == ssl->token_binding_params[i]) {
-      ssl->negotiated_token_binding_param = param;
-      ssl->token_binding_negotiated = true;
+      ssl->s3->negotiated_token_binding_param = param;
+      ssl->s3->token_binding_negotiated = true;
       return true;
     }
   }
@@ -2547,7 +2547,7 @@
     uint8_t tb_param = ssl->token_binding_params[i];
     for (uint8_t peer_param : peer_params) {
       if (tb_param == peer_param) {
-        ssl->negotiated_token_binding_param = tb_param;
+        ssl->s3->negotiated_token_binding_param = tb_param;
         return true;
       }
     }
@@ -2587,14 +2587,14 @@
     return true;
   }
 
-  ssl->token_binding_negotiated = true;
+  ssl->s3->token_binding_negotiated = true;
   return true;
 }
 
 static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
   SSL *const ssl = hs->ssl;
 
-  if (!ssl->token_binding_negotiated) {
+  if (!ssl->s3->token_binding_negotiated) {
     return true;
   }
 
@@ -2603,7 +2603,7 @@
       !CBB_add_u16_length_prefixed(out, &contents) ||
       !CBB_add_u16(&contents, hs->negotiated_token_binding_version) ||
       !CBB_add_u8_length_prefixed(&contents, &params) ||
-      !CBB_add_u8(&params, ssl->negotiated_token_binding_param) ||
+      !CBB_add_u8(&params, ssl->s3->negotiated_token_binding_param) ||
       !CBB_flush(out)) {
     return false;
   }
@@ -3220,7 +3220,7 @@
 static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
 
-  if (ssl->token_binding_negotiated &&
+  if (ssl->s3->token_binding_negotiated &&
       !(SSL_get_secure_renegotiation_support(ssl) &&
         SSL_get_extms_support(ssl))) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI);
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index aa05456..6e328b8 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -436,7 +436,7 @@
       return ssl_hs_error;
     }
     if (ssl->s3->tlsext_channel_id_valid || hs->received_custom_extension ||
-        ssl->token_binding_negotiated) {
+        ssl->s3->token_binding_negotiated) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION_ON_EARLY_DATA);
       return ssl_hs_error;
     }
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 3bd6786..9d7f5e0 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -391,7 +391,7 @@
           // Channel ID is incompatible with 0-RTT.
           !ssl->s3->tlsext_channel_id_valid &&
           // If Token Binding is negotiated, reject 0-RTT.
-          !ssl->token_binding_negotiated &&
+          !ssl->s3->token_binding_negotiated &&
           // Custom extensions is incompatible with 0-RTT.
           hs->custom_extensions.received == 0 &&
           // The negotiated ALPN must match the one in the ticket.
diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc
index 3152e7a..a2e4a20 100644
--- a/src/ssl/tls_record.cc
+++ b/src/ssl/tls_record.cc
@@ -258,8 +258,8 @@
     return ssl_open_record_partial;
   }
 
-  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER,
-                      in.subspan(0, SSL3_RT_HEADER_LENGTH));
+  Span<const uint8_t> header = in.subspan(0, SSL3_RT_HEADER_LENGTH);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, header);
 
   *out_consumed = in.size() - CBS_len(&cbs);
 
@@ -288,7 +288,7 @@
 
   // Decrypt the body in-place.
   if (!ssl->s3->aead_read_ctx->Open(
-          out, type, version, ssl->s3->read_sequence,
+          out, type, version, ssl->s3->read_sequence, header,
           MakeSpan(const_cast<uint8_t *>(CBS_data(&body)), CBS_len(&body)))) {
     if (ssl->s3->skip_early_data && !ssl->s3->aead_read_ctx->is_null_cipher()) {
       ERR_clear_error();
@@ -376,27 +376,22 @@
 static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
                           uint8_t *out_suffix, uint8_t type, const uint8_t *in,
                           const size_t in_len) {
+  SSLAEADContext *aead = ssl->s3->aead_write_ctx.get();
   uint8_t *extra_in = NULL;
   size_t extra_in_len = 0;
-  if (!ssl->s3->aead_write_ctx->is_null_cipher() &&
-      ssl->s3->aead_write_ctx->ProtocolVersion() >= TLS1_3_VERSION) {
+  if (!aead->is_null_cipher() &&
+      aead->ProtocolVersion() >= TLS1_3_VERSION) {
     // TLS 1.3 hides the actual record type inside the encrypted data.
     extra_in = &type;
     extra_in_len = 1;
   }
 
-  size_t suffix_len;
-  if (!ssl->s3->aead_write_ctx->SuffixLen(&suffix_len, in_len, extra_in_len)) {
+  size_t suffix_len, ciphertext_len;
+  if (!aead->SuffixLen(&suffix_len, in_len, extra_in_len) ||
+      !aead->CiphertextLen(&ciphertext_len, in_len, extra_in_len)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
     return 0;
   }
-  size_t ciphertext_len =
-      ssl->s3->aead_write_ctx->ExplicitNonceLen() + suffix_len;
-  if (ciphertext_len + in_len < ciphertext_len) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
-    return 0;
-  }
-  ciphertext_len += in_len;
 
   assert(in == out || !buffers_alias(in, in_len, out, in_len));
   assert(!buffers_alias(in, in_len, out_prefix, ssl_record_prefix_len(ssl)));
@@ -408,28 +403,27 @@
     out_prefix[0] = type;
   }
 
-  uint16_t record_version = ssl->s3->aead_write_ctx->RecordVersion();
+  uint16_t record_version = aead->RecordVersion();
 
   out_prefix[1] = record_version >> 8;
   out_prefix[2] = record_version & 0xff;
   out_prefix[3] = ciphertext_len >> 8;
   out_prefix[4] = ciphertext_len & 0xff;
+  Span<const uint8_t> header = MakeSpan(out_prefix, SSL3_RT_HEADER_LENGTH);
 
-  if (!ssl->s3->aead_write_ctx->SealScatter(
-          out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, out_prefix[0],
-          record_version, ssl->s3->write_sequence, in, in_len, extra_in,
-          extra_in_len) ||
+  if (!aead->SealScatter(out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix,
+                         out_prefix[0], record_version, ssl->s3->write_sequence,
+                         header, in, in_len, extra_in, extra_in_len) ||
       !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
     return 0;
   }
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER,
-                      MakeSpan(out_prefix, SSL3_RT_HEADER_LENGTH));
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header);
   return 1;
 }
 
 static size_t tls_seal_scatter_prefix_len(const SSL *ssl, uint8_t type,
-                                   size_t in_len) {
+                                          size_t in_len) {
   size_t ret = SSL3_RT_HEADER_LENGTH;
   if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
       ssl_needs_record_splitting(ssl)) {