Put SCTs and OCSP responses in CRYPTO_BUFFERs.

They both can be moderately large. This should hopefully relieve a little
memory pressure from both connections to hosts which serve SCTs and
TLS 1.3's single-use tickets.

Change-Id: I034bbf057fe5a064015a0f554b3ae9ea7797cd4e
Reviewed-on: https://boringssl-review.googlesource.com/19584
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/handshake_client.cc b/ssl/handshake_client.cc
index dd09797..e3c4641 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -1162,9 +1162,10 @@
     return -1;
   }
 
-  if (!CBS_stow(&ocsp_response, &hs->new_session->ocsp_response,
-                &hs->new_session->ocsp_response_length)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+  CRYPTO_BUFFER_free(hs->new_session->ocsp_response);
+  hs->new_session->ocsp_response =
+      CRYPTO_BUFFER_new_from_CBS(&ocsp_response, ssl->ctx->pool);
+  if (hs->new_session->ocsp_response == nullptr) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return -1;
   }
diff --git a/ssl/ssl_asn1.cc b/ssl/ssl_asn1.cc
index 0cf90d1..b87c795 100644
--- a/ssl/ssl_asn1.cc
+++ b/ssl/ssl_asn1.cc
@@ -311,20 +311,22 @@
     }
   }
 
-  if (in->tlsext_signed_cert_timestamp_list_length > 0) {
+  if (in->signed_cert_timestamp_list != nullptr) {
     if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
         !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
-        !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list,
-                       in->tlsext_signed_cert_timestamp_list_length)) {
+        !CBB_add_bytes(&child2,
+                       CRYPTO_BUFFER_data(in->signed_cert_timestamp_list),
+                       CRYPTO_BUFFER_len(in->signed_cert_timestamp_list))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
   }
 
-  if (in->ocsp_response_length > 0) {
+  if (in->ocsp_response != nullptr) {
     if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
         !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
-        !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) {
+        !CBB_add_bytes(&child2, CRYPTO_BUFFER_data(in->ocsp_response),
+                       CRYPTO_BUFFER_len(in->ocsp_response))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
@@ -470,6 +472,29 @@
   return 1;
 }
 
+static int SSL_SESSION_parse_crypto_buffer(CBS *cbs, CRYPTO_BUFFER **out,
+                                           unsigned tag,
+                                           CRYPTO_BUFFER_POOL *pool) {
+  if (!CBS_peek_asn1_tag(cbs, tag)) {
+    return 1;
+  }
+
+  CBS child, value;
+  if (!CBS_get_asn1(cbs, &child, tag) ||
+      !CBS_get_asn1(&child, &value, CBS_ASN1_OCTETSTRING) ||
+      CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+    return 0;
+  }
+  CRYPTO_BUFFER_free(*out);
+  *out = CRYPTO_BUFFER_new_from_CBS(&value, pool);
+  if (*out == nullptr) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+  return 1;
+}
+
 /* SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING
  * explicitly tagged with |tag| of size at most |max_out|. */
 static int SSL_SESSION_parse_bounded_octet_string(
@@ -635,13 +660,11 @@
           &session, ret->original_handshake_hash,
           &ret->original_handshake_hash_len,
           sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) ||
-      !SSL_SESSION_parse_octet_string(
-          &session, &ret->tlsext_signed_cert_timestamp_list,
-          &ret->tlsext_signed_cert_timestamp_list_length,
-          kSignedCertTimestampListTag) ||
-      !SSL_SESSION_parse_octet_string(
-          &session, &ret->ocsp_response, &ret->ocsp_response_length,
-          kOCSPResponseTag)) {
+      !SSL_SESSION_parse_crypto_buffer(&session,
+                                       &ret->signed_cert_timestamp_list,
+                                       kSignedCertTimestampListTag, pool) ||
+      !SSL_SESSION_parse_crypto_buffer(&session, &ret->ocsp_response,
+                                       kOCSPResponseTag, pool)) {
     return nullptr;
   }
 
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 026e218..32ec272 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -1811,28 +1811,27 @@
 void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out,
                                          size_t *out_len) {
   SSL_SESSION *session = SSL_get_session(ssl);
-
-  *out_len = 0;
-  *out = NULL;
-  if (ssl->server || !session || !session->tlsext_signed_cert_timestamp_list) {
+  if (ssl->server || !session || !session->signed_cert_timestamp_list) {
+    *out_len = 0;
+    *out = NULL;
     return;
   }
 
-  *out = session->tlsext_signed_cert_timestamp_list;
-  *out_len = session->tlsext_signed_cert_timestamp_list_length;
+  *out = CRYPTO_BUFFER_data(session->signed_cert_timestamp_list);
+  *out_len = CRYPTO_BUFFER_len(session->signed_cert_timestamp_list);
 }
 
 void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out,
                             size_t *out_len) {
   SSL_SESSION *session = SSL_get_session(ssl);
-
-  *out_len = 0;
-  *out = NULL;
   if (ssl->server || !session || !session->ocsp_response) {
+    *out_len = 0;
+    *out = NULL;
     return;
   }
-  *out = session->ocsp_response;
-  *out_len = session->ocsp_response_length;
+
+  *out = CRYPTO_BUFFER_data(session->ocsp_response);
+  *out_len = CRYPTO_BUFFER_len(session->ocsp_response);
 }
 
 int SSL_set_tlsext_host_name(SSL *ssl, const char *name) {
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index dad0656..6bacc80 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -227,24 +227,15 @@
 
   new_session->verify_result = session->verify_result;
 
-  new_session->ocsp_response_length = session->ocsp_response_length;
   if (session->ocsp_response != NULL) {
-    new_session->ocsp_response = (uint8_t *)BUF_memdup(
-        session->ocsp_response, session->ocsp_response_length);
-    if (new_session->ocsp_response == NULL) {
-      return nullptr;
-    }
+    new_session->ocsp_response = session->ocsp_response;
+    CRYPTO_BUFFER_up_ref(new_session->ocsp_response);
   }
 
-  new_session->tlsext_signed_cert_timestamp_list_length =
-      session->tlsext_signed_cert_timestamp_list_length;
-  if (session->tlsext_signed_cert_timestamp_list != NULL) {
-    new_session->tlsext_signed_cert_timestamp_list = (uint8_t *)BUF_memdup(
-        session->tlsext_signed_cert_timestamp_list,
-        session->tlsext_signed_cert_timestamp_list_length);
-    if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
-      return nullptr;
-    }
+  if (session->signed_cert_timestamp_list != NULL) {
+    new_session->signed_cert_timestamp_list =
+        session->signed_cert_timestamp_list;
+    CRYPTO_BUFFER_up_ref(new_session->signed_cert_timestamp_list);
   }
 
   OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
@@ -898,8 +889,8 @@
   session->x509_method->session_clear(session);
   OPENSSL_free(session->tlsext_hostname);
   OPENSSL_free(session->tlsext_tick);
-  OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
-  OPENSSL_free(session->ocsp_response);
+  CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
+  CRYPTO_BUFFER_free(session->ocsp_response);
   OPENSSL_free(session->psk_identity);
   OPENSSL_free(session->early_alpn);
   OPENSSL_cleanse(session, sizeof(*session));
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index bbe6401..e50710a 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -1327,11 +1327,14 @@
    * requirement, so tolerate this.
    *
    * TODO(davidben): Enforce this anyway. */
-  if (!ssl->s3->session_reused &&
-      !CBS_stow(contents, &hs->new_session->tlsext_signed_cert_timestamp_list,
-                &hs->new_session->tlsext_signed_cert_timestamp_list_length)) {
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-    return 0;
+  if (!ssl->s3->session_reused) {
+    CRYPTO_BUFFER_free(hs->new_session->signed_cert_timestamp_list);
+    hs->new_session->signed_cert_timestamp_list =
+        CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool);
+    if (hs->new_session->signed_cert_timestamp_list == nullptr) {
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      return 0;
+    }
   }
 
   return 1;
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 39e0cb3..6e7260e 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -284,11 +284,14 @@
         return 0;
       }
 
-      if (sk_CRYPTO_BUFFER_num(certs.get()) == 1 &&
-          !CBS_stow(&ocsp_response, &hs->new_session->ocsp_response,
-                    &hs->new_session->ocsp_response_length)) {
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        return 0;
+      if (sk_CRYPTO_BUFFER_num(certs.get()) == 1) {
+        CRYPTO_BUFFER_free(hs->new_session->ocsp_response);
+        hs->new_session->ocsp_response =
+            CRYPTO_BUFFER_new_from_CBS(&ocsp_response, ssl->ctx->pool);
+        if (hs->new_session->ocsp_response == nullptr) {
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+          return 0;
+        }
       }
     }
 
@@ -305,12 +308,14 @@
         return 0;
       }
 
-      if (sk_CRYPTO_BUFFER_num(certs.get()) == 1 &&
-          !CBS_stow(
-              &sct, &hs->new_session->tlsext_signed_cert_timestamp_list,
-              &hs->new_session->tlsext_signed_cert_timestamp_list_length)) {
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        return 0;
+      if (sk_CRYPTO_BUFFER_num(certs.get()) == 1) {
+        CRYPTO_BUFFER_free(hs->new_session->signed_cert_timestamp_list);
+        hs->new_session->signed_cert_timestamp_list =
+            CRYPTO_BUFFER_new_from_CBS(&sct, ssl->ctx->pool);
+        if (hs->new_session->signed_cert_timestamp_list == nullptr) {
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+          return 0;
+        }
       }
     }
   }