Push Span down a layer.

Change-Id: I893292b140d033a5aed7e08f928a6c32996bb983
Reviewed-on: https://boringssl-review.googlesource.com/21287
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc
index c2f6479..66f59a4 100644
--- a/ssl/d1_both.cc
+++ b/ssl/d1_both.cc
@@ -344,7 +344,7 @@
       // Flag the ChangeCipherSpec for later.
       ssl->d1->has_change_cipher_spec = true;
       ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC,
-                          rr->data, rr->length);
+                          MakeSpan(rr->data, rr->length));
 
       rr->length = 0;
       ssl_read_buffer_discard(ssl);
@@ -433,8 +433,9 @@
   CBS_init(&out->raw, frag->data, DTLS1_HM_HEADER_LENGTH + frag->msg_len);
   out->is_v2_hello = false;
   if (!ssl->s3->has_message) {
-    ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE, frag->data,
-                        frag->msg_len + DTLS1_HM_HEADER_LENGTH);
+    ssl_do_msg_callback(
+        ssl, 0 /* read */, SSL3_RT_HANDSHAKE,
+        MakeSpan(frag->data, frag->msg_len + DTLS1_HM_HEADER_LENGTH));
     ssl->s3->has_message = true;
   }
   return true;
@@ -673,7 +674,7 @@
     }
 
     ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_CHANGE_CIPHER_SPEC,
-                        kChangeCipherSpec, sizeof(kChangeCipherSpec));
+                        kChangeCipherSpec);
     return seal_success;
   }
 
@@ -716,7 +717,8 @@
     return seal_error;
   }
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, frag, frag_len);
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE,
+                      MakeSpan(frag, frag_len));
 
   if (!dtls_seal_record(ssl, out, out_len, max_out, SSL3_RT_HANDSHAKE,
                         out + prefix, frag_len, use_epoch)) {
diff --git a/ssl/d1_pkt.cc b/ssl/d1_pkt.cc
index 91fc647..d9496d9 100644
--- a/ssl/d1_pkt.cc
+++ b/ssl/d1_pkt.cc
@@ -141,7 +141,7 @@
   }
 
   // Read a new packet if there is no unconsumed one.
-  if (ssl_read_buffer_len(ssl) == 0) {
+  if (ssl_read_buffer(ssl).empty()) {
     int read_ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */);
     if (read_ret < 0 && dtls1_is_timer_expired(ssl)) {
       // Historically, timeouts were handled implicitly if the caller did not
@@ -159,14 +159,13 @@
       return read_ret;
     }
   }
-  assert(ssl_read_buffer_len(ssl) > 0);
+  assert(!ssl_read_buffer(ssl).empty());
 
-  CBS body;
+  Span<uint8_t> body;
   uint8_t type, alert;
   size_t consumed;
-  enum ssl_open_record_t open_ret =
-      dtls_open_record(ssl, &type, &body, &consumed, &alert,
-                       ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
+  enum ssl_open_record_t open_ret = dtls_open_record(
+      ssl, &type, &body, &consumed, &alert, ssl_read_buffer(ssl));
   ssl_read_buffer_consume(ssl, consumed);
   switch (open_ret) {
     case ssl_open_record_partial:
@@ -174,15 +173,15 @@
       break;
 
     case ssl_open_record_success: {
-      if (CBS_len(&body) > 0xffff) {
+      if (body.size() > 0xffff) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
         return -1;
       }
 
       SSL3_RECORD *rr = &ssl->s3->rrec;
       rr->type = type;
-      rr->length = (uint16_t)CBS_len(&body);
-      rr->data = (uint8_t *)CBS_data(&body);
+      rr->length = static_cast<uint16_t>(body.size());
+      rr->data = body.data();
       return 1;
     }
 
@@ -368,8 +367,7 @@
     BIO_flush(ssl->wbio);
   }
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert,
-                      2);
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert);
 
   int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
   ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
diff --git a/ssl/dtls_record.cc b/ssl/dtls_record.cc
index 5009f04..71b5e3b 100644
--- a/ssl/dtls_record.cc
+++ b/ssl/dtls_record.cc
@@ -174,14 +174,13 @@
   }
 }
 
-enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type,
+                                        Span<uint8_t> *out,
                                         size_t *out_consumed,
-                                        uint8_t *out_alert, uint8_t *in,
-                                        size_t in_len) {
+                                        uint8_t *out_alert, Span<uint8_t> in) {
   *out_consumed = 0;
 
-  CBS cbs;
-  CBS_init(&cbs, in, in_len);
+  CBS cbs = CBS(in);
 
   // Decode the record.
   uint8_t type;
@@ -194,7 +193,7 @@
       !CBS_get_u16_length_prefixed(&cbs, &body) ||
       CBS_len(&body) > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
     // The record header was incomplete or malformed. Drop the entire packet.
-    *out_consumed = in_len;
+    *out_consumed = in.size();
     return ssl_open_record_discard;
   }
 
@@ -209,12 +208,12 @@
 
   if (!version_ok) {
     // The record header was incomplete or malformed. Drop the entire packet.
-    *out_consumed = in_len;
+    *out_consumed = in.size();
     return ssl_open_record_discard;
   }
 
-  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
-                      DTLS1_RT_HEADER_LENGTH);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER,
+                      in.subspan(0, DTLS1_RT_HEADER_LENGTH));
 
   uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1];
   if (epoch != ssl->d1->r_epoch ||
@@ -223,14 +222,14 @@
     // |epoch| is the next epoch, the record could be buffered for later. For
     // simplicity, drop it and expect retransmit to handle it later; DTLS must
     // handle packet loss anyway.
-    *out_consumed = in_len - CBS_len(&cbs);
+    *out_consumed = in.size() - CBS_len(&cbs);
     return ssl_open_record_discard;
   }
 
-  // Decrypt the body in-place.
-  if (!ssl->s3->aead_read_ctx->Open(out, type, version, sequence,
-                                    (uint8_t *)CBS_data(&body),
-                                    CBS_len(&body))) {
+  // discard the body in-place.
+  if (!ssl->s3->aead_read_ctx->Open(
+          out, type, version, sequence,
+          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
     // entire packet as it must not have come from the peer.
@@ -238,13 +237,13 @@
     // TODO(davidben): This doesn't distinguish malloc failures from encryption
     // failures.
     ERR_clear_error();
-    *out_consumed = in_len - CBS_len(&cbs);
+    *out_consumed = in.size() - CBS_len(&cbs);
     return ssl_open_record_discard;
   }
-  *out_consumed = in_len - CBS_len(&cbs);
+  *out_consumed = in.size() - CBS_len(&cbs);
 
   // Check the plaintext length.
-  if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) {
+  if (out->size() > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
     *out_alert = SSL_AD_RECORD_OVERFLOW;
     return ssl_open_record_error;
@@ -256,7 +255,7 @@
   // useful if we also limit discarded packets.
 
   if (type == SSL3_RT_ALERT) {
-    return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out));
+    return ssl_process_alert(ssl, out_alert, *out);
   }
 
   ssl->s3->warning_alert_count = 0;
@@ -338,8 +337,8 @@
 
   *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len;
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out,
-                      DTLS1_RT_HEADER_LENGTH);
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER,
+                      MakeSpan(out, DTLS1_RT_HEADER_LENGTH));
 
   return 1;
 }
diff --git a/ssl/internal.h b/ssl/internal.h
index b9a597c..36d3390 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -657,12 +657,11 @@
   bool SuffixLen(size_t *out_suffix_len, size_t in_len,
                  size_t extra_in_len) const;
 
-  // Open authenticates and decrypts |in_len| bytes from |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(CBS *out, uint8_t type, uint16_t record_version,
-            const uint8_t seqnum[8], uint8_t *in, size_t in_len);
+  // 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);
 
   // Seal encrypts and authenticates |in_len| bytes from |in| and writes the
   // result to |out|. It returns true on success and false on error.
@@ -790,16 +789,16 @@
 //
 // On failure or fatal alert, it returns |ssl_open_record_error| and sets
 // |*out_alert| to an alert to emit, or zero if no alert should be emitted.
-enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
-                                       size_t *out_consumed, uint8_t *out_alert,
-                                       uint8_t *in, size_t in_len);
+enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type,
+                                       Span<uint8_t> *out, size_t *out_consumed,
+                                       uint8_t *out_alert, Span<uint8_t> in);
 
 // dtls_open_record implements |tls_open_record| for DTLS. It never returns
 // |ssl_open_record_partial| but otherwise behaves analogously.
-enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type,
+                                        Span<uint8_t> *out,
                                         size_t *out_consumed,
-                                        uint8_t *out_alert, uint8_t *in,
-                                        size_t in_len);
+                                        uint8_t *out_alert, Span<uint8_t> in);
 
 // ssl_seal_align_prefix_len returns the length of the prefix before the start
 // of the bulk of the ciphertext when sealing a record with |ssl|. Callers may
@@ -853,7 +852,7 @@
 // |ssl_open_record_close_notify|, or |ssl_open_record_fatal_alert| as
 // appropriate.
 enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
-                                         const uint8_t *in, size_t in_len);
+                                         Span<const uint8_t> in);
 
 
 // Private key operations.
@@ -1013,16 +1012,13 @@
 
 // ssl_do_msg_callback calls |ssl|'s message callback, if set.
 void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
-                         const void *buf, size_t len);
+                         Span<const uint8_t> in);
 
 
 // Transport buffers.
 
-// ssl_read_buffer returns a pointer to contents of the read buffer.
-uint8_t *ssl_read_buffer(SSL *ssl);
-
-// ssl_read_buffer_len returns the length of the read buffer.
-size_t ssl_read_buffer_len(const SSL *ssl);
+// ssl_read_buffer returns the current read buffer.
+Span<uint8_t> ssl_read_buffer(SSL *ssl);
 
 // ssl_read_buffer_extend_to extends the read buffer to the desired length. For
 // TLS, it reads to the end of the buffer until the buffer is |len| bytes
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index 65e2089..d63d133 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -194,8 +194,7 @@
     }
   } while (!rest.empty());
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg.data(),
-                      msg.size());
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg);
   // TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript on
   // hs.
   if (ssl->s3->hs != NULL &&
@@ -214,7 +213,7 @@
   }
 
   ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_CHANGE_CIPHER_SPEC,
-                      kChangeCipherSpec, sizeof(kChangeCipherSpec));
+                      kChangeCipherSpec);
   return 1;
 }
 
@@ -224,7 +223,7 @@
     return 0;
   }
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, alert, sizeof(alert));
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, alert);
   ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, ((int)level << 8) | desc);
   return 1;
 }
@@ -359,7 +358,7 @@
   if (ret <= 0) {
     return ret;
   }
-  const uint8_t *p = ssl_read_buffer(ssl);
+  const uint8_t *p = ssl_read_buffer(ssl).data();
 
   // Some dedicated error codes for protocol mixups should the application wish
   // to interpret them differently. (These do not overlap with ClientHello or
@@ -402,9 +401,7 @@
     return ret;
   }
 
-  CBS v2_client_hello;
-  CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length);
-
+  CBS v2_client_hello = CBS(ssl_read_buffer(ssl).subspan(2, msg_length));
   // 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.
@@ -414,7 +411,7 @@
   }
 
   ssl_do_msg_callback(ssl, 0 /* read */, 0 /* V2ClientHello */,
-                      CBS_data(&v2_client_hello), CBS_len(&v2_client_hello));
+                      v2_client_hello);
 
   uint8_t msg_type;
   uint16_t version, cipher_spec_length, session_id_length, challenge_length;
@@ -530,8 +527,7 @@
   out->is_v2_hello = ssl->s3->is_v2_hello;
   if (!ssl->s3->has_message) {
     if (!out->is_v2_hello) {
-      ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE,
-                          CBS_data(&out->raw), CBS_len(&out->raw));
+      ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE, out->raw);
     }
     ssl->s3->has_message = true;
   }
diff --git a/ssl/s3_pkt.cc b/ssl/s3_pkt.cc
index 5334145..48de23f 100644
--- a/ssl/s3_pkt.cc
+++ b/ssl/s3_pkt.cc
@@ -141,12 +141,11 @@
       return 0;
   }
 
-  CBS body;
+  Span<uint8_t> body;
   uint8_t type, alert = SSL_AD_DECODE_ERROR;
   size_t consumed;
-  enum ssl_open_record_t open_ret =
-      tls_open_record(ssl, &type, &body, &consumed, &alert,
-                      ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
+  enum ssl_open_record_t open_ret = tls_open_record(
+      ssl, &type, &body, &consumed, &alert, ssl_read_buffer(ssl));
   if (open_ret != ssl_open_record_partial) {
     ssl_read_buffer_consume(ssl, consumed);
   }
@@ -160,15 +159,15 @@
     }
 
     case ssl_open_record_success: {
-      if (CBS_len(&body) > 0xffff) {
+      if (body.size() > 0xffff) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
         return -1;
       }
 
       SSL3_RECORD *rr = &ssl->s3->rrec;
       rr->type = type;
-      rr->length = (uint16_t)CBS_len(&body);
-      rr->data = (uint8_t *)CBS_data(&body);
+      rr->length = static_cast<uint16_t>(body.size());
+      rr->data = body.data();
       return 1;
     }
 
@@ -483,8 +482,8 @@
     return -1;
   }
 
-  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data,
-                      rr->length);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC,
+                      MakeSpan(rr->data, rr->length));
 
   rr->length = 0;
   ssl_read_buffer_discard(ssl);
@@ -575,8 +574,7 @@
     BIO_flush(ssl->wbio);
   }
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert,
-                      2);
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert);
 
   int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
   ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
diff --git a/ssl/ssl_aead_ctx.cc b/ssl/ssl_aead_ctx.cc
index 8856f74..775827c 100644
--- a/ssl/ssl_aead_ctx.cc
+++ b/ssl/ssl_aead_ctx.cc
@@ -225,11 +225,12 @@
   return len;
 }
 
-bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t record_version,
-                          const uint8_t seqnum[8], uint8_t *in, size_t in_len) {
+bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type,
+                          uint16_t record_version, const uint8_t seqnum[8],
+                          Span<uint8_t> in) {
   if (is_null_cipher() || FUZZER_MODE) {
     // Handle the initial NULL cipher.
-    CBS_init(out, in, in_len);
+    *out = in;
     return true;
   }
 
@@ -238,12 +239,12 @@
   size_t plaintext_len = 0;
   if (!omit_length_in_ad_) {
     size_t overhead = MaxOverhead();
-    if (in_len < overhead) {
+    if (in.size() < overhead) {
       // Publicly invalid.
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
       return false;
     }
-    plaintext_len = in_len - overhead;
+    plaintext_len = in.size() - overhead;
   }
   uint8_t ad[13];
   size_t ad_len =
@@ -264,14 +265,13 @@
 
   // Add the variable nonce.
   if (variable_nonce_included_in_record_) {
-    if (in_len < variable_nonce_len_) {
+    if (in.size() < variable_nonce_len_) {
       // Publicly invalid.
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
       return false;
     }
-    OPENSSL_memcpy(nonce + nonce_len, in, variable_nonce_len_);
-    in += variable_nonce_len_;
-    in_len -= variable_nonce_len_;
+    OPENSSL_memcpy(nonce + nonce_len, in.data(), variable_nonce_len_);
+    in = in.subspan(variable_nonce_len_);
   } else {
     assert(variable_nonce_len_ == 8);
     OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_);
@@ -288,11 +288,11 @@
 
   // Decrypt in-place.
   size_t len;
-  if (!EVP_AEAD_CTX_open(ctx_.get(), in, &len, in_len, nonce, nonce_len, in,
-                         in_len, ad, ad_len)) {
+  if (!EVP_AEAD_CTX_open(ctx_.get(), in.data(), &len, in.size(), nonce,
+                         nonce_len, in.data(), in.size(), ad, ad_len)) {
     return false;
   }
-  CBS_init(out, in, len);
+  *out = in.subspan(0, len);
   return true;
 }
 
diff --git a/ssl/ssl_buffer.cc b/ssl/ssl_buffer.cc
index b424138..79f0cae 100644
--- a/ssl/ssl_buffer.cc
+++ b/ssl/ssl_buffer.cc
@@ -89,12 +89,9 @@
   OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
 }
 
-uint8_t *ssl_read_buffer(SSL *ssl) {
-  return ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset;
-}
-
-size_t ssl_read_buffer_len(const SSL *ssl) {
-  return ssl->s3->read_buffer.len;
+Span<uint8_t> ssl_read_buffer(SSL *ssl) {
+  return MakeSpan(ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset,
+                  ssl->s3->read_buffer.len);
 }
 
 static int dtls_read_buffer_next_packet(SSL *ssl) {
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index 094d85a..de761d6 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -599,7 +599,8 @@
       !CBS_get_optional_asn1(
           &tbs_cert, &outer_extensions, &has_extensions,
           CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) {
-    goto parse_err;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+    return 0;
   }
 
   if (!has_extensions) {
@@ -608,7 +609,8 @@
 
   CBS extensions;
   if (!CBS_get_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) {
-    goto parse_err;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+    return 0;
   }
 
   while (CBS_len(&extensions) > 0) {
@@ -619,7 +621,8 @@
          !CBS_get_asn1(&extension, NULL, CBS_ASN1_BOOLEAN)) ||
         !CBS_get_asn1(&extension, &contents, CBS_ASN1_OCTETSTRING) ||
         CBS_len(&extension) != 0) {
-      goto parse_err;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+      return 0;
     }
 
     static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f};
@@ -632,13 +635,15 @@
     CBS bit_string;
     if (!CBS_get_asn1(&contents, &bit_string, CBS_ASN1_BITSTRING) ||
         CBS_len(&contents) != 0) {
-      goto parse_err;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+      return 0;
     }
 
     // This is the KeyUsage extension. See
     // https://tools.ietf.org/html/rfc5280#section-4.2.1.3
     if (!CBS_is_valid_asn1_bitstring(&bit_string)) {
-      goto parse_err;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+      return 0;
     }
 
     if (!CBS_asn1_bitstring_has_bit(&bit_string, 0)) {
@@ -651,10 +656,6 @@
 
   // No KeyUsage extension found.
   return 1;
-
-parse_err:
-  OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
-  return 0;
 }
 
 UniquePtr<STACK_OF(CRYPTO_BUFFER)> ssl_parse_client_CA_list(SSL *ssl,
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index f62d155..89eb6fe 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -344,7 +344,7 @@
 }
 
 void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
-                         const void *buf, size_t len) {
+                         Span<const uint8_t> in) {
   if (ssl->msg_callback == NULL) {
     return;
   }
@@ -364,7 +364,7 @@
       version = SSL_version(ssl);
   }
 
-  ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
+  ssl->msg_callback(is_write, version, content_type, in.data(), in.size(), ssl,
                     ssl->msg_callback_arg);
 }
 
diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc
index f9033e6..b70e4f5 100644
--- a/ssl/tls_record.cc
+++ b/ssl/tls_record.cc
@@ -187,13 +187,12 @@
   return ret;
 }
 
-enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
-                                       size_t *out_consumed, uint8_t *out_alert,
-                                       uint8_t *in, size_t in_len) {
+enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type,
+                                       Span<uint8_t> *out, size_t *out_consumed,
+                                       uint8_t *out_alert, Span<uint8_t> in) {
   *out_consumed = 0;
 
-  CBS cbs;
-  CBS_init(&cbs, in, in_len);
+  CBS cbs = CBS(in);
 
   // Decode the record header.
   uint8_t type;
@@ -234,10 +233,10 @@
     return ssl_open_record_partial;
   }
 
-  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
-                      SSL3_RT_HEADER_LENGTH);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER,
+                      in.subspan(0, SSL3_RT_HEADER_LENGTH));
 
-  *out_consumed = in_len - CBS_len(&cbs);
+  *out_consumed = in.size() - CBS_len(&cbs);
 
   // Skip early data received when expecting a second ClientHello if we rejected
   // 0RTT.
@@ -248,9 +247,9 @@
   }
 
   // Decrypt the body in-place.
-  if (!ssl->s3->aead_read_ctx->Open(out, type, version, ssl->s3->read_sequence,
-                                    (uint8_t *)CBS_data(&body),
-                                    CBS_len(&body))) {
+  if (!ssl->s3->aead_read_ctx->Open(
+          out, type, version, ssl->s3->read_sequence,
+          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();
       goto skipped_data;
@@ -279,23 +278,25 @@
     }
 
     do {
-      if (!CBS_get_last_u8(out, &type)) {
+      if (out->empty()) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
         *out_alert = SSL_AD_DECRYPT_ERROR;
         return ssl_open_record_error;
       }
+      type = out->back();
+      *out = out->subspan(0, out->size() - 1);
     } while (type == 0);
   }
 
   // Check the plaintext length.
-  if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) {
+  if (out->size() > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
     *out_alert = SSL_AD_RECORD_OVERFLOW;
     return ssl_open_record_error;
   }
 
   // Limit the number of consecutive empty records.
-  if (CBS_len(out) == 0) {
+  if (out->empty()) {
     ssl->s3->empty_record_count++;
     if (ssl->s3->empty_record_count > kMaxEmptyRecords) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_EMPTY_FRAGMENTS);
@@ -310,14 +311,14 @@
 
   if (type == SSL3_RT_ALERT) {
     // Return end_of_early_data alerts as-is for the caller to process.
-    if (CBS_len(out) == 2 &&
-        CBS_data(out)[0] == SSL3_AL_WARNING &&
-        CBS_data(out)[1] == TLS1_AD_END_OF_EARLY_DATA) {
+    if (out->size() == 2 &&
+        (*out)[0] == SSL3_AL_WARNING &&
+        (*out)[1] == TLS1_AD_END_OF_EARLY_DATA) {
       *out_type = type;
       return ssl_open_record_success;
     }
 
-    return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out));
+    return ssl_process_alert(ssl, out_alert, *out);
   }
 
   ssl->s3->warning_alert_count = 0;
@@ -390,8 +391,8 @@
     return 0;
   }
 
-  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out_prefix,
-                      SSL3_RT_HEADER_LENGTH);
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER,
+                      MakeSpan(out_prefix, SSL3_RT_HEADER_LENGTH));
   return 1;
 }
 
@@ -516,15 +517,15 @@
 }
 
 enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
-                                         const uint8_t *in, size_t in_len) {
+                                         Span<const uint8_t> in) {
   // Alerts records may not contain fragmented or multiple alerts.
-  if (in_len != 2) {
+  if (in.size() != 2) {
     *out_alert = SSL_AD_DECODE_ERROR;
     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
     return ssl_open_record_error;
   }
 
-  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_ALERT, in, in_len);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_ALERT, in);
 
   const uint8_t alert_level = in[0];
   const uint8_t alert_descr = in[1];
@@ -584,10 +585,10 @@
     return OpenRecordResult::kError;
   }
 
-  CBS plaintext;
+  Span<uint8_t> plaintext;
   uint8_t type;
   const ssl_open_record_t result = tls_open_record(
-      ssl, &type, &plaintext, out_record_len, out_alert, in.data(), in.size());
+      ssl, &type, &plaintext, out_record_len, out_alert, in);
 
   switch (result) {
     case ssl_open_record_success:
@@ -595,8 +596,7 @@
         *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
         return OpenRecordResult::kError;
       }
-      *out = MakeSpan(
-          const_cast<uint8_t*>(CBS_data(&plaintext)), CBS_len(&plaintext));
+      *out = plaintext;
       return OpenRecordResult::kOK;
     case ssl_open_record_discard:
       return OpenRecordResult::kDiscard;