Give SSL_SESSION a destructor.

Previously we'd partially attempted the ssl_st / bssl::SSLConnection
subclassing split, but that gets messy when we actually try to add a
destructor, because CRYPTO_EX_DATA's cleanup function needs an ssl_st*,
not a bssl::SSLConnection*. Downcasting is technically undefined at this
point and will likely offend some CFI-like check.

Moreover, it appears that even with today's subclassing split,
New<SSL>() emits symbols like:

W ssl_st*& std::forward<ssl_st*&>(std::remove_reference<ssl_st*&>::type&)

The compiler does not bother emitting them in optimized builds, but it
does suggest we can't really avoid claiming the ssl_st type name at the
symbol level, short of doing reinterpret_casts at all API boundaries.
And, of course, we've already long claimed it at the #include level.

So I've just left this defining directly on ssl_session_st. The cost is
we need to write some silly "bssl::" prefixes in the headers, but so it
goes. In the likely event we change our minds again, we can always
revise this.

Change-Id: Ieb429e8eaabe7c2961ef7f8d9234fb71f19a5e2a
Reviewed-on: https://boringssl-review.googlesource.com/29587
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_asn1.cc b/ssl/ssl_asn1.cc
index 54e87bf..5dfacb2 100644
--- a/ssl/ssl_asn1.cc
+++ b/ssl/ssl_asn1.cc
@@ -224,8 +224,8 @@
 
   // The peer certificate is only serialized if the SHA-256 isn't
   // serialized instead.
-  if (sk_CRYPTO_BUFFER_num(in->certs) > 0 && !in->peer_sha256_valid) {
-    const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, 0);
+  if (sk_CRYPTO_BUFFER_num(in->certs.get()) > 0 && !in->peer_sha256_valid) {
+    const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), 0);
     if (!CBB_add_asn1(&session, &child, kPeerTag) ||
         !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
                        CRYPTO_BUFFER_len(buffer))) {
@@ -252,25 +252,26 @@
 
   if (in->psk_identity) {
     if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
-        !CBB_add_asn1_octet_string(&child, (const uint8_t *)in->psk_identity,
-                                   strlen(in->psk_identity))) {
+        !CBB_add_asn1_octet_string(&child,
+                                   (const uint8_t *)in->psk_identity.get(),
+                                   strlen(in->psk_identity.get()))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
   }
 
-  if (in->tlsext_tick_lifetime_hint > 0) {
+  if (in->ticket_lifetime_hint > 0) {
     if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
-        !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) {
+        !CBB_add_asn1_uint64(&child, in->ticket_lifetime_hint)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
   }
 
-  if (in->tlsext_tick && !for_ticket) {
+  if (!in->ticket.empty() && !for_ticket) {
     if (!CBB_add_asn1(&session, &child, kTicketTag) ||
-        !CBB_add_asn1_octet_string(&child, in->tlsext_tick,
-                                   in->tlsext_ticklen)) {
+        !CBB_add_asn1_octet_string(&child, in->ticket.data(),
+                                   in->ticket.size())) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
@@ -297,8 +298,8 @@
   if (in->signed_cert_timestamp_list != nullptr) {
     if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
         !CBB_add_asn1_octet_string(
-            &child, CRYPTO_BUFFER_data(in->signed_cert_timestamp_list),
-            CRYPTO_BUFFER_len(in->signed_cert_timestamp_list))) {
+            &child, CRYPTO_BUFFER_data(in->signed_cert_timestamp_list.get()),
+            CRYPTO_BUFFER_len(in->signed_cert_timestamp_list.get()))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
@@ -306,9 +307,9 @@
 
   if (in->ocsp_response != nullptr) {
     if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
-        !CBB_add_asn1_octet_string(&child,
-                                   CRYPTO_BUFFER_data(in->ocsp_response),
-                                   CRYPTO_BUFFER_len(in->ocsp_response))) {
+        !CBB_add_asn1_octet_string(
+            &child, CRYPTO_BUFFER_data(in->ocsp_response.get()),
+            CRYPTO_BUFFER_len(in->ocsp_response.get()))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
@@ -333,13 +334,13 @@
   // serialized instead.
   if (in->certs != NULL &&
       !in->peer_sha256_valid &&
-      sk_CRYPTO_BUFFER_num(in->certs) >= 2) {
+      sk_CRYPTO_BUFFER_num(in->certs.get()) >= 2) {
     if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
-    for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) {
-      const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i);
+    for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs.get()); i++) {
+      const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), i);
       if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
                          CRYPTO_BUFFER_len(buffer))) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -386,10 +387,10 @@
     return 0;
   }
 
-  if (in->early_alpn) {
+  if (!in->early_alpn.empty()) {
     if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) ||
-        !CBB_add_asn1_octet_string(&child, (const uint8_t *)in->early_alpn,
-                                   in->early_alpn_len)) {
+        !CBB_add_asn1_octet_string(&child, in->early_alpn.data(),
+                                   in->early_alpn.size())) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
@@ -398,13 +399,11 @@
   return CBB_flush(cbb);
 }
 
-// SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
-// explicitly tagged with |tag| from |cbs| and saves it in |*out|. On
-// entry, if |*out| is not NULL, it frees the existing contents. If
-// the element was not found, it sets |*out| to NULL. It returns one
-// on success, whether or not the element was found, and zero on
-// decode error.
-static int SSL_SESSION_parse_string(CBS *cbs, char **out, unsigned tag) {
+// SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING explicitly
+// tagged with |tag| from |cbs| and saves it in |*out|. If the element was not
+// found, it sets |*out| to NULL. It returns one on success, whether or not the
+// element was found, and zero on decode error.
+static int SSL_SESSION_parse_string(CBS *cbs, UniquePtr<char> *out, unsigned tag) {
   CBS value;
   int present;
   if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) {
@@ -416,38 +415,33 @@
       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
       return 0;
     }
-    if (!CBS_strdup(&value, out)) {
+    char *raw = nullptr;
+    if (!CBS_strdup(&value, &raw)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;
     }
+    out->reset(raw);
   } else {
-    OPENSSL_free(*out);
-    *out = NULL;
+    out->reset();
   }
   return 1;
 }
 
-// SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
-// explicitly tagged with |tag| from |cbs| and stows it in |*out_ptr|
-// and |*out_len|. If |*out_ptr| is not NULL, it frees the existing
-// contents. On entry, if the element was not found, it sets
-// |*out_ptr| to NULL. It returns one on success, whether or not the
-// element was found, and zero on decode error.
-static int SSL_SESSION_parse_octet_string(CBS *cbs, uint8_t **out_ptr,
-                                          size_t *out_len, unsigned tag) {
+// SSL_SESSION_parse_octet_string gets an optional ASN.1 OCTET STRING explicitly
+// tagged with |tag| from |cbs| and stows it in |*out|. It returns one on
+// success, whether or not the element was found, and zero on decode error.
+static bool SSL_SESSION_parse_octet_string(CBS *cbs, Array<uint8_t> *out,
+                                           unsigned tag) {
   CBS value;
   if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
-    return 0;
+    return false;
   }
-  if (!CBS_stow(&value, out_ptr, out_len)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-  return 1;
+  return out->CopyFrom(value);
 }
 
-static int SSL_SESSION_parse_crypto_buffer(CBS *cbs, CRYPTO_BUFFER **out,
+static int SSL_SESSION_parse_crypto_buffer(CBS *cbs,
+                                           UniquePtr<CRYPTO_BUFFER> *out,
                                            unsigned tag,
                                            CRYPTO_BUFFER_POOL *pool) {
   if (!CBS_peek_asn1_tag(cbs, tag)) {
@@ -461,8 +455,7 @@
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     return 0;
   }
-  CRYPTO_BUFFER_free(*out);
-  *out = CRYPTO_BUFFER_new_from_CBS(&value, pool);
+  out->reset(CRYPTO_BUFFER_new_from_CBS(&value, pool));
   if (*out == nullptr) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return 0;
@@ -617,10 +610,9 @@
 
   if (!SSL_SESSION_parse_string(&session, &ret->psk_identity,
                                 kPSKIdentityTag) ||
-      !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint,
+      !SSL_SESSION_parse_u32(&session, &ret->ticket_lifetime_hint,
                              kTicketLifetimeHintTag, 0) ||
-      !SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick,
-                                      &ret->tlsext_ticklen, kTicketTag)) {
+      !SSL_SESSION_parse_octet_string(&session, &ret->ticket, kTicketTag)) {
     return nullptr;
   }
 
@@ -680,8 +672,8 @@
     return nullptr;
   }
   if (has_peer || has_cert_chain) {
-    ret->certs = sk_CRYPTO_BUFFER_new_null();
-    if (ret->certs == NULL) {
+    ret->certs.reset(sk_CRYPTO_BUFFER_new_null());
+    if (ret->certs == nullptr) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return nullptr;
     }
@@ -689,7 +681,7 @@
     if (has_peer) {
       UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new_from_CBS(&peer, pool));
       if (!buffer ||
-          !PushToStack(ret->certs, std::move(buffer))) {
+          !PushToStack(ret->certs.get(), std::move(buffer))) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
         return nullptr;
       }
@@ -705,7 +697,7 @@
 
       UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new_from_CBS(&cert, pool));
       if (buffer == nullptr ||
-          !PushToStack(ret->certs, std::move(buffer))) {
+          !PushToStack(ret->certs.get(), std::move(buffer))) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
         return nullptr;
       }
@@ -746,7 +738,7 @@
       !SSL_SESSION_parse_u32(&session, &ret->auth_timeout, kAuthTimeoutTag,
                              ret->timeout) ||
       !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
-                                      &ret->early_alpn_len, kEarlyALPNTag) ||
+                                      kEarlyALPNTag) ||
       CBS_len(&session) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     return nullptr;