Have a bit more fun with Span.

Change-Id: Iba909603a72ec0d149d9898423c114304a5011fa
Reviewed-on: https://boringssl-review.googlesource.com/21644
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc
index f865de9..1110e98 100644
--- a/ssl/d1_both.cc
+++ b/ssl/d1_both.cc
@@ -574,7 +574,7 @@
     // 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.data(), data.size())) {
+        !ssl->s3->hs->transcript.Update(data)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       return 0;
     }
diff --git a/ssl/handshake.cc b/ssl/handshake.cc
index 41ff7dc..80b64f3 100644
--- a/ssl/handshake.cc
+++ b/ssl/handshake.cc
@@ -216,7 +216,7 @@
     return true;
   }
 
-  return hs->transcript.Update(CBS_data(&msg.raw), CBS_len(&msg.raw));
+  return hs->transcript.Update(msg.raw);
 }
 
 int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 1533411..5466b56 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -1028,8 +1028,7 @@
     }
 
     ScopedCBB transcript;
-    uint8_t *transcript_data;
-    size_t transcript_len;
+    Array<uint8_t> transcript_data;
     if (!CBB_init(transcript.get(),
                   2 * SSL3_RANDOM_SIZE + CBS_len(&parameter)) ||
         !CBB_add_bytes(transcript.get(), ssl->s3->client_random,
@@ -1038,19 +1037,16 @@
                        SSL3_RANDOM_SIZE) ||
         !CBB_add_bytes(transcript.get(), CBS_data(&parameter),
                        CBS_len(&parameter)) ||
-        !CBB_finish(transcript.get(), &transcript_data, &transcript_len)) {
+        !CBBFinishArray(transcript.get(), &transcript_data)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
       return ssl_hs_error;
     }
 
-    int sig_ok = ssl_public_key_verify(
-        ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
-        hs->peer_pubkey.get(), transcript_data, transcript_len);
-    OPENSSL_free(transcript_data);
-
+    bool sig_ok = ssl_public_key_verify(ssl, signature, signature_algorithm,
+                                        hs->peer_pubkey.get(), transcript_data);
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-    sig_ok = 1;
+    sig_ok = true;
     ERR_clear_error();
 #endif
     if (!sig_ok) {
@@ -1347,19 +1343,15 @@
   if (alg_a & SSL_aPSK) {
     ScopedCBB pms_cbb;
     CBB child;
-    uint8_t *new_pms;
-    size_t new_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.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)) {
+        !CBBFinishArray(pms_cbb.get(), &pms)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return ssl_hs_error;
     }
-    pms.Reset(new_pms, new_pms_len);
   }
 
   // The message must be added to the finished hash before calculating the
@@ -1438,9 +1430,9 @@
       return ssl_hs_error;
     }
   } else {
-    switch (ssl_private_key_sign(
-        hs, ptr, &sig_len, max_sig_len, signature_algorithm,
-        hs->transcript.buffer_data(), hs->transcript.buffer_len())) {
+    switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
+                                 signature_algorithm,
+                                 hs->transcript.buffer())) {
       case ssl_private_key_success:
         break;
       case ssl_private_key_failure:
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
index 74bfce9..7b282d8 100644
--- a/ssl/handshake_server.cc
+++ b/ssl/handshake_server.cc
@@ -876,8 +876,7 @@
 
     size_t sig_len;
     switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
-                                 signature_algorithm, hs->server_params.data(),
-                                 hs->server_params.size())) {
+                                 signature_algorithm, hs->server_params)) {
       case ssl_private_key_success:
         if (!CBB_did_write(&child, sig_len)) {
           return ssl_hs_error;
@@ -1113,8 +1112,7 @@
     size_t decrypt_len;
     switch (ssl_private_key_decrypt(hs, decrypt_buf.data(), &decrypt_len,
                                     decrypt_buf.size(),
-                                    CBS_data(&encrypted_premaster_secret),
-                                    CBS_len(&encrypted_premaster_secret))) {
+                                    encrypted_premaster_secret)) {
       case ssl_private_key_success:
         break;
       case ssl_private_key_failure:
@@ -1226,8 +1224,6 @@
 
     ScopedCBB new_premaster;
     CBB child;
-    uint8_t *new_data;
-    size_t new_len;
     if (!CBB_init(new_premaster.get(),
                   2 + psk_len + 2 + premaster_secret.size()) ||
         !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
@@ -1235,12 +1231,10 @@
                        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)) {
+        !CBBFinishArray(new_premaster.get(), &premaster_secret)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return ssl_hs_error;
     }
-
-    premaster_secret.Reset(new_data, new_len);
   }
 
   if (!ssl_hash_message(hs, msg)) {
@@ -1312,7 +1306,7 @@
     return ssl_hs_error;
   }
 
-  int sig_ok;
+  bool sig_ok;
   // The SSL3 construction for CertificateVerify does not decompose into a
   // single final digest and signature, and must be special-cased.
   if (ssl_protocol_version(ssl) == SSL3_VERSION) {
@@ -1330,14 +1324,13 @@
              EVP_PKEY_verify(pctx.get(), CBS_data(&signature),
                              CBS_len(&signature), digest, digest_len);
   } else {
-    sig_ok = ssl_public_key_verify(
-        ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
-        hs->peer_pubkey.get(), hs->transcript.buffer_data(),
-        hs->transcript.buffer_len());
+    sig_ok =
+        ssl_public_key_verify(ssl, signature, signature_algorithm,
+                              hs->peer_pubkey.get(), hs->transcript.buffer());
   }
 
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  sig_ok = 1;
+  sig_ok = true;
   ERR_clear_error();
 #endif
   if (!sig_ok) {
diff --git a/ssl/internal.h b/ssl/internal.h
index 092ad8c..4c1f9ea 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -545,10 +545,10 @@
   // to call this function after the handshake buffer is released.
   bool InitHash(uint16_t version, const SSL_CIPHER *cipher);
 
-  const uint8_t *buffer_data() const {
-    return reinterpret_cast<const uint8_t *>(buffer_->data);
+  Span<const uint8_t> buffer() {
+    return MakeConstSpan(reinterpret_cast<const uint8_t *>(buffer_->data),
+                         buffer_->length);
   }
-  size_t buffer_len() const { return buffer_->length; }
 
   // FreeBuffer releases the handshake buffer. Subsequent calls to
   // |Update| will not update the handshake buffer.
@@ -563,7 +563,7 @@
 
   // Update adds |in| to the handshake buffer and handshake hash, whichever is
   // enabled. It returns true on success and false on failure.
-  bool Update(const uint8_t *in, size_t in_len);
+  bool Update(Span<const uint8_t> in);
 
   // GetHash writes the handshake hash to |out| which must have room for at
   // least |DigestLen| bytes. On success, it returns true and sets |*out_len| to
@@ -877,22 +877,24 @@
 
 enum ssl_private_key_result_t ssl_private_key_sign(
     SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
-    uint16_t sigalg, const uint8_t *in, size_t in_len);
+    uint16_t sigalg, Span<const uint8_t> in);
 
-enum ssl_private_key_result_t ssl_private_key_decrypt(
-    SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
-    const uint8_t *in, size_t in_len);
+enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs,
+                                                      uint8_t *out,
+                                                      size_t *out_len,
+                                                      size_t max_out,
+                                                      Span<const uint8_t> in);
 
-// ssl_private_key_supports_signature_algorithm returns one if |hs|'s private
-// key supports |sigalg| and zero otherwise.
-int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
+// ssl_private_key_supports_signature_algorithm returns whether |hs|'s private
+// key supports |sigalg|.
+bool ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
                                                  uint16_t sigalg);
 
 // ssl_public_key_verify verifies that the |signature| is valid for the public
 // key |pkey| and input |in|, using the signature algorithm |sigalg|.
-int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
-                          size_t signature_len, uint16_t sigalg, EVP_PKEY *pkey,
-                          const uint8_t *in, size_t in_len);
+bool ssl_public_key_verify(SSL *ssl, Span<const uint8_t> signature,
+                           uint16_t sigalg, EVP_PKEY *pkey,
+                           Span<const uint8_t> in);
 
 
 // Custom extensions
@@ -1533,11 +1535,10 @@
 
 // tls13_get_cert_verify_signature_input generates the message to be signed for
 // TLS 1.3's CertificateVerify message. |cert_verify_context| determines the
-// type of signature. It sets |*out| and |*out_len| to a newly allocated buffer
-// containing the result. The caller must free it with |OPENSSL_free| to release
-// it. This function returns one on success and zero on failure.
-int tls13_get_cert_verify_signature_input(
-    SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
+// type of signature. It sets |*out| to a newly allocated buffer containing the
+// result. This function returns true on success and false on failure.
+bool tls13_get_cert_verify_signature_input(
+    SSL_HANDSHAKE *hs, Array<uint8_t> *out,
     enum ssl_cert_verify_context_t cert_verify_context);
 
 // ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index b2edc9e..3cc01e9 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -198,7 +198,7 @@
   // 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.data(), msg.size())) {
+      !ssl->s3->hs->transcript.Update(msg)) {
     return 0;
   }
   return 1;
@@ -345,8 +345,7 @@
   // The V2ClientHello without the length is incorporated into the handshake
   // hash. This is only ever called at the start of the handshake, so hs is
   // guaranteed to be non-NULL.
-  if (!ssl->s3->hs->transcript.Update(CBS_data(&v2_client_hello),
-                                      CBS_len(&v2_client_hello))) {
+  if (!ssl->s3->hs->transcript.Update(v2_client_hello)) {
     return -1;
   }
 
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index a07f291..b00613d 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -222,16 +222,16 @@
 
 enum ssl_private_key_result_t ssl_private_key_sign(
     SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
-    uint16_t sigalg, const uint8_t *in, size_t in_len) {
+    uint16_t sigalg, Span<const uint8_t> in) {
   SSL *const ssl = hs->ssl;
   if (ssl->cert->key_method != NULL) {
     enum ssl_private_key_result_t ret;
     if (hs->pending_private_key_op) {
       ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
     } else {
-      ret = (ssl->cert->key_method->sign != NULL
-                 ? ssl->cert->key_method->sign
-                 : legacy_sign)(ssl, out, out_len, max_out, sigalg, in, in_len);
+      ret = (ssl->cert->key_method->sign != NULL ? ssl->cert->key_method->sign
+                                                 : legacy_sign)(
+          ssl, out, out_len, max_out, sigalg, in.data(), in.size());
     }
     hs->pending_private_key_op = ret == ssl_private_key_retry;
     return ret;
@@ -240,31 +240,34 @@
   *out_len = max_out;
   ScopedEVP_MD_CTX ctx;
   if (!setup_ctx(ssl, ctx.get(), ssl->cert->privatekey, sigalg, 0 /* sign */) ||
-      !EVP_DigestSign(ctx.get(), out, out_len, in, in_len)) {
+      !EVP_DigestSign(ctx.get(), out, out_len, in.data(), in.size())) {
     return ssl_private_key_failure;
   }
   return ssl_private_key_success;
 }
 
-int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
-                          size_t signature_len, uint16_t sigalg, EVP_PKEY *pkey,
-                          const uint8_t *in, size_t in_len) {
+bool ssl_public_key_verify(SSL *ssl, Span<const uint8_t> signature,
+                           uint16_t sigalg, EVP_PKEY *pkey,
+                           Span<const uint8_t> in) {
   ScopedEVP_MD_CTX ctx;
   return setup_ctx(ssl, ctx.get(), pkey, sigalg, 1 /* verify */) &&
-         EVP_DigestVerify(ctx.get(), signature, signature_len, in, in_len);
+         EVP_DigestVerify(ctx.get(), signature.data(), signature.size(),
+                          in.data(), in.size());
 }
 
-enum ssl_private_key_result_t ssl_private_key_decrypt(
-    SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
-    const uint8_t *in, size_t in_len) {
+enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs,
+                                                      uint8_t *out,
+                                                      size_t *out_len,
+                                                      size_t max_out,
+                                                      Span<const uint8_t> in) {
   SSL *const ssl = hs->ssl;
   if (ssl->cert->key_method != NULL) {
     enum ssl_private_key_result_t ret;
     if (hs->pending_private_key_op) {
       ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
     } else {
-      ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
-                                           in_len);
+      ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out,
+                                           in.data(), in.size());
     }
     hs->pending_private_key_op = ret == ssl_private_key_retry;
     return ret;
@@ -279,17 +282,18 @@
 
   // Decrypt with no padding. PKCS#1 padding will be removed as part of the
   // timing-sensitive code by the caller.
-  if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
+  if (!RSA_decrypt(rsa, out_len, out, max_out, in.data(), in.size(),
+                   RSA_NO_PADDING)) {
     return ssl_private_key_failure;
   }
   return ssl_private_key_success;
 }
 
-int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
-                                                 uint16_t sigalg) {
+bool ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
+                                                  uint16_t sigalg) {
   SSL *const ssl = hs->ssl;
   if (!pkey_supports_algorithm(ssl, hs->local_pubkey.get(), sigalg)) {
-    return 0;
+    return false;
   }
 
   // Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
@@ -301,7 +305,7 @@
   const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
   if (alg->is_rsa_pss && (size_t)EVP_PKEY_size(hs->local_pubkey.get()) <
                              2 * EVP_MD_size(alg->digest_func()) + 2) {
-    return 0;
+    return false;
   }
 
   // Newer algorithms require message-based private keys.
@@ -309,10 +313,10 @@
   if (ssl->cert->key_method != NULL &&
       ssl->cert->key_method->sign == NULL &&
       !legacy_sign_digest_supported(alg)) {
-    return 0;
+    return false;
   }
 
-  return 1;
+  return true;
 }
 
 }  // namespace bssl
diff --git a/ssl/ssl_transcript.cc b/ssl/ssl_transcript.cc
index b9c1713..8bddbe2 100644
--- a/ssl/ssl_transcript.cc
+++ b/ssl/ssl_transcript.cc
@@ -209,26 +209,26 @@
   return EVP_MD_CTX_md(hash_.get());
 }
 
-bool SSLTranscript::Update(const uint8_t *in, size_t in_len) {
+bool SSLTranscript::Update(Span<const uint8_t> in) {
   // Depending on the state of the handshake, either the handshake buffer may be
   // active, the rolling hash, or both.
   if (buffer_) {
-    size_t new_len = buffer_->length + in_len;
-    if (new_len < in_len) {
+    size_t new_len = buffer_->length + in.size();
+    if (new_len < in.size()) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
       return false;
     }
     if (!BUF_MEM_grow(buffer_.get(), new_len)) {
       return false;
     }
-    OPENSSL_memcpy(buffer_->data + new_len - in_len, in, in_len);
+    OPENSSL_memcpy(buffer_->data + new_len - in.size(), in.data(), in.size());
   }
 
   if (EVP_MD_CTX_md(hash_.get()) != NULL) {
-    EVP_DigestUpdate(hash_.get(), in, in_len);
+    EVP_DigestUpdate(hash_.get(), in.data(), in.size());
   }
   if (EVP_MD_CTX_md(md5_.get()) != NULL) {
-    EVP_DigestUpdate(md5_.get(), in, in_len);
+    EVP_DigestUpdate(md5_.get(), in.data(), in.size());
   }
 
   return true;
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 3ebb15d..32a0471 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -3330,15 +3330,13 @@
 int tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
   SSL *const ssl = hs->ssl;
   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
-    uint8_t *msg;
-    size_t msg_len;
-    if (!tls13_get_cert_verify_signature_input(hs, &msg, &msg_len,
+    Array<uint8_t> msg;
+    if (!tls13_get_cert_verify_signature_input(hs, &msg,
                                                ssl_cert_verify_channel_id)) {
       return 0;
     }
-    SHA256(msg, msg_len, out);
+    SHA256(msg.data(), msg.size(), out);
     *out_len = SHA256_DIGEST_LENGTH;
-    OPENSSL_free(msg);
     return 1;
   }
 
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 1e7bdf1..5796bf4 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -37,57 +37,55 @@
 // without being able to return application data.
 static const uint8_t kMaxKeyUpdates = 32;
 
-int tls13_get_cert_verify_signature_input(
-    SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
+bool tls13_get_cert_verify_signature_input(
+    SSL_HANDSHAKE *hs, Array<uint8_t> *out,
     enum ssl_cert_verify_context_t cert_verify_context) {
   ScopedCBB cbb;
   if (!CBB_init(cbb.get(), 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
+    return false;
   }
 
   for (size_t i = 0; i < 64; i++) {
     if (!CBB_add_u8(cbb.get(), 0x20)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      return 0;
+      return false;
     }
   }
 
-  const uint8_t *context;
-  size_t context_len;
+  Span<const char> context;
   if (cert_verify_context == ssl_cert_verify_server) {
-    // Include the NUL byte.
     static const char kContext[] = "TLS 1.3, server CertificateVerify";
-    context = (const uint8_t *)kContext;
-    context_len = sizeof(kContext);
+    context = kContext;
   } else if (cert_verify_context == ssl_cert_verify_client) {
     static const char kContext[] = "TLS 1.3, client CertificateVerify";
-    context = (const uint8_t *)kContext;
-    context_len = sizeof(kContext);
+    context = kContext;
   } else if (cert_verify_context == ssl_cert_verify_channel_id) {
     static const char kContext[] = "TLS 1.3, Channel ID";
-    context = (const uint8_t *)kContext;
-    context_len = sizeof(kContext);
+    context = kContext;
   } else {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
+    return false;
   }
 
-  if (!CBB_add_bytes(cbb.get(), context, context_len)) {
+  // Note |context| includes the NUL byte separator.
+  if (!CBB_add_bytes(cbb.get(),
+                     reinterpret_cast<const uint8_t *>(context.data()),
+                     context.size())) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
+    return false;
   }
 
   uint8_t context_hash[EVP_MAX_MD_SIZE];
   size_t context_hash_len;
   if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
       !CBB_add_bytes(cbb.get(), context_hash, context_hash_len) ||
-      !CBB_finish(cbb.get(), out, out_len)) {
+      !CBBFinishArray(cbb.get(), out)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
+    return false;
   }
 
-  return 1;
+  return true;
 }
 
 int tls13_process_certificate(SSL_HANDSHAKE *hs, const SSLMessage &msg,
@@ -285,21 +283,18 @@
   }
   hs->new_session->peer_signature_algorithm = signature_algorithm;
 
-  uint8_t *input = NULL;
-  size_t input_len;
+  Array<uint8_t> input;
   if (!tls13_get_cert_verify_signature_input(
-          hs, &input, &input_len,
+          hs, &input,
           ssl->server ? ssl_cert_verify_client : ssl_cert_verify_server)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return 0;
   }
-  UniquePtr<uint8_t> free_input(input);
 
-  int sig_ok = ssl_public_key_verify(ssl, CBS_data(&signature),
-                                     CBS_len(&signature), signature_algorithm,
-                                     hs->peer_pubkey.get(), input, input_len);
+  bool sig_ok = ssl_public_key_verify(ssl, signature, signature_algorithm,
+                                      hs->peer_pubkey.get(), input);
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  sig_ok = 1;
+  sig_ok = true;
   ERR_clear_error();
 #endif
   if (!sig_ok) {
@@ -441,18 +436,16 @@
     return ssl_private_key_failure;
   }
 
-  uint8_t *msg = NULL;
-  size_t msg_len;
+  Array<uint8_t> msg;
   if (!tls13_get_cert_verify_signature_input(
-          hs, &msg, &msg_len,
+          hs, &msg,
           ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return ssl_private_key_failure;
   }
-  UniquePtr<uint8_t> free_msg(msg);
 
   enum ssl_private_key_result_t sign_result = ssl_private_key_sign(
-      hs, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len);
+      hs, sig, &sig_len, max_sig_len, signature_algorithm, msg);
   if (sign_result != ssl_private_key_success) {
     return sign_result;
   }
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc
index e4f14c3..6c7e1da 100644
--- a/ssl/tls13_enc.cc
+++ b/ssl/tls13_enc.cc
@@ -382,8 +382,8 @@
   uint8_t context[EVP_MAX_MD_SIZE];
   unsigned context_len;
   if (!EVP_DigestInit_ex(ctx.get(), digest, NULL) ||
-      !EVP_DigestUpdate(ctx.get(), hs->transcript.buffer_data(),
-                        hs->transcript.buffer_len()) ||
+      !EVP_DigestUpdate(ctx.get(), hs->transcript.buffer().data(),
+                        hs->transcript.buffer().size()) ||
       !EVP_DigestUpdate(ctx.get(), msg, len - hash_len - 3) ||
       !EVP_DigestFinal_ex(ctx.get(), context, &context_len)) {
     return 0;
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index c48c5b4..09437a5 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -668,8 +668,9 @@
     assert(hs->hash_len <= 0xff);
     uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0,
                          static_cast<uint8_t>(hs->hash_len)};
-    if (!hs->transcript.Update(header, sizeof(header)) ||
-        !hs->transcript.Update(hs->expected_client_finished, hs->hash_len) ||
+    if (!hs->transcript.Update(header) ||
+        !hs->transcript.Update(
+            MakeConstSpan(hs->expected_client_finished, hs->hash_len)) ||
         !tls13_derive_resumption_secret(hs) ||
         !add_new_session_tickets(hs)) {
       return ssl_hs_error;