Give SSL and SSL_CTX dummy constructor and destructor.

This doesn't actually make use of much of C++ yet. (SSL_CTX and
SSL/SSL_CONFIG carry analogous versions of a number of fields. It's
difficult to switch them to UniquePtr separately.)

Change-Id: Ia948f539c5c90e2d8301193f719604a31be17fc4
Reviewed-on: https://boringssl-review.googlesource.com/29589
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index 5a58472..d8f0cc7 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -2814,8 +2814,12 @@
 };
 
 struct ssl_ctx_st {
-  const bssl::SSL_PROTOCOL_METHOD *method;
-  const bssl::SSL_X509_METHOD *x509_method;
+  explicit ssl_ctx_st(const SSL_METHOD *ssl_method);
+  ssl_ctx_st(const ssl_ctx_st &) = delete;
+  ssl_ctx_st &operator=(const ssl_ctx_st &) = delete;
+
+  const bssl::SSL_PROTOCOL_METHOD *method = nullptr;
+  const bssl::SSL_X509_METHOD *x509_method = nullptr;
 
   // lock is used to protect various operations on this object.
   CRYPTO_MUTEX lock;
@@ -2823,45 +2827,45 @@
   // conf_max_version is the maximum acceptable protocol version configured by
   // |SSL_CTX_set_max_proto_version|. Note this version is normalized in DTLS
   // and is further constrainted by |SSL_OP_NO_*|.
-  uint16_t conf_max_version;
+  uint16_t conf_max_version = 0;
 
   // conf_min_version is the minimum acceptable protocol version configured by
   // |SSL_CTX_set_min_proto_version|. Note this version is normalized in DTLS
   // and is further constrainted by |SSL_OP_NO_*|.
-  uint16_t conf_min_version;
+  uint16_t conf_min_version = 0;
 
   // tls13_variant is the variant of TLS 1.3 we are using for this
   // configuration.
-  enum tls13_variant_t tls13_variant;
+  tls13_variant_t tls13_variant = tls13_default;
 
-  bssl::SSLCipherPreferenceList *cipher_list;
+  bssl::SSLCipherPreferenceList *cipher_list = nullptr;
 
-  X509_STORE *cert_store;
-  LHASH_OF(SSL_SESSION) *sessions;
+  X509_STORE *cert_store = nullptr;
+  LHASH_OF(SSL_SESSION) *sessions = nullptr;
   // Most session-ids that will be cached, default is
   // SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited.
-  unsigned long session_cache_size;
-  SSL_SESSION *session_cache_head;
-  SSL_SESSION *session_cache_tail;
+  unsigned long session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
+  SSL_SESSION *session_cache_head = nullptr;
+  SSL_SESSION *session_cache_tail = nullptr;
 
   // handshakes_since_cache_flush is the number of successful handshakes since
   // the last cache flush.
-  int handshakes_since_cache_flush;
+  int handshakes_since_cache_flush = 0;
 
   // This can have one of 2 values, ored together,
   // SSL_SESS_CACHE_CLIENT,
   // SSL_SESS_CACHE_SERVER,
   // Default is SSL_SESSION_CACHE_SERVER, which means only
   // SSL_accept which cache SSL_SESSIONS.
-  int session_cache_mode;
+  int session_cache_mode = SSL_SESS_CACHE_SERVER;
 
   // session_timeout is the default lifetime for new sessions in TLS 1.2 and
   // earlier, in seconds.
-  uint32_t session_timeout;
+  uint32_t session_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
 
   // session_psk_dhe_timeout is the default lifetime for new sessions in TLS
   // 1.3, in seconds.
-  uint32_t session_psk_dhe_timeout;
+  uint32_t session_psk_dhe_timeout = SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT;
 
   // If this callback is not null, it will be called each time a session id is
   // added to the cache.  If this function returns 1, it means that the
@@ -2870,111 +2874,113 @@
   // remove_session_cb is not null, it will be called when a session-id is
   // removed from the cache.  After the call, OpenSSL will SSL_SESSION_free()
   // it.
-  int (*new_session_cb)(SSL *ssl, SSL_SESSION *sess);
-  void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *sess);
+  int (*new_session_cb)(SSL *ssl, SSL_SESSION *sess) = nullptr;
+  void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *sess) = nullptr;
   SSL_SESSION *(*get_session_cb)(SSL *ssl, const uint8_t *data, int len,
-                                 int *copy);
+                                 int *copy) = nullptr;
 
-  CRYPTO_refcount_t references;
+  CRYPTO_refcount_t references = 1;
 
   // if defined, these override the X509_verify_cert() calls
-  int (*app_verify_callback)(X509_STORE_CTX *store_ctx, void *arg);
-  void *app_verify_arg;
+  int (*app_verify_callback)(X509_STORE_CTX *store_ctx, void *arg) = nullptr;
+  void *app_verify_arg = nullptr;
 
-  enum ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
-                                                     uint8_t *out_alert);
+  ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
+                                                uint8_t *out_alert) = nullptr;
 
   // Default password callback.
-  pem_password_cb *default_passwd_callback;
+  pem_password_cb *default_passwd_callback = nullptr;
 
   // Default password callback user data.
-  void *default_passwd_callback_userdata;
+  void *default_passwd_callback_userdata = nullptr;
 
   // get client cert callback
-  int (*client_cert_cb)(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey);
+  int (*client_cert_cb)(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) = nullptr;
 
   // get channel id callback
-  void (*channel_id_cb)(SSL *ssl, EVP_PKEY **out_pkey);
+  void (*channel_id_cb)(SSL *ssl, EVP_PKEY **out_pkey) = nullptr;
 
   CRYPTO_EX_DATA ex_data;
 
   // custom_*_extensions stores any callback sets for custom extensions. Note
   // that these pointers will be NULL if the stack would otherwise be empty.
-  STACK_OF(SSL_CUSTOM_EXTENSION) *client_custom_extensions;
-  STACK_OF(SSL_CUSTOM_EXTENSION) *server_custom_extensions;
+  STACK_OF(SSL_CUSTOM_EXTENSION) *client_custom_extensions = nullptr;
+  STACK_OF(SSL_CUSTOM_EXTENSION) *server_custom_extensions = nullptr;
 
   // Default values used when no per-SSL value is defined follow
 
-  void (*info_callback)(const SSL *ssl, int type, int value);
+  void (*info_callback)(const SSL *ssl, int type, int value) = nullptr;
 
   // what we put in client cert requests
-  STACK_OF(CRYPTO_BUFFER) *client_CA;
+  STACK_OF(CRYPTO_BUFFER) *client_CA = nullptr;
 
   // cached_x509_client_CA is a cache of parsed versions of the elements of
   // |client_CA|.
-  STACK_OF(X509_NAME) *cached_x509_client_CA;
+  STACK_OF(X509_NAME) *cached_x509_client_CA = nullptr;
 
 
   // Default values to use in SSL structures follow (these are copied by
   // SSL_new)
 
-  uint32_t options;
-  uint32_t mode;
-  uint32_t max_cert_list;
+  uint32_t options = 0;
+  // Disable the auto-chaining feature by default. wpa_supplicant relies on this
+  // feature, but require callers opt into it.
+  uint32_t mode = SSL_MODE_NO_AUTO_CHAIN;
+  uint32_t max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
 
-  bssl::CERT *cert;
+  bssl::CERT *cert = nullptr;
 
   // callback that allows applications to peek at protocol messages
   void (*msg_callback)(int write_p, int version, int content_type,
-                       const void *buf, size_t len, SSL *ssl, void *arg);
-  void *msg_callback_arg;
+                       const void *buf, size_t len, SSL *ssl, void *arg) = nullptr;
+  void *msg_callback_arg = nullptr;
 
-  int verify_mode;
-  int (*default_verify_callback)(
-      int ok, X509_STORE_CTX *ctx);  // called 'verify_callback' in the SSL
+  int verify_mode = SSL_VERIFY_NONE;
+  int (*default_verify_callback)(int ok, X509_STORE_CTX *ctx) =
+      nullptr;  // called 'verify_callback' in the SSL
 
-  X509_VERIFY_PARAM *param;
+  X509_VERIFY_PARAM *param = nullptr;
 
   // select_certificate_cb is called before most ClientHello processing and
   // before the decision whether to resume a session is made. See
   // |ssl_select_cert_result_t| for details of the return values.
-  enum ssl_select_cert_result_t (*select_certificate_cb)(
-      const SSL_CLIENT_HELLO *);
+  ssl_select_cert_result_t (*select_certificate_cb)(const SSL_CLIENT_HELLO *) =
+      nullptr;
 
   // dos_protection_cb is called once the resumption decision for a ClientHello
   // has been made. It returns one to continue the handshake or zero to
   // abort.
-  int (*dos_protection_cb) (const SSL_CLIENT_HELLO *);
+  int (*dos_protection_cb) (const SSL_CLIENT_HELLO *) = nullptr;
 
   // Maximum amount of data to send in one fragment. actual record size can be
   // more than this due to padding and MAC overheads.
-  uint16_t max_send_fragment;
+  uint16_t max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
 
   // TLS extensions servername callback
-  int (*tlsext_servername_callback)(SSL *, int *, void *);
-  void *tlsext_servername_arg;
+  int (*tlsext_servername_callback)(SSL *, int *, void *) = nullptr;
+  void *tlsext_servername_arg = nullptr;
 
   // RFC 4507 session ticket keys. |tlsext_ticket_key_current| may be NULL
   // before the first handshake and |tlsext_ticket_key_prev| may be NULL at any
   // time. Automatically generated ticket keys are rotated as needed at
   // handshake time. Hence, all access must be synchronized through |lock|.
-  bssl::tlsext_ticket_key *tlsext_ticket_key_current;
-  bssl::tlsext_ticket_key *tlsext_ticket_key_prev;
+  bssl::tlsext_ticket_key *tlsext_ticket_key_current = nullptr;
+  bssl::tlsext_ticket_key *tlsext_ticket_key_prev = nullptr;
 
   // Callback to support customisation of ticket key setting
   int (*tlsext_ticket_key_cb)(SSL *ssl, uint8_t *name, uint8_t *iv,
-                              EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc);
+                              EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx,
+                              int enc) = nullptr;
 
   // Server-only: psk_identity_hint is the default identity hint to send in
   // PSK-based key exchanges.
-  char *psk_identity_hint;
+  char *psk_identity_hint = nullptr;
 
-  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);
-  unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
-                                      uint8_t *psk, unsigned int max_psk_len);
+  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;
 
 
   // Next protocol negotiation information
@@ -2983,13 +2989,14 @@
   // For a server, this contains a callback function by which the set of
   // advertised protocols can be provided.
   int (*next_protos_advertised_cb)(SSL *ssl, const uint8_t **out,
-                                   unsigned *out_len, void *arg);
-  void *next_protos_advertised_cb_arg;
+                                   unsigned *out_len, void *arg) = nullptr;
+  void *next_protos_advertised_cb_arg = nullptr;
   // For a client, this contains a callback function that selects the
   // next protocol from the list provided by the server.
   int (*next_proto_select_cb)(SSL *ssl, uint8_t **out, uint8_t *out_len,
-                              const uint8_t *in, unsigned in_len, void *arg);
-  void *next_proto_select_cb_arg;
+                              const uint8_t *in, unsigned in_len,
+                              void *arg) = nullptr;
+  void *next_proto_select_cb_arg = nullptr;
 
   // ALPN information
   // (we are in the process of transitioning from NPN to ALPN.)
@@ -3003,53 +3010,54 @@
   //       wire-format.
   //   inlen: the length of |in|.
   int (*alpn_select_cb)(SSL *ssl, const uint8_t **out, uint8_t *out_len,
-                        const uint8_t *in, unsigned in_len, void *arg);
-  void *alpn_select_cb_arg;
+                        const uint8_t *in, unsigned in_len,
+                        void *arg) = nullptr;
+  void *alpn_select_cb_arg = nullptr;
 
   // For a client, this contains the list of supported protocols in wire
   // format.
-  uint8_t *alpn_client_proto_list;
-  unsigned alpn_client_proto_list_len;
+  uint8_t *alpn_client_proto_list = nullptr;
+  unsigned alpn_client_proto_list_len = 0;
 
   // SRTP profiles we are willing to do from RFC 5764
-  STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+  STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles = nullptr;
 
   // Defined compression algorithms for certificates.
-  STACK_OF(CertCompressionAlg) *cert_compression_algs;
+  STACK_OF(CertCompressionAlg) *cert_compression_algs = nullptr;
 
   // Supported group values inherited by SSL structure
-  size_t supported_group_list_len;
-  uint16_t *supported_group_list;
+  size_t supported_group_list_len = 0;
+  uint16_t *supported_group_list = nullptr;
 
   // The client's Channel ID private key.
-  EVP_PKEY *tlsext_channel_id_private;
+  EVP_PKEY *tlsext_channel_id_private = nullptr;
 
   // keylog_callback, if not NULL, is the key logging callback. See
   // |SSL_CTX_set_keylog_callback|.
-  void (*keylog_callback)(const SSL *ssl, const char *line);
+  void (*keylog_callback)(const SSL *ssl, const char *line) = nullptr;
 
   // current_time_cb, if not NULL, is the function to use to get the current
   // time. It sets |*out_clock| to the current time. The |ssl| argument is
   // always NULL. See |SSL_CTX_set_current_time_cb|.
-  void (*current_time_cb)(const SSL *ssl, struct timeval *out_clock);
+  void (*current_time_cb)(const SSL *ssl, struct timeval *out_clock) = nullptr;
 
   // pool is used for all |CRYPTO_BUFFER|s in case we wish to share certificate
   // memory.
-  CRYPTO_BUFFER_POOL *pool;
+  CRYPTO_BUFFER_POOL *pool = nullptr;
 
   // ticket_aead_method contains function pointers for opening and sealing
   // session tickets.
-  const SSL_TICKET_AEAD_METHOD *ticket_aead_method;
+  const SSL_TICKET_AEAD_METHOD *ticket_aead_method = nullptr;
 
   // legacy_ocsp_callback implements an OCSP-related callback for OpenSSL
   // compatibility.
-  int (*legacy_ocsp_callback)(SSL *ssl, void *arg);
-  void *legacy_ocsp_callback_arg;
+  int (*legacy_ocsp_callback)(SSL *ssl, void *arg) = nullptr;
+  void *legacy_ocsp_callback_arg = nullptr;
 
   // verify_sigalgs, if not empty, is the set of signature algorithms
   // accepted from the peer in decreasing order of preference.
-  uint16_t *verify_sigalgs;
-  size_t num_verify_sigalgs;
+  uint16_t *verify_sigalgs = nullptr;
+  size_t num_verify_sigalgs = 0;
 
   // 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
@@ -3097,75 +3105,88 @@
 
   // If enable_early_data is true, early data can be sent and accepted.
   bool enable_early_data : 1;
+
+ private:
+  ~ssl_ctx_st();
+  friend void SSL_CTX_free(SSL_CTX *);
 };
 
 struct ssl_st {
+  explicit ssl_st(SSL_CTX *ctx_arg);
+  ssl_st(const ssl_st &) = delete;
+  ssl_st &operator=(const ssl_st &) = delete;
+  ~ssl_st();
+
   // method is the method table corresponding to the current protocol (DTLS or
   // TLS).
-  const bssl::SSL_PROTOCOL_METHOD *method;
+  const bssl::SSL_PROTOCOL_METHOD *method = nullptr;
 
   // config is a container for handshake configuration.  Accesses to this field
   // should check for nullptr, since configuration may be shed after the
   // handshake completes.  (If you have the |SSL_HANDSHAKE| object at hand, use
   // that instead, and skip the null check.)
-  bssl::SSL_CONFIG *config;
+  bssl::SSL_CONFIG *config = nullptr;
 
   // version is the protocol version.
-  uint16_t version;
+  uint16_t version = 0;
 
-  uint16_t max_send_fragment;
+  uint16_t max_send_fragment = 0;
 
   // There are 2 BIO's even though they are normally both the same. This is so
   // data can be read and written to different handlers
 
-  BIO *rbio;  // used by SSL_read
-  BIO *wbio;  // used by SSL_write
+  BIO *rbio = nullptr;  // used by SSL_read
+  BIO *wbio = nullptr;  // used by SSL_write
 
   // do_handshake runs the handshake. On completion, it returns |ssl_hs_ok|.
   // Otherwise, it returns a value corresponding to what operation is needed to
   // progress.
-  bssl::ssl_hs_wait_t (*do_handshake)(bssl::SSL_HANDSHAKE *hs);
+  bssl::ssl_hs_wait_t (*do_handshake)(bssl::SSL_HANDSHAKE *hs) = nullptr;
 
-  bssl::SSL3_STATE *s3;   // SSLv3 variables
-  bssl::DTLS1_STATE *d1;  // DTLSv1 variables
+  bssl::SSL3_STATE *s3 = nullptr;   // SSLv3 variables
+  bssl::DTLS1_STATE *d1 = nullptr;  // DTLSv1 variables
 
   // callback that allows applications to peek at protocol messages
   void (*msg_callback)(int write_p, int version, int content_type,
-                       const void *buf, size_t len, SSL *ssl, void *arg);
-  void *msg_callback_arg;
+                       const void *buf, size_t len, SSL *ssl,
+                       void *arg) = nullptr;
+  void *msg_callback_arg = nullptr;
 
   // session info
 
   // initial_timeout_duration_ms is the default DTLS timeout duration in
   // milliseconds. It's used to initialize the timer any time it's restarted.
-  unsigned initial_timeout_duration_ms;
+  //
+  // RFC 6347 states that implementations SHOULD use an initial timer value of 1
+  // second.
+  unsigned initial_timeout_duration_ms = 1000;
 
   // tls13_variant is the variant of TLS 1.3 we are using for this
   // configuration.
-  enum tls13_variant_t tls13_variant;
+  tls13_variant_t tls13_variant = tls13_default;
 
   // session is the configured session to be offered by the client. This session
   // is immutable.
-  SSL_SESSION *session;
+  SSL_SESSION *session = nullptr;
 
-  void (*info_callback)(const SSL *ssl, int type, int value);
+  void (*info_callback)(const SSL *ssl, int type, int value) = nullptr;
 
-  SSL_CTX *ctx;
+  SSL_CTX *ctx = nullptr;
 
   // session_ctx is the |SSL_CTX| used for the session cache and related
   // settings.
-  SSL_CTX *session_ctx;
+  SSL_CTX *session_ctx = nullptr;
 
   // extra application data
   CRYPTO_EX_DATA ex_data;
 
-  uint32_t options;  // protocol behaviour
-  uint32_t mode;     // API behaviour
-  uint32_t max_cert_list;
-  char *tlsext_hostname;
+  uint32_t options = 0;  // protocol behaviour
+  uint32_t mode = 0;     // API behaviour
+  uint32_t max_cert_list = 0;
+  char *tlsext_hostname = nullptr;
 
   // renegotiate_mode controls how peer renegotiation attempts are handled.
-  enum ssl_renegotiate_mode_t renegotiate_mode;
+  ssl_renegotiate_mode_t renegotiate_mode = ssl_renegotiate_never;
 
   // server is true iff the this SSL* is the server half. Note: before the SSL*
   // is initialized by either SSL_set_accept_state or SSL_set_connect_state,
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index c68968a..d6d1194 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -534,84 +534,86 @@
   return OPENSSL_memcmp(a->session_id, b->session_id, a->session_id_length);
 }
 
-SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
-  SSL_CTX *ret = NULL;
+ssl_ctx_st::ssl_ctx_st(const SSL_METHOD *ssl_method)
+    : method(ssl_method->method),
+      x509_method(ssl_method->x509_method),
+      retain_only_sha256_of_client_certs(false),
+      quiet_shutdown(false),
+      ocsp_stapling_enabled(false),
+      signed_cert_timestamps_enabled(false),
+      tlsext_channel_id_enabled(false),
+      grease_enabled(false),
+      allow_unknown_alpn_protos(false),
+      ed25519_enabled(false),
+      rsa_pss_rsae_certs_enabled(true),
+      false_start_allowed_without_alpn(false),
+      handoff(false),
+      enable_early_data(false) {
+  CRYPTO_MUTEX_init(&lock);
+  CRYPTO_new_ex_data(&ex_data);
+}
 
+ssl_ctx_st::~ssl_ctx_st() {
+  // Free the internal session cache. Note that this calls the caller-supplied
+  // remove callback, so we must do it before clearing ex_data. (See ticket
+  // [openssl.org #212].)
+  SSL_CTX_flush_sessions(this, 0);
+
+  CRYPTO_free_ex_data(&g_ex_data_class_ssl_ctx, this, &ex_data);
+
+  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);
+}
+
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
   if (method == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_NULL_SSL_METHOD_PASSED);
-    return NULL;
+    return nullptr;
   }
 
-  ret = (SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX));
-  if (ret == NULL) {
-    goto err;
+  UniquePtr<SSL_CTX> ret = MakeUnique<SSL_CTX>(method);
+  if (!ret) {
+    return nullptr;
   }
 
-  OPENSSL_memset(ret, 0, sizeof(SSL_CTX));
-
-  ret->method = method->method;
-  ret->x509_method = method->x509_method;
-
-  CRYPTO_MUTEX_init(&ret->lock);
-
-  ret->session_cache_mode = SSL_SESS_CACHE_SERVER;
-  ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
-
-  ret->session_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
-  ret->session_psk_dhe_timeout = SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT;
-
-  ret->references = 1;
-
-  ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
-  ret->verify_mode = SSL_VERIFY_NONE;
   ret->cert = New<CERT>(method->x509_method);
-  if (ret->cert == NULL) {
-    goto err;
-  }
-
   ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp);
-  if (ret->sessions == NULL) {
-    goto err;
-  }
-
-  if (!ret->x509_method->ssl_ctx_new(ret)) {
-    goto err;
-  }
-
-  if (!SSL_CTX_set_strict_cipher_list(ret, SSL_DEFAULT_CIPHER_LIST)) {
-    goto err2;
-  }
-
   ret->client_CA = sk_CRYPTO_BUFFER_new_null();
-  if (ret->client_CA == NULL) {
-    goto err;
+  if (ret->cert == nullptr ||
+      ret->sessions == nullptr ||
+      ret->client_CA == nullptr ||
+      !ret->x509_method->ssl_ctx_new(ret.get())) {
+    return nullptr;
   }
 
-  CRYPTO_new_ex_data(&ret->ex_data);
-
-  ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
-
-  // Disable the auto-chaining feature by default. Once this has stuck without
-  // problems, the feature will be removed entirely.
-  ret->mode = SSL_MODE_NO_AUTO_CHAIN;
-
-  ret->rsa_pss_rsae_certs_enabled = true;
-
-  // Lock the SSL_CTX to the specified version, for compatibility with legacy
-  // uses of SSL_METHOD.
-  if (!SSL_CTX_set_max_proto_version(ret, method->version) ||
-      !SSL_CTX_set_min_proto_version(ret, method->version)) {
+  if (!SSL_CTX_set_strict_cipher_list(ret.get(), SSL_DEFAULT_CIPHER_LIST) ||
+      // Lock the SSL_CTX to the specified version, for compatibility with
+      // legacy uses of SSL_METHOD.
+      !SSL_CTX_set_max_proto_version(ret.get(), method->version) ||
+      !SSL_CTX_set_min_proto_version(ret.get(), method->version)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    goto err2;
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-err2:
-  SSL_CTX_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int SSL_CTX_up_ref(SSL_CTX *ctx) {
@@ -625,99 +627,82 @@
     return;
   }
 
-  // Free internal session cache. However: the remove_cb() may reference the
-  // ex_data of SSL_CTX, thus the ex_data store can only be removed after the
-  // sessions were flushed. As the ex_data handling routines might also touch
-  // the session cache, the most secure solution seems to be: empty (flush) the
-  // cache, then free ex_data, then finally free the cache. (See ticket
-  // [openssl.org #212].)
-  SSL_CTX_flush_sessions(ctx, 0);
-
-  CRYPTO_free_ex_data(&g_ex_data_class_ssl_ctx, ctx, &ctx->ex_data);
-
-  CRYPTO_MUTEX_cleanup(&ctx->lock);
-  lh_SSL_SESSION_free(ctx->sessions);
-  Delete(ctx->cipher_list);
-  Delete(ctx->cert);
-  sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->client_custom_extensions,
-                                   SSL_CUSTOM_EXTENSION_free);
-  sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->server_custom_extensions,
-                                   SSL_CUSTOM_EXTENSION_free);
-  sk_CRYPTO_BUFFER_pop_free(ctx->client_CA, CRYPTO_BUFFER_free);
-  ctx->x509_method->ssl_ctx_free(ctx);
-  sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles);
-  sk_CertCompressionAlg_pop_free(ctx->cert_compression_algs,
-                                 Delete<CertCompressionAlg>);
-  OPENSSL_free(ctx->psk_identity_hint);
-  OPENSSL_free(ctx->supported_group_list);
-  OPENSSL_free(ctx->alpn_client_proto_list);
-  EVP_PKEY_free(ctx->tlsext_channel_id_private);
-  OPENSSL_free(ctx->verify_sigalgs);
-  OPENSSL_free(ctx->tlsext_ticket_key_current);
-  OPENSSL_free(ctx->tlsext_ticket_key_prev);
-
+  ctx->~ssl_ctx_st();
   OPENSSL_free(ctx);
 }
 
+ssl_st::ssl_st(SSL_CTX *ctx_arg)
+    : method(ctx_arg->method),
+      max_send_fragment(ctx_arg->max_send_fragment),
+      msg_callback(ctx_arg->msg_callback),
+      msg_callback_arg(ctx_arg->msg_callback_arg),
+      tls13_variant(ctx_arg->tls13_variant),
+      ctx(UpRef(ctx_arg).release()),
+      session_ctx(UpRef(ctx_arg).release()),
+      options(ctx->options),
+      mode(ctx->mode),
+      max_cert_list(ctx->max_cert_list),
+      server(false),
+      quiet_shutdown(ctx->quiet_shutdown),
+      did_dummy_pq_padding(false),
+      enable_early_data(ctx->enable_early_data) {
+  CRYPTO_new_ex_data(&ex_data);
+}
+
+ssl_st::~ssl_st() {
+  CRYPTO_free_ex_data(&g_ex_data_class_ssl, this, &ex_data);
+
+  BIO_free_all(rbio);
+  BIO_free_all(wbio);
+
+  Delete(config);
+  config = nullptr;
+
+  SSL_SESSION_free(session);
+
+  OPENSSL_free(tlsext_hostname);
+
+  if (method != NULL) {
+    method->ssl_free(this);
+  }
+  SSL_CTX_free(ctx);
+  SSL_CTX_free(session_ctx);
+}
+
 SSL *SSL_new(SSL_CTX *ctx) {
-  if (ctx == NULL) {
+  if (ctx == nullptr) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_NULL_SSL_CTX);
-    return NULL;
-  }
-  if (ctx->method == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
-    return NULL;
+    return nullptr;
   }
 
-  SSL *ssl = (SSL *)OPENSSL_malloc(sizeof(SSL));
-  if (ssl == NULL) {
-    goto err;
+  UniquePtr<SSL> ssl = MakeUnique<SSL>(ctx);
+  if (ssl == nullptr) {
+    return nullptr;
   }
-  OPENSSL_memset(ssl, 0, sizeof(SSL));
 
-  ssl->config = New<SSL_CONFIG>(ssl);
+  ssl->config = New<SSL_CONFIG>(ssl.get());
   if (ssl->config == nullptr) {
-    goto err;
+    return nullptr;
   }
   ssl->config->conf_min_version = ctx->conf_min_version;
   ssl->config->conf_max_version = ctx->conf_max_version;
-  ssl->tls13_variant = ctx->tls13_variant;
-
-  // RFC 6347 states that implementations SHOULD use an initial timer value of
-  // 1 second.
-  ssl->initial_timeout_duration_ms = 1000;
-
-  ssl->options = ctx->options;
-  ssl->mode = ctx->mode;
-  ssl->max_cert_list = ctx->max_cert_list;
 
   ssl->config->cert = ssl_cert_dup(ctx->cert).release();
   if (ssl->config->cert == NULL) {
-    goto err;
+    return nullptr;
   }
 
-  ssl->msg_callback = ctx->msg_callback;
-  ssl->msg_callback_arg = ctx->msg_callback_arg;
   ssl->config->verify_mode = ctx->verify_mode;
   ssl->config->verify_callback = ctx->default_verify_callback;
   ssl->config->custom_verify_callback = ctx->custom_verify_callback;
   ssl->config->retain_only_sha256_of_client_certs =
       ctx->retain_only_sha256_of_client_certs;
 
-  ssl->quiet_shutdown = ctx->quiet_shutdown;
-  ssl->max_send_fragment = ctx->max_send_fragment;
-  ssl->enable_early_data = ctx->enable_early_data;
-
-  SSL_CTX_up_ref(ctx);
-  ssl->ctx = ctx;
-  SSL_CTX_up_ref(ctx);
-  ssl->session_ctx = ctx;
-
   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) {
-      goto err;
+      return nullptr;
     }
     ssl->config->supported_group_list_len = ctx->supported_group_list_len;
   }
@@ -726,27 +711,15 @@
     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) {
-      goto err;
+      return nullptr;
     }
     ssl->config->alpn_client_proto_list_len = ctx->alpn_client_proto_list_len;
   }
 
-  ssl->method = ctx->method;
-
-  if (!ssl->method->ssl_new(ssl)) {
-    goto err;
-  }
-
-  if (!ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
-    goto err;
-  }
-
-  CRYPTO_new_ex_data(&ssl->ex_data);
-
   if (ctx->psk_identity_hint) {
     ssl->config->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint);
     if (ssl->config->psk_identity_hint == NULL) {
-      goto err;
+      return nullptr;
     }
   }
   ssl->config->psk_client_callback = ctx->psk_client_callback;
@@ -763,13 +736,12 @@
   ssl->config->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
   ssl->config->handoff = ctx->handoff;
 
-  return ssl;
+  if (!ssl->method->ssl_new(ssl.get()) ||
+      !ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
+    return nullptr;
+  }
 
-err:
-  SSL_free(ssl);
-  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-
-  return NULL;
+  return ssl.release();
 }
 
 SSL_CONFIG::SSL_CONFIG(SSL *ssl_arg)
@@ -800,29 +772,7 @@
 }
 
 void SSL_free(SSL *ssl) {
-  if (ssl == NULL) {
-    return;
-  }
-
-  CRYPTO_free_ex_data(&g_ex_data_class_ssl, ssl, &ssl->ex_data);
-
-  BIO_free_all(ssl->rbio);
-  BIO_free_all(ssl->wbio);
-
-  Delete(ssl->config);
-  ssl->config = NULL;
-
-  SSL_SESSION_free(ssl->session);
-
-  OPENSSL_free(ssl->tlsext_hostname);
-
-  if (ssl->method != NULL) {
-    ssl->method->ssl_free(ssl);
-  }
-  SSL_CTX_free(ssl->ctx);
-  SSL_CTX_free(ssl->session_ctx);
-
-  OPENSSL_free(ssl);
+  Delete(ssl);
 }
 
 void SSL_set_connect_state(SSL *ssl) {