A bunch more scopers.

Change-Id: I5c8dbfec4a404d8d1501725a90b383eb3e05c664
Reviewed-on: https://boringssl-review.googlesource.com/29591
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_srtp.cc b/ssl/d1_srtp.cc
index 69b693c..96d7d51 100644
--- a/ssl/d1_srtp.cc
+++ b/ssl/d1_srtp.cc
@@ -158,8 +158,9 @@
   return 0;
 }
 
-static int ssl_ctx_make_profiles(const char *profiles_string,
-                                 STACK_OF(SRTP_PROTECTION_PROFILE) **out) {
+static int ssl_ctx_make_profiles(
+    const char *profiles_string,
+    UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> *out) {
   UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> profiles(
       sk_SRTP_PROTECTION_PROFILE_new_null());
   if (profiles == nullptr) {
@@ -188,8 +189,7 @@
     }
   } while (col);
 
-  sk_SRTP_PROTECTION_PROFILE_free(*out);
-  *out = profiles.release();
+  *out = std::move(profiles);
   return 1;
 }
 
@@ -212,8 +212,9 @@
     return nullptr;
   }
 
-  return ssl->config->srtp_profiles != nullptr ? ssl->config->srtp_profiles
-                                               : ssl->ctx->srtp_profiles;
+  return ssl->config->srtp_profiles != nullptr
+             ? ssl->config->srtp_profiles.get()
+             : ssl->ctx->srtp_profiles.get();
 }
 
 const SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *ssl) {
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
index a0674d1..4b6749f 100644
--- a/ssl/handshake_server.cc
+++ b/ssl/handshake_server.cc
@@ -535,8 +535,9 @@
 
   // Negotiate the cipher suite. This must be done after |cert_cb| so the
   // certificate is finalized.
-  SSLCipherPreferenceList *prefs =
-      hs->config->cipher_list ? hs->config->cipher_list : ssl->ctx->cipher_list;
+  SSLCipherPreferenceList *prefs = hs->config->cipher_list
+                                       ? hs->config->cipher_list.get()
+                                       : ssl->ctx->cipher_list.get();
   hs->new_cipher = ssl3_choose_cipher(hs, &client_hello, prefs);
   if (hs->new_cipher == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
@@ -788,11 +789,12 @@
 
     // PSK ciphers begin with an identity hint.
     if (alg_a & SSL_aPSK) {
-      size_t len = (hs->config->psk_identity_hint == NULL)
+      size_t len = hs->config->psk_identity_hint == nullptr
                        ? 0
-                       : strlen(hs->config->psk_identity_hint);
+                       : strlen(hs->config->psk_identity_hint.get());
       if (!CBB_add_u16_length_prefixed(cbb.get(), &child) ||
-          !CBB_add_bytes(&child, (const uint8_t *)hs->config->psk_identity_hint,
+          !CBB_add_bytes(&child,
+                         (const uint8_t *)hs->config->psk_identity_hint.get(),
                          len)) {
         return ssl_hs_error;
       }
diff --git a/ssl/internal.h b/ssl/internal.h
index 279b332..d71ea57 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -524,7 +524,7 @@
 // true on success and false on failure. If |strict| is true, nonsense will be
 // rejected. If false, nonsense will be silently ignored. An empty result is
 // considered an error regardless of |strict|.
-bool ssl_create_cipher_list(SSLCipherPreferenceList **out_cipher_list,
+bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
                             const char *rule_str, bool strict);
 
 // ssl_cipher_get_value returns the cipher suite id of |cipher|.
@@ -2417,11 +2417,11 @@
   X509_VERIFY_PARAM *param = nullptr;
 
   // crypto
-  SSLCipherPreferenceList *cipher_list = nullptr;
+  UniquePtr<SSLCipherPreferenceList> cipher_list;
 
   // This is used to hold the local certificate used (i.e. the server
   // certificate for a server or the client certificate for a client).
-  CERT *cert = nullptr;
+  UniquePtr<CERT> cert;
 
   int (*verify_callback)(int ok,
                          X509_STORE_CTX *ctx) =
@@ -2431,47 +2431,40 @@
       SSL *ssl, uint8_t *out_alert) = nullptr;
   // Server-only: psk_identity_hint is the identity hint to send in
   // PSK-based key exchanges.
-  char *psk_identity_hint = nullptr;
+  UniquePtr<char> psk_identity_hint;
 
-  unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
-                                      char *identity,
-                                      unsigned int max_identity_len,
-                                      uint8_t *psk,
-                                      unsigned int max_psk_len) = nullptr;
-  unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
-                                      uint8_t *psk,
-                                      unsigned int max_psk_len) = nullptr;
+  unsigned (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+                                  unsigned max_identity_len, uint8_t *psk,
+                                  unsigned max_psk_len) = nullptr;
+  unsigned (*psk_server_callback)(SSL *ssl, const char *identity, uint8_t *psk,
+                                  unsigned max_psk_len) = nullptr;
 
   // for server side, keep the list of CA_dn we can use
-  STACK_OF(CRYPTO_BUFFER) *client_CA = nullptr;
+  UniquePtr<STACK_OF(CRYPTO_BUFFER)> client_CA;
 
   // cached_x509_client_CA is a cache of parsed versions of the elements of
   // |client_CA|.
   STACK_OF(X509_NAME) *cached_x509_client_CA = nullptr;
 
   uint16_t dummy_pq_padding_len = 0;
-  size_t supported_group_list_len = 0;
-  uint16_t *supported_group_list = nullptr;  // our list
+  Array<uint16_t> supported_group_list;  // our list
 
   // The client's Channel ID private key.
-  EVP_PKEY *tlsext_channel_id_private = nullptr;
+  UniquePtr<EVP_PKEY> tlsext_channel_id_private;
 
   // For a client, this contains the list of supported protocols in wire
   // format.
-  uint8_t *alpn_client_proto_list = nullptr;
-  unsigned alpn_client_proto_list_len = 0;
+  Array<uint8_t> alpn_client_proto_list;
 
   // Contains a list of supported Token Binding key parameters.
-  uint8_t *token_binding_params = nullptr;
-  size_t token_binding_params_len = 0;
+  Array<uint8_t> token_binding_params;
 
   // Contains the QUIC transport params that this endpoint will send.
-  uint8_t *quic_transport_params = nullptr;
-  size_t quic_transport_params_len = 0;
+  Array<uint8_t> quic_transport_params;
 
   // srtp_profiles is the list of configured SRTP protection profiles for
   // DTLS-SRTP.
-  STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles = nullptr;
+  UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> srtp_profiles;
 
   // verify_mode is a bitmask of |SSL_VERIFY_*| values.
   uint8_t verify_mode = SSL_VERIFY_NONE;
@@ -2712,19 +2705,16 @@
 // found, it returns zero.
 int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id);
 
-// tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves|
-// into a newly allocated array of TLS group IDs. On success, the function
-// returns one and writes the array to |*out_group_ids| and its size to
-// |*out_group_ids_len|. Otherwise, it returns zero.
-int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
-                    const int *curves, size_t ncurves);
+// tls1_set_curves converts the array of NIDs in |curves| into a newly allocated
+// array of TLS group IDs. On success, the function returns true and writes the
+// array to |*out_group_ids|. Otherwise, it returns false.
+bool tls1_set_curves(Array<uint16_t> *out_group_ids, Span<const int> curves);
 
 // tls1_set_curves_list converts the string of curves pointed to by |curves|
 // into a newly allocated array of TLS group IDs. On success, the function
-// returns one and writes the array to |*out_group_ids| and its size to
-// |*out_group_ids_len|. Otherwise, it returns zero.
-int tls1_set_curves_list(uint16_t **out_group_ids, size_t *out_group_ids_len,
-                         const char *curves);
+// returns true and writes the array to |*out_group_ids|. Otherwise, it returns
+// false.
+bool tls1_set_curves_list(Array<uint16_t> *out_group_ids, const char *curves);
 
 // ssl_add_clienthello_tlsext writes ClientHello extensions to |out|. It
 // returns one on success and zero on failure. The |header_len| argument is the
@@ -2840,7 +2830,7 @@
   // configuration.
   tls13_variant_t tls13_variant = tls13_default;
 
-  bssl::SSLCipherPreferenceList *cipher_list = nullptr;
+  bssl::UniquePtr<bssl::SSLCipherPreferenceList> cipher_list;
 
   X509_STORE *cert_store = nullptr;
   LHASH_OF(SSL_SESSION) *sessions = nullptr;
@@ -2914,7 +2904,7 @@
   void (*info_callback)(const SSL *ssl, int type, int value) = nullptr;
 
   // what we put in client cert requests
-  STACK_OF(CRYPTO_BUFFER) *client_CA = nullptr;
+  bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> client_CA;
 
   // cached_x509_client_CA is a cache of parsed versions of the elements of
   // |client_CA|.
@@ -2930,7 +2920,7 @@
   uint32_t mode = SSL_MODE_NO_AUTO_CHAIN;
   uint32_t max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
 
-  bssl::CERT *cert = nullptr;
+  bssl::UniquePtr<bssl::CERT> cert;
 
   // callback that allows applications to peek at protocol messages
   void (*msg_callback)(int write_p, int version, int content_type,
@@ -2976,7 +2966,7 @@
 
   // Server-only: psk_identity_hint is the default identity hint to send in
   // PSK-based key exchanges.
-  char *psk_identity_hint = nullptr;
+  bssl::UniquePtr<char> psk_identity_hint;
 
   unsigned (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
                                   unsigned max_identity_len, uint8_t *psk,
@@ -3018,21 +3008,19 @@
 
   // For a client, this contains the list of supported protocols in wire
   // format.
-  uint8_t *alpn_client_proto_list = nullptr;
-  unsigned alpn_client_proto_list_len = 0;
+  bssl::Array<uint8_t> alpn_client_proto_list;
 
   // SRTP profiles we are willing to do from RFC 5764
-  STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles = nullptr;
+  bssl::UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> srtp_profiles;
 
   // Defined compression algorithms for certificates.
   STACK_OF(CertCompressionAlg) *cert_compression_algs = nullptr;
 
   // Supported group values inherited by SSL structure
-  size_t supported_group_list_len = 0;
-  uint16_t *supported_group_list = nullptr;
+  bssl::Array<uint16_t> supported_group_list;
 
   // The client's Channel ID private key.
-  EVP_PKEY *tlsext_channel_id_private = nullptr;
+  bssl::UniquePtr<EVP_PKEY> tlsext_channel_id_private;
 
   // keylog_callback, if not NULL, is the key logging callback. See
   // |SSL_CTX_set_keylog_callback|.
@@ -3058,8 +3046,7 @@
 
   // verify_sigalgs, if not empty, is the set of signature algorithms
   // accepted from the peer in decreasing order of preference.
-  uint16_t *verify_sigalgs = nullptr;
-  size_t num_verify_sigalgs = 0;
+  bssl::Array<uint16_t> verify_sigalgs;
 
   // 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
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index 421b30a..4842974 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -656,11 +656,11 @@
 }
 
 bool ssl_has_client_CAs(const SSL_CONFIG *cfg) {
-  STACK_OF(CRYPTO_BUFFER) *names = cfg->client_CA;
-  if (names == NULL) {
-    names = cfg->ssl->ctx->client_CA;
+  const STACK_OF(CRYPTO_BUFFER) *names = cfg->client_CA.get();
+  if (names == nullptr) {
+    names = cfg->ssl->ctx->client_CA.get();
   }
-  if (names == NULL) {
+  if (names == nullptr) {
     return false;
   }
   return sk_CRYPTO_BUFFER_num(names) > 0;
@@ -672,9 +672,9 @@
     return 0;
   }
 
-  STACK_OF(CRYPTO_BUFFER) *names = hs->config->client_CA;
+  const STACK_OF(CRYPTO_BUFFER) *names = hs->config->client_CA.get();
   if (names == NULL) {
-    names = hs->ssl->ctx->client_CA;
+    names = hs->ssl->ctx->client_CA.get();
   }
   if (names == NULL) {
     return CBB_flush(cbb);
@@ -760,14 +760,14 @@
   if (!ssl->config) {
     return 0;
   }
-  return cert_set_chain_and_key(ssl->config->cert, certs, num_certs, privkey,
-                                privkey_method);
+  return cert_set_chain_and_key(ssl->config->cert.get(), certs, num_certs,
+                                privkey, privkey_method);
 }
 
 int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
                               size_t num_certs, EVP_PKEY *privkey,
                               const SSL_PRIVATE_KEY_METHOD *privkey_method) {
-  return cert_set_chain_and_key(ctx->cert, certs, num_certs, privkey,
+  return cert_set_chain_and_key(ctx->cert.get(), certs, num_certs, privkey,
                                 privkey_method);
 }
 
@@ -778,7 +778,7 @@
     return 0;
   }
 
-  return ssl_set_cert(ctx->cert, std::move(buffer));
+  return ssl_set_cert(ctx->cert.get(), std::move(buffer));
 }
 
 int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
@@ -787,19 +787,19 @@
     return 0;
   }
 
-  return ssl_set_cert(ssl->config->cert, std::move(buffer));
+  return ssl_set_cert(ssl->config->cert.get(), std::move(buffer));
 }
 
 void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
                          void *arg) {
-  ssl_cert_set_cert_cb(ctx->cert, cb, arg);
+  ssl_cert_set_cert_cb(ctx->cert.get(), cb, arg);
 }
 
 void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
   if (!ssl->config) {
     return;
   }
-  ssl_cert_set_cert_cb(ssl->config->cert, cb, arg);
+  ssl_cert_set_cert_cb(ssl->config->cert.get(), cb, arg);
 }
 
 const STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
@@ -834,7 +834,7 @@
 
 int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list,
                                            size_t list_len) {
-  return set_signed_cert_timestamp_list(ctx->cert, list, list_len);
+  return set_signed_cert_timestamp_list(ctx->cert.get(), list, list_len);
 }
 
 int SSL_set_signed_cert_timestamp_list(SSL *ssl, const uint8_t *list,
@@ -842,7 +842,8 @@
   if (!ssl->config) {
     return 0;
   }
-  return set_signed_cert_timestamp_list(ssl->config->cert, list, list_len);
+  return set_signed_cert_timestamp_list(ssl->config->cert.get(), list,
+                                        list_len);
 }
 
 int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
@@ -864,8 +865,7 @@
 
 void SSL_CTX_set0_client_CAs(SSL_CTX *ctx, STACK_OF(CRYPTO_BUFFER) *name_list) {
   ctx->x509_method->ssl_ctx_flush_cached_client_CA(ctx);
-  sk_CRYPTO_BUFFER_pop_free(ctx->client_CA, CRYPTO_BUFFER_free);
-  ctx->client_CA = name_list;
+  ctx->client_CA.reset(name_list);
 }
 
 void SSL_set0_client_CAs(SSL *ssl, STACK_OF(CRYPTO_BUFFER) *name_list) {
@@ -873,6 +873,5 @@
     return;
   }
   ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl->config.get());
-  sk_CRYPTO_BUFFER_pop_free(ssl->config->client_CA, CRYPTO_BUFFER_free);
-  ssl->config->client_CA = name_list;
+  ssl->config->client_CA.reset(name_list);
 }
diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc
index 42be591..02380c1 100644
--- a/ssl/ssl_cipher.cc
+++ b/ssl/ssl_cipher.cc
@@ -1137,7 +1137,7 @@
   return true;
 }
 
-bool ssl_create_cipher_list(SSLCipherPreferenceList **out_cipher_list,
+bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
                             const char *rule_str, bool strict) {
   // Return with error if nothing to do.
   if (rule_str == NULL || out_cipher_list == NULL) {
@@ -1255,10 +1255,7 @@
     return false;
   }
 
-  if (*out_cipher_list) {
-    Delete(*out_cipher_list);
-  }
-  *out_cipher_list = pref_list.release();
+  *out_cipher_list = std::move(pref_list);
 
   // Configuring an empty cipher list is an error but still updates the
   // output.
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 13e6267..39c5d92 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -562,22 +562,13 @@
 
   CRYPTO_MUTEX_cleanup(&lock);
   lh_SSL_SESSION_free(sessions);
-  Delete(cipher_list);
-  Delete(cert);
   sk_SSL_CUSTOM_EXTENSION_pop_free(client_custom_extensions,
                                    SSL_CUSTOM_EXTENSION_free);
   sk_SSL_CUSTOM_EXTENSION_pop_free(server_custom_extensions,
                                    SSL_CUSTOM_EXTENSION_free);
-  sk_CRYPTO_BUFFER_pop_free(client_CA, CRYPTO_BUFFER_free);
   x509_method->ssl_ctx_free(this);
-  sk_SRTP_PROTECTION_PROFILE_free(srtp_profiles);
   sk_CertCompressionAlg_pop_free(cert_compression_algs,
                                  Delete<CertCompressionAlg>);
-  OPENSSL_free(psk_identity_hint);
-  OPENSSL_free(supported_group_list);
-  OPENSSL_free(alpn_client_proto_list);
-  EVP_PKEY_free(tlsext_channel_id_private);
-  OPENSSL_free(verify_sigalgs);
   OPENSSL_free(tlsext_ticket_key_current);
   OPENSSL_free(tlsext_ticket_key_prev);
 }
@@ -593,9 +584,9 @@
     return nullptr;
   }
 
-  ret->cert = New<CERT>(method->x509_method);
+  ret->cert = MakeUnique<CERT>(method->x509_method);
   ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp);
-  ret->client_CA = sk_CRYPTO_BUFFER_new_null();
+  ret->client_CA.reset(sk_CRYPTO_BUFFER_new_null());
   if (ret->cert == nullptr ||
       ret->sessions == nullptr ||
       ret->client_CA == nullptr ||
@@ -675,8 +666,8 @@
   ssl->config->conf_min_version = ctx->conf_min_version;
   ssl->config->conf_max_version = ctx->conf_max_version;
 
-  ssl->config->cert = ssl_cert_dup(ctx->cert).release();
-  if (ssl->config->cert == NULL) {
+  ssl->config->cert = ssl_cert_dup(ctx->cert.get());
+  if (ssl->config->cert == nullptr) {
     return nullptr;
   }
 
@@ -686,27 +677,16 @@
   ssl->config->retain_only_sha256_of_client_certs =
       ctx->retain_only_sha256_of_client_certs;
 
-  if (ctx->supported_group_list) {
-    ssl->config->supported_group_list = (uint16_t *)BUF_memdup(
-        ctx->supported_group_list, ctx->supported_group_list_len * 2);
-    if (!ssl->config->supported_group_list) {
-      return nullptr;
-    }
-    ssl->config->supported_group_list_len = ctx->supported_group_list_len;
-  }
-
-  if (ctx->alpn_client_proto_list) {
-    ssl->config->alpn_client_proto_list = (uint8_t *)BUF_memdup(
-        ctx->alpn_client_proto_list, ctx->alpn_client_proto_list_len);
-    if (ssl->config->alpn_client_proto_list == NULL) {
-      return nullptr;
-    }
-    ssl->config->alpn_client_proto_list_len = ctx->alpn_client_proto_list_len;
+  if (!ssl->config->supported_group_list.CopyFrom(ctx->supported_group_list) ||
+      !ssl->config->alpn_client_proto_list.CopyFrom(
+          ctx->alpn_client_proto_list)) {
+    return nullptr;
   }
 
   if (ctx->psk_identity_hint) {
-    ssl->config->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint);
-    if (ssl->config->psk_identity_hint == NULL) {
+    ssl->config->psk_identity_hint.reset(
+        BUF_strdup(ctx->psk_identity_hint.get()));
+    if (ssl->config->psk_identity_hint == nullptr) {
       return nullptr;
     }
   }
@@ -714,10 +694,8 @@
   ssl->config->psk_server_callback = ctx->psk_server_callback;
 
   ssl->config->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled;
-  if (ctx->tlsext_channel_id_private) {
-    EVP_PKEY_up_ref(ctx->tlsext_channel_id_private);
-    ssl->config->tlsext_channel_id_private = ctx->tlsext_channel_id_private;
-  }
+  ssl->config->tlsext_channel_id_private =
+      UpRef(ctx->tlsext_channel_id_private);
 
   ssl->config->signed_cert_timestamps_enabled =
       ctx->signed_cert_timestamps_enabled;
@@ -747,16 +725,6 @@
   if (ssl->ctx != nullptr) {
     ssl->ctx->x509_method->ssl_config_free(this);
   }
-  Delete(cipher_list);
-  Delete(cert);
-  OPENSSL_free(psk_identity_hint);
-  OPENSSL_free(supported_group_list);
-  EVP_PKEY_free(tlsext_channel_id_private);
-  OPENSSL_free(alpn_client_proto_list);
-  OPENSSL_free(token_binding_params);
-  OPENSSL_free(quic_transport_params);
-  sk_SRTP_PROTECTION_PROFILE_free(srtp_profiles);
-  sk_CRYPTO_BUFFER_pop_free(client_CA, CRYPTO_BUFFER_free);
 }
 
 void SSL_free(SSL *ssl) {
@@ -1126,16 +1094,8 @@
 
 int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
                                   size_t params_len) {
-  if (!ssl->config) {
-    return 0;
-  }
-  ssl->config->quic_transport_params =
-      (uint8_t *)BUF_memdup(params, params_len);
-  if (!ssl->config->quic_transport_params) {
-    return 0;
-  }
-  ssl->config->quic_transport_params_len = params_len;
-  return 1;
+  return ssl->config && ssl->config->quic_transport_params.CopyFrom(
+                            MakeConstSpan(params, params_len));
 }
 
 void SSL_get_peer_quic_transport_params(const SSL *ssl,
@@ -1399,7 +1359,7 @@
 
 int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
                                    size_t sid_ctx_len) {
-  return set_session_id_context(ctx->cert, sid_ctx, sid_ctx_len);
+  return set_session_id_context(ctx->cert.get(), sid_ctx, sid_ctx_len);
 }
 
 int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
@@ -1407,7 +1367,7 @@
   if (!ssl->config) {
     return 0;
   }
-  return set_session_id_context(ssl->config->cert, sid_ctx, sid_ctx_len);
+  return set_session_id_context(ssl->config->cert.get(), sid_ctx, sid_ctx_len);
 }
 
 const uint8_t *SSL_get0_session_id_context(const SSL *ssl, size_t *out_len) {
@@ -1424,7 +1384,7 @@
   if (!ssl->config) {
     return;
   }
-  ssl_cert_clear_certs(ssl->config->cert);
+  ssl_cert_clear_certs(ssl->config->cert.get());
 }
 
 int SSL_get_fd(const SSL *ssl) { return SSL_get_rfd(ssl); }
@@ -1579,17 +1539,16 @@
   return static_cast<int>(ssl->s3->pending_app_data.size());
 }
 
-// Fix this so it checks all the valid key/cert options
 int SSL_CTX_check_private_key(const SSL_CTX *ctx) {
-  return ssl_cert_check_private_key(ctx->cert, ctx->cert->privatekey.get());
+  return ssl_cert_check_private_key(ctx->cert.get(),
+                                    ctx->cert->privatekey.get());
 }
 
-// Fix this function so that it takes an optional type parameter
 int SSL_check_private_key(const SSL *ssl) {
   if (!ssl->config) {
     return 0;
   }
-  return ssl_cert_check_private_key(ssl->config->cert,
+  return ssl_cert_check_private_key(ssl->config->cert.get(),
                                     ssl->config->cert->privatekey.get());
 }
 
@@ -1759,8 +1718,7 @@
 
 int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) {
   return tls1_set_curves(&ctx->supported_group_list,
-                         &ctx->supported_group_list_len, curves,
-                         curves_len);
+                         MakeConstSpan(curves, curves_len));
 }
 
 int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
@@ -1768,21 +1726,18 @@
     return 0;
   }
   return tls1_set_curves(&ssl->config->supported_group_list,
-                         &ssl->config->supported_group_list_len, curves,
-                         curves_len);
+                         MakeConstSpan(curves, curves_len));
 }
 
 int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves) {
-  return tls1_set_curves_list(&ctx->supported_group_list,
-                              &ctx->supported_group_list_len, curves);
+  return tls1_set_curves_list(&ctx->supported_group_list, curves);
 }
 
 int SSL_set1_curves_list(SSL *ssl, const char *curves) {
   if (!ssl->config) {
     return 0;
   }
-  return tls1_set_curves_list(&ssl->config->supported_group_list,
-                              &ssl->config->supported_group_list_len, curves);
+  return tls1_set_curves_list(&ssl->config->supported_group_list, curves);
 }
 
 uint16_t SSL_get_curve_id(const SSL *ssl) {
@@ -2043,29 +1998,21 @@
 
 int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos,
                             unsigned protos_len) {
-  OPENSSL_free(ctx->alpn_client_proto_list);
-  ctx->alpn_client_proto_list = (uint8_t *)BUF_memdup(protos, protos_len);
-  if (!ctx->alpn_client_proto_list) {
-    return 1;
-  }
-  ctx->alpn_client_proto_list_len = protos_len;
-
-  return 0;
+  // Note this function's calling convention is backwards.
+  return ctx->alpn_client_proto_list.CopyFrom(MakeConstSpan(protos, protos_len))
+             ? 0
+             : 1;
 }
 
 int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) {
+  // Note this function's calling convention is backwards.
   if (!ssl->config) {
-    return 0;
-  }
-  OPENSSL_free(ssl->config->alpn_client_proto_list);
-  ssl->config->alpn_client_proto_list =
-      (uint8_t *)BUF_memdup(protos, protos_len);
-  if (!ssl->config->alpn_client_proto_list) {
     return 1;
   }
-  ssl->config->alpn_client_proto_list_len = protos_len;
-
-  return 0;
+  return ssl->config->alpn_client_proto_list.CopyFrom(
+             MakeConstSpan(protos, protos_len))
+             ? 0
+             : 1;
 }
 
 void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
@@ -2171,9 +2118,7 @@
     return 0;
   }
 
-  EVP_PKEY_free(ctx->tlsext_channel_id_private);
-  EVP_PKEY_up_ref(private_key);
-  ctx->tlsext_channel_id_private = private_key;
+  ctx->tlsext_channel_id_private = UpRef(private_key);
   ctx->tlsext_channel_id_enabled = true;
 
   return 1;
@@ -2188,9 +2133,7 @@
     return 0;
   }
 
-  EVP_PKEY_free(ssl->config->tlsext_channel_id_private);
-  EVP_PKEY_up_ref(private_key);
-  ssl->config->tlsext_channel_id_private = private_key;
+  ssl->config->tlsext_channel_id_private = UpRef(private_key);
   ssl->config->tlsext_channel_id_enabled = true;
 
   return 1;
@@ -2213,13 +2156,7 @@
     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
     return 0;
   }
-  OPENSSL_free(ssl->config->token_binding_params);
-  ssl->config->token_binding_params = (uint8_t *)BUF_memdup(params, len);
-  if (!ssl->config->token_binding_params) {
-    return 0;
-  }
-  ssl->config->token_binding_params_len = len;
-  return 1;
+  return ssl->config->token_binding_params.CopyFrom(MakeConstSpan(params, len));
 }
 
 int SSL_is_token_binding_negotiated(const SSL *ssl) {
@@ -2337,9 +2274,12 @@
     ctx = ssl->session_ctx.get();
   }
 
-  Delete(ssl->config->cert);
-  ssl->config->cert = ssl_cert_dup(ctx->cert).release();
+  UniquePtr<CERT> new_cert = ssl_cert_dup(ctx->cert.get());
+  if (!new_cert) {
+    return nullptr;
+  }
 
+  ssl->config->cert = std::move(new_cert);
   ssl->ctx = UpRef(ctx);
   ssl->enable_early_data = ssl->ctx->enable_early_data;
 
@@ -2423,23 +2363,23 @@
 void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*cb)(SSL *ssl, int is_export,
                                                  int keylength)) {}
 
-static int use_psk_identity_hint(char **out, const char *identity_hint) {
+static int use_psk_identity_hint(UniquePtr<char> *out,
+                                 const char *identity_hint) {
   if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
     return 0;
   }
 
   // Clear currently configured hint, if any.
-  OPENSSL_free(*out);
-  *out = NULL;
+  out->reset();
 
   // Treat the empty hint as not supplying one. Plain PSK makes it possible to
   // send either no hint (omit ServerKeyExchange) or an empty hint, while
   // ECDHE_PSK can only spell empty hint. Having different capabilities is odd,
   // so we interpret empty and missing as identical.
   if (identity_hint != NULL && identity_hint[0] != '\0') {
-    *out = BUF_strdup(identity_hint);
-    if (*out == NULL) {
+    out->reset(BUF_strdup(identity_hint));
+    if (*out == nullptr) {
       return 0;
     }
   }
@@ -2466,7 +2406,7 @@
     assert(ssl->config);
     return NULL;
   }
-  return ssl->config->psk_identity_hint;
+  return ssl->config->psk_identity_hint.get();
 }
 
 const char *SSL_get_psk_identity(const SSL *ssl) {
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index d41ea5d..f5c387b 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -304,7 +304,7 @@
     return 0;
   }
 
-  return ssl_set_pkey(ssl->config->cert, pkey.get());
+  return ssl_set_pkey(ssl->config->cert.get(), pkey.get());
 }
 
 int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
@@ -323,7 +323,7 @@
     return 0;
   }
 
-  return ssl_set_pkey(ssl->config->cert, pkey);
+  return ssl_set_pkey(ssl->config->cert.get(), pkey);
 }
 
 int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
@@ -356,7 +356,7 @@
     return 0;
   }
 
-  return ssl_set_pkey(ctx->cert, pkey.get());
+  return ssl_set_pkey(ctx->cert.get(), pkey.get());
 }
 
 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
@@ -376,7 +376,7 @@
     return 0;
   }
 
-  return ssl_set_pkey(ctx->cert, pkey);
+  return ssl_set_pkey(ctx->cert.get(), pkey);
 }
 
 int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
@@ -461,21 +461,6 @@
   return alg != nullptr && alg->is_rsa_pss;
 }
 
-static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs,
-                               const uint16_t *prefs, size_t num_prefs) {
-  OPENSSL_free(*out_prefs);
-
-  *out_num_prefs = 0;
-  *out_prefs = (uint16_t *)BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
-  if (*out_prefs == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-  *out_num_prefs = num_prefs;
-
-  return 1;
-}
-
 int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
                                         size_t num_prefs) {
   return ctx->cert->sigalgs.CopyFrom(MakeConstSpan(prefs, num_prefs));
@@ -491,6 +476,5 @@
 
 int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
                                        size_t num_prefs) {
-  return set_algorithm_prefs(&ctx->verify_sigalgs, &ctx->num_verify_sigalgs,
-                             prefs, num_prefs);
+  return ctx->verify_sigalgs.CopyFrom(MakeConstSpan(prefs, num_prefs));
 }
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 6b4732c..3bf93d9 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -493,7 +493,7 @@
     ASSERT_TRUE(ctx);
 
     ASSERT_TRUE(SSL_CTX_set1_curves_list(ctx.get(), t.rule));
-    ASSERT_EQ(t.expected.size(), ctx->supported_group_list_len);
+    ASSERT_EQ(t.expected.size(), ctx->supported_group_list.size());
     for (size_t i = 0; i < t.expected.size(); i++) {
       EXPECT_EQ(t.expected[i], ctx->supported_group_list[i]);
     }
diff --git a/ssl/ssl_x509.cc b/ssl/ssl_x509.cc
index aabf2a0..8f4e53b 100644
--- a/ssl/ssl_x509.cc
+++ b/ssl/ssl_x509.cc
@@ -460,11 +460,11 @@
   // Remove the leaf from the generated chain.
   X509_free(sk_X509_shift(ctx->chain));
 
-  if (!ssl_cert_set_chain(hs->config->cert, ctx->chain)) {
+  if (!ssl_cert_set_chain(hs->config->cert.get(), ctx->chain)) {
     return 0;
   }
 
-  ssl_crypto_x509_cert_flush_cached_chain(hs->config->cert);
+  ssl_crypto_x509_cert_flush_cached_chain(hs->config->cert.get());
 
   return 1;
 }
@@ -755,12 +755,12 @@
   if (!ssl->config) {
     return 0;
   }
-  return ssl_use_certificate(ssl->config->cert, x);
+  return ssl_use_certificate(ssl->config->cert.get(), x);
 }
 
 int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
   check_ssl_ctx_x509_method(ctx);
-  return ssl_use_certificate(ctx->cert, x);
+  return ssl_use_certificate(ctx->cert.get(), x);
 }
 
 // ssl_cert_cache_leaf_cert sets |cert->x509_leaf|, if currently NULL, from the
@@ -797,13 +797,13 @@
     assert(ssl->config);
     return 0;
   }
-  return ssl_cert_get0_leaf(ssl->config->cert);
+  return ssl_cert_get0_leaf(ssl->config->cert.get());
 }
 
 X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
   check_ssl_ctx_x509_method(ctx);
   MutexWriteLock lock(const_cast<CRYPTO_MUTEX*>(&ctx->lock));
-  return ssl_cert_get0_leaf(ctx->cert);
+  return ssl_cert_get0_leaf(ctx->cert.get());
 }
 
 static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
@@ -869,12 +869,12 @@
 
 int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
   check_ssl_ctx_x509_method(ctx);
-  return ssl_cert_set0_chain(ctx->cert, chain);
+  return ssl_cert_set0_chain(ctx->cert.get(), chain);
 }
 
 int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
   check_ssl_ctx_x509_method(ctx);
-  return ssl_cert_set1_chain(ctx->cert, chain);
+  return ssl_cert_set1_chain(ctx->cert.get(), chain);
 }
 
 int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
@@ -882,7 +882,7 @@
   if (!ssl->config) {
     return 0;
   }
-  return ssl_cert_set0_chain(ssl->config->cert, chain);
+  return ssl_cert_set0_chain(ssl->config->cert.get(), chain);
 }
 
 int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
@@ -890,17 +890,17 @@
   if (!ssl->config) {
     return 0;
   }
-  return ssl_cert_set1_chain(ssl->config->cert, chain);
+  return ssl_cert_set1_chain(ssl->config->cert.get(), chain);
 }
 
 int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
   check_ssl_ctx_x509_method(ctx);
-  return ssl_cert_add0_chain_cert(ctx->cert, x509);
+  return ssl_cert_add0_chain_cert(ctx->cert.get(), x509);
 }
 
 int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
   check_ssl_ctx_x509_method(ctx);
-  return ssl_cert_add1_chain_cert(ctx->cert, x509);
+  return ssl_cert_add1_chain_cert(ctx->cert.get(), x509);
 }
 
 int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
@@ -913,7 +913,7 @@
   if (!ssl->config) {
     return 0;
   }
-  return ssl_cert_add0_chain_cert(ssl->config->cert, x509);
+  return ssl_cert_add0_chain_cert(ssl->config->cert.get(), x509);
 }
 
 int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
@@ -921,7 +921,7 @@
   if (!ssl->config) {
     return 0;
   }
-  return ssl_cert_add1_chain_cert(ssl->config->cert, x509);
+  return ssl_cert_add1_chain_cert(ssl->config->cert.get(), x509);
 }
 
 int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
@@ -971,7 +971,7 @@
 int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
   check_ssl_ctx_x509_method(ctx);
   MutexWriteLock lock(const_cast<CRYPTO_MUTEX*>(&ctx->lock));
-  if (!ssl_cert_cache_chain_certs(ctx->cert)) {
+  if (!ssl_cert_cache_chain_certs(ctx->cert.get())) {
     *out_chain = NULL;
     return 0;
   }
@@ -991,7 +991,7 @@
     assert(ssl->config);
     return 0;
   }
-  if (!ssl_cert_cache_chain_certs(ssl->config->cert)) {
+  if (!ssl_cert_cache_chain_certs(ssl->config->cert.get())) {
     *out_chain = NULL;
     return 0;
   }
@@ -1042,7 +1042,7 @@
   return sk_X509_NAME_deep_copy(list, X509_NAME_dup, X509_NAME_free);
 }
 
-static void set_client_CA_list(STACK_OF(CRYPTO_BUFFER) **ca_list,
+static void set_client_CA_list(UniquePtr<STACK_OF(CRYPTO_BUFFER)> *ca_list,
                                const STACK_OF(X509_NAME) *name_list,
                                CRYPTO_BUFFER_POOL *pool) {
   UniquePtr<STACK_OF(CRYPTO_BUFFER)> buffers(sk_CRYPTO_BUFFER_new_null());
@@ -1065,8 +1065,7 @@
     }
   }
 
-  sk_CRYPTO_BUFFER_pop_free(*ca_list, CRYPTO_BUFFER_free);
-  *ca_list = buffers.release();
+  *ca_list = std::move(buffers);
 }
 
 void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list) {
@@ -1140,7 +1139,7 @@
 
   if (ssl->config->client_CA != NULL) {
     return buffer_names_to_x509(
-        ssl->config->client_CA,
+        ssl->config->client_CA.get(),
         (STACK_OF(X509_NAME) **)&ssl->config->cached_x509_client_CA);
   }
   return SSL_CTX_get_client_CA_list(ssl->ctx.get());
@@ -1152,11 +1151,11 @@
   // so it needs to lock around updating |cached_x509_client_CA|.
   MutexWriteLock lock(const_cast<CRYPTO_MUTEX *>(&ctx->lock));
   return buffer_names_to_x509(
-      ctx->client_CA,
+      ctx->client_CA.get(),
       const_cast<STACK_OF(X509_NAME) **>(&ctx->cached_x509_client_CA));
 }
 
-static int add_client_CA(STACK_OF(CRYPTO_BUFFER) **names, X509 *x509,
+static int add_client_CA(UniquePtr<STACK_OF(CRYPTO_BUFFER)> *names, X509 *x509,
                          CRYPTO_BUFFER_POOL *pool) {
   if (x509 == NULL) {
     return 0;
@@ -1175,8 +1174,8 @@
   }
 
   int alloced = 0;
-  if (*names == NULL) {
-    *names = sk_CRYPTO_BUFFER_new_null();
+  if (*names == nullptr) {
+    names->reset(sk_CRYPTO_BUFFER_new_null());
     alloced = 1;
 
     if (*names == NULL) {
@@ -1184,10 +1183,9 @@
     }
   }
 
-  if (!PushToStack(*names, std::move(buffer))) {
+  if (!PushToStack(names->get(), std::move(buffer))) {
     if (alloced) {
-      sk_CRYPTO_BUFFER_pop_free(*names, CRYPTO_BUFFER_free);
-      *names = NULL;
+      names->reset();
     }
     return 0;
   }
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index dfabbae..e0e7504 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -293,9 +293,8 @@
 };
 
 Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
-  if (hs->config->supported_group_list != nullptr) {
-    return MakeConstSpan(hs->config->supported_group_list,
-                         hs->config->supported_group_list_len);
+  if (!hs->config->supported_group_list.empty()) {
+    return hs->config->supported_group_list;
   }
   return Span<const uint16_t>(kDefaultGroups);
 }
@@ -335,68 +334,55 @@
   return 0;
 }
 
-int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
-                    const int *curves, size_t ncurves) {
-  uint16_t *group_ids = (uint16_t *)OPENSSL_malloc(ncurves * sizeof(uint16_t));
-  if (group_ids == NULL) {
-    return 0;
+bool tls1_set_curves(Array<uint16_t> *out_group_ids, Span<const int> curves) {
+  Array<uint16_t> group_ids;
+  if (!group_ids.Init(curves.size())) {
+    return false;
   }
 
-  for (size_t i = 0; i < ncurves; i++) {
+  for (size_t i = 0; i < curves.size(); i++) {
     if (!ssl_nid_to_group_id(&group_ids[i], curves[i])) {
-      OPENSSL_free(group_ids);
-      return 0;
+      return false;
     }
   }
 
-  OPENSSL_free(*out_group_ids);
-  *out_group_ids = group_ids;
-  *out_group_ids_len = ncurves;
-
-  return 1;
+  *out_group_ids = std::move(group_ids);
+  return true;
 }
 
-int tls1_set_curves_list(uint16_t **out_group_ids, size_t *out_group_ids_len,
-                         const char *curves) {
-  uint16_t *group_ids = NULL;
-  size_t ncurves = 0;
-
-  const char *col;
-  const char *ptr = curves;
-
+bool tls1_set_curves_list(Array<uint16_t> *out_group_ids, const char *curves) {
+  // Count the number of curves in the list.
+  size_t count = 0;
+  const char *ptr = curves, *col;
   do {
     col = strchr(ptr, ':');
-
-    uint16_t group_id;
-    if (!ssl_name_to_group_id(&group_id, ptr,
-                              col ? (size_t)(col - ptr) : strlen(ptr))) {
-      goto err;
-    }
-
-    uint16_t *new_group_ids = (uint16_t *)OPENSSL_realloc(
-        group_ids, (ncurves + 1) * sizeof(uint16_t));
-    if (new_group_ids == NULL) {
-      goto err;
-    }
-    group_ids = new_group_ids;
-
-    group_ids[ncurves] = group_id;
-    ncurves++;
-
+    count++;
     if (col) {
       ptr = col + 1;
     }
   } while (col);
 
-  OPENSSL_free(*out_group_ids);
-  *out_group_ids = group_ids;
-  *out_group_ids_len = ncurves;
+  Array<uint16_t> group_ids;
+  if (!group_ids.Init(count)) {
+    return false;
+  }
 
-  return 1;
+  size_t i = 0;
+  ptr = curves;
+  do {
+    col = strchr(ptr, ':');
+    if (!ssl_name_to_group_id(&group_ids[i++], ptr,
+                              col ? (size_t)(col - ptr) : strlen(ptr))) {
+      return false;
+    }
+    if (col) {
+      ptr = col + 1;
+    }
+  } while (col);
 
-err:
-  OPENSSL_free(group_ids);
-  return 0;
+  assert(i == count);
+  *out_group_ids = std::move(group_ids);
+  return true;
 }
 
 int tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
@@ -506,9 +492,8 @@
 static SSLSignatureAlgorithmList tls12_get_verify_sigalgs(const SSL *ssl,
                                                           bool for_certs) {
   SSLSignatureAlgorithmList ret;
-  if (ssl->ctx->num_verify_sigalgs != 0) {
-    ret.list =
-        MakeConstSpan(ssl->ctx->verify_sigalgs, ssl->ctx->num_verify_sigalgs);
+  if (!ssl->ctx->verify_sigalgs.empty()) {
+    ret.list = ssl->ctx->verify_sigalgs;
   } else {
     ret.list = kVerifySignatureAlgorithms;
     ret.skip_ed25519 = !ssl->ctx->ed25519_enabled;
@@ -1393,7 +1378,7 @@
 
 static bool ext_alpn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
   SSL *const ssl = hs->ssl;
-  if (hs->config->alpn_client_proto_list == NULL ||
+  if (hs->config->alpn_client_proto_list.empty() ||
       ssl->s3->initial_handshake_complete) {
     return true;
   }
@@ -1402,8 +1387,8 @@
   if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
       !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
-      !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list,
-                     hs->config->alpn_client_proto_list_len) ||
+      !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list.data(),
+                     hs->config->alpn_client_proto_list.size()) ||
       !CBB_flush(out)) {
     return false;
   }
@@ -1419,7 +1404,7 @@
   }
 
   assert(!ssl->s3->initial_handshake_complete);
-  assert(hs->config->alpn_client_proto_list != NULL);
+  assert(!hs->config->alpn_client_proto_list.empty());
 
   if (hs->next_proto_neg_seen) {
     // NPN and ALPN may not be negotiated in the same connection.
@@ -1456,7 +1441,7 @@
 
 bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
                                   Span<const uint8_t> protocol) {
-  if (hs->config->alpn_client_proto_list == nullptr) {
+  if (hs->config->alpn_client_proto_list.empty()) {
     return false;
   }
 
@@ -1465,9 +1450,9 @@
   }
 
   // Check that the protocol name is one of the ones we advertised.
-  CBS client_protocol_name_list, client_protocol_name;
-  CBS_init(&client_protocol_name_list, hs->config->alpn_client_proto_list,
-           hs->config->alpn_client_proto_list_len);
+  CBS client_protocol_name_list =
+          MakeConstSpan(hs->config->alpn_client_proto_list),
+      client_protocol_name;
   while (CBS_len(&client_protocol_name_list) > 0) {
     if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
                                     &client_protocol_name)) {
@@ -2549,7 +2534,7 @@
 
 static bool ext_token_binding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
   SSL *const ssl = hs->ssl;
-  if (hs->config->token_binding_params == nullptr || SSL_is_dtls(ssl)) {
+  if (hs->config->token_binding_params.empty() || SSL_is_dtls(ssl)) {
     return true;
   }
 
@@ -2558,8 +2543,8 @@
       !CBB_add_u16_length_prefixed(out, &contents) ||
       !CBB_add_u16(&contents, kTokenBindingMaxVersion) ||
       !CBB_add_u8_length_prefixed(&contents, &params) ||
-      !CBB_add_bytes(&params, hs->config->token_binding_params,
-                     hs->config->token_binding_params_len) ||
+      !CBB_add_bytes(&params, hs->config->token_binding_params.data(),
+                     hs->config->token_binding_params.size()) ||
       !CBB_flush(out)) {
     return false;
   }
@@ -2599,8 +2584,8 @@
     return true;
   }
 
-  for (size_t i = 0; i < hs->config->token_binding_params_len; ++i) {
-    if (param == hs->config->token_binding_params[i]) {
+  for (uint8_t config_param : hs->config->token_binding_params) {
+    if (param == config_param) {
       ssl->s3->negotiated_token_binding_param = param;
       ssl->s3->token_binding_negotiated = true;
       return true;
@@ -2617,8 +2602,7 @@
 // param is found, and false otherwise.
 static bool select_tb_param(SSL_HANDSHAKE *hs,
                             Span<const uint8_t> peer_params) {
-  for (size_t i = 0; i < hs->config->token_binding_params_len; ++i) {
-    uint8_t tb_param = hs->config->token_binding_params[i];
+  for (uint8_t tb_param : hs->config->token_binding_params) {
     for (uint8_t peer_param : peer_params) {
       if (tb_param == peer_param) {
         hs->ssl->s3->negotiated_token_binding_param = tb_param;
@@ -2633,7 +2617,7 @@
                                                 uint8_t *out_alert,
                                                 CBS *contents) {
   SSL *const ssl = hs->ssl;
-  if (contents == nullptr || hs->config->token_binding_params == nullptr) {
+  if (contents == nullptr || hs->config->token_binding_params.empty()) {
     return true;
   }
 
@@ -2689,15 +2673,16 @@
 
 static bool ext_quic_transport_params_add_clienthello(SSL_HANDSHAKE *hs,
                                                       CBB *out) {
-  if (!hs->config->quic_transport_params || hs->max_version <= TLS1_2_VERSION) {
+  if (hs->config->quic_transport_params.empty() ||
+      hs->max_version <= TLS1_2_VERSION) {
     return true;
   }
 
   CBB contents;
   if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_bytes(&contents, hs->config->quic_transport_params,
-                     hs->config->quic_transport_params_len) ||
+      !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
+                     hs->config->quic_transport_params.size()) ||
       !CBB_flush(out)) {
     return false;
   }
@@ -2724,7 +2709,7 @@
                                                         uint8_t *out_alert,
                                                         CBS *contents) {
   SSL *const ssl = hs->ssl;
-  if (!contents || !hs->config->quic_transport_params) {
+  if (!contents || hs->config->quic_transport_params.empty()) {
     return true;
   }
   // Ignore the extension before TLS 1.3.
@@ -2737,15 +2722,15 @@
 
 static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
                                                       CBB *out) {
-  if (!hs->config->quic_transport_params) {
+  if (hs->config->quic_transport_params.empty()) {
     return true;
   }
 
   CBB contents;
   if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_bytes(&contents, hs->config->quic_transport_params,
-                     hs->config->quic_transport_params_len) ||
+      !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
+                     hs->config->quic_transport_params.size()) ||
       !CBB_flush(out)) {
     return false;
   }
@@ -3667,7 +3652,7 @@
 
 bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
   SSL *const ssl = hs->ssl;
-  CERT *cert = hs->config->cert;
+  CERT *cert = hs->config->cert.get();
 
   // Before TLS 1.2, the signature algorithm isn't negotiated as part of the
   // handshake.
@@ -3789,7 +3774,8 @@
     return false;
   }
 
-  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->tlsext_channel_id_private);
+  EC_KEY *ec_key =
+      EVP_PKEY_get0_EC_KEY(hs->config->tlsext_channel_id_private.get());
   if (ec_key == nullptr) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return false;
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 696909a..4424318 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -415,7 +415,7 @@
 
 int tls13_add_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  CERT *const cert = hs->config->cert;
+  CERT *const cert = hs->config->cert.get();
 
   ScopedCBB cbb;
   CBB *body, body_storage, certificate_list;