Give SSL3_STATE a constructor and destructor.

Change-Id: I326bbc234cecb01741c177884ecabbc53367463d
Reviewed-on: https://boringssl-review.googlesource.com/21945
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/internal.h b/ssl/internal.h
index e502ec0..8c373d2 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -2161,11 +2161,16 @@
 };
 
 struct SSL3_STATE {
-  uint8_t read_sequence[8];
-  uint8_t write_sequence[8];
+  static constexpr bool kAllowUniquePtr = true;
 
-  uint8_t server_random[SSL3_RANDOM_SIZE];
-  uint8_t client_random[SSL3_RANDOM_SIZE];
+  SSL3_STATE();
+  ~SSL3_STATE();
+
+  uint8_t read_sequence[8] = {0};
+  uint8_t write_sequence[8] = {0};
+
+  uint8_t server_random[SSL3_RANDOM_SIZE] = {0};
+  uint8_t client_random[SSL3_RANDOM_SIZE] = {0};
 
   // read_buffer holds data from the transport to be processed.
   SSLBuffer read_buffer;
@@ -2177,39 +2182,39 @@
   Span<uint8_t> pending_app_data;
 
   // partial write - check the numbers match
-  unsigned int wnum;  // number of bytes sent so far
-  int wpend_tot;      // number bytes written
-  int wpend_type;
-  int wpend_ret;  // number of bytes submitted
-  const uint8_t *wpend_buf;
+  unsigned int wnum = 0;  // number of bytes sent so far
+  int wpend_tot = 0;      // number bytes written
+  int wpend_type = 0;
+  int wpend_ret = 0;  // number of bytes submitted
+  const uint8_t *wpend_buf = nullptr;
 
   // read_shutdown is the shutdown state for the read half of the connection.
-  enum ssl_shutdown_t read_shutdown;
+  enum ssl_shutdown_t read_shutdown = ssl_shutdown_none;
 
   // write_shutdown is the shutdown state for the write half of the connection.
-  enum ssl_shutdown_t write_shutdown;
+  enum ssl_shutdown_t write_shutdown = ssl_shutdown_none;
 
   // read_error, if |read_shutdown| is |ssl_shutdown_error|, is the error for
   // the receive half of the connection.
-  ERR_SAVE_STATE *read_error;
+  ERR_SAVE_STATE *read_error = nullptr;
 
-  int alert_dispatch;
+  int alert_dispatch = 0;
 
-  int total_renegotiations;
+  int total_renegotiations = 0;
 
   // early_data_skipped is the amount of early data that has been skipped by the
   // record layer.
-  uint16_t early_data_skipped;
+  uint16_t early_data_skipped = 0;
 
   // empty_record_count is the number of consecutive empty records received.
-  uint8_t empty_record_count;
+  uint8_t empty_record_count = 0;
 
   // warning_alert_count is the number of consecutive warning alerts
   // received.
-  uint8_t warning_alert_count;
+  uint8_t warning_alert_count = 0;
 
   // key_update_count is the number of consecutive KeyUpdates received.
-  uint8_t key_update_count;
+  uint8_t key_update_count = 0;
 
   // skip_early_data instructs the record layer to skip unexpected early data
   // messages when 0RTT is rejected.
@@ -2253,41 +2258,41 @@
   // wpend_pending is true if we have a pending write outstanding.
   bool wpend_pending:1;
 
-  uint8_t send_alert[2];
+  uint8_t send_alert[2] = {0};
 
   // pending_flight is the pending outgoing flight. This is used to flush each
   // handshake flight in a single write. |write_buffer| must be written out
   // before this data.
-  BUF_MEM *pending_flight;
+  BUF_MEM *pending_flight = nullptr;
 
   // pending_flight_offset is the number of bytes of |pending_flight| which have
   // been successfully written.
-  uint32_t pending_flight_offset;
+  uint32_t pending_flight_offset = 0;
 
   // aead_read_ctx is the current read cipher state.
-  SSLAEADContext *aead_read_ctx;
+  SSLAEADContext *aead_read_ctx = nullptr;
 
   // aead_write_ctx is the current write cipher state.
-  SSLAEADContext *aead_write_ctx;
+  SSLAEADContext *aead_write_ctx = nullptr;
 
   // hs is the handshake state for the current handshake or NULL if there isn't
   // one.
-  SSL_HANDSHAKE *hs;
+  SSL_HANDSHAKE *hs = nullptr;
 
-  uint8_t write_traffic_secret[EVP_MAX_MD_SIZE];
-  uint8_t read_traffic_secret[EVP_MAX_MD_SIZE];
-  uint8_t exporter_secret[EVP_MAX_MD_SIZE];
-  uint8_t early_exporter_secret[EVP_MAX_MD_SIZE];
-  uint8_t write_traffic_secret_len;
-  uint8_t read_traffic_secret_len;
-  uint8_t exporter_secret_len;
-  uint8_t early_exporter_secret_len;
+  uint8_t write_traffic_secret[EVP_MAX_MD_SIZE] = {0};
+  uint8_t read_traffic_secret[EVP_MAX_MD_SIZE] = {0};
+  uint8_t exporter_secret[EVP_MAX_MD_SIZE] = {0};
+  uint8_t early_exporter_secret[EVP_MAX_MD_SIZE] = {0};
+  uint8_t write_traffic_secret_len = 0;
+  uint8_t read_traffic_secret_len = 0;
+  uint8_t exporter_secret_len = 0;
+  uint8_t early_exporter_secret_len = 0;
 
   // Connection binding to prevent renegotiation attacks
-  uint8_t previous_client_finished[12];
-  uint8_t previous_client_finished_len;
-  uint8_t previous_server_finished_len;
-  uint8_t previous_server_finished[12];
+  uint8_t previous_client_finished[12] = {0};
+  uint8_t previous_client_finished_len = 0;
+  uint8_t previous_server_finished_len = 0;
+  uint8_t previous_server_finished[12] = {0};
 
   // State pertaining to the pending handshake.
   //
@@ -2297,12 +2302,12 @@
     uint8_t new_mac_secret_len;
     uint8_t new_key_len;
     uint8_t new_fixed_iv_len;
-  } tmp;
+  } tmp = {0, 0, 0};
 
   // established_session is the session established by the connection. This
   // session is only filled upon the completion of the handshake and is
   // immutable.
-  SSL_SESSION *established_session;
+  SSL_SESSION *established_session = nullptr;
 
   // Next protocol negotiation. For the client, this is the protocol that we
   // sent in NextProtocol and is set when handling ServerHello extensions.
@@ -2310,8 +2315,8 @@
   // For a server, this is the client's selected_protocol from NextProtocol and
   // is set when handling the NextProtocol message, before the Finished
   // message.
-  uint8_t *next_proto_negotiated;
-  size_t next_proto_negotiated_len;
+  uint8_t *next_proto_negotiated = nullptr;
+  size_t next_proto_negotiated_len = 0;
 
   // ALPN information
   // (we are in the process of transitioning from NPN to ALPN.)
@@ -2319,22 +2324,22 @@
   // In a server these point to the selected ALPN protocol after the
   // ClientHello has been processed. In a client these contain the protocol
   // that the server selected once the ServerHello has been processed.
-  uint8_t *alpn_selected;
-  size_t alpn_selected_len;
+  uint8_t *alpn_selected = nullptr;
+  size_t alpn_selected_len = 0;
 
   // hostname, on the server, is the value of the SNI extension.
-  char *hostname;
+  char *hostname = nullptr;
 
   // For a server:
   //     If |tlsext_channel_id_valid| is true, then this contains the
   //     verified Channel ID from the client: a P256 point, (x,y), where
   //     each are big-endian values.
-  uint8_t tlsext_channel_id[64];
+  uint8_t tlsext_channel_id[64] = {0};
 
   // ticket_age_skew is the difference, in seconds, between the client-sent
   // ticket age and the server-computed value in TLS 1.3 server connections
   // which resumed a session.
-  int32_t ticket_age_skew;
+  int32_t ticket_age_skew = 0;
 };
 
 // lengths of messages
diff --git a/ssl/s3_lib.cc b/ssl/s3_lib.cc
index d7af4f4..f69005b 100644
--- a/ssl/s3_lib.cc
+++ b/ssl/s3_lib.cc
@@ -164,6 +164,31 @@
 
 namespace bssl {
 
+SSL3_STATE::SSL3_STATE()
+    : skip_early_data(false),
+      have_version(false),
+      v2_hello_done(false),
+      is_v2_hello(false),
+      has_message(false),
+      initial_handshake_complete(false),
+      session_reused(false),
+      send_connection_binding(false),
+      tlsext_channel_id_valid(false),
+      key_update_pending(false),
+      wpend_pending(false) {}
+
+SSL3_STATE::~SSL3_STATE() {
+  ERR_SAVE_STATE_free(read_error);
+  SSL_SESSION_free(established_session);
+  ssl_handshake_free(hs);
+  OPENSSL_free(next_proto_negotiated);
+  OPENSSL_free(alpn_selected);
+  OPENSSL_free(hostname);
+  Delete(aead_read_ctx);
+  Delete(aead_write_ctx);
+  BUF_MEM_free(pending_flight);
+}
+
 bool ssl3_new(SSL *ssl) {
   UniquePtr<SSLAEADContext> aead_read_ctx =
       SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
@@ -173,23 +198,19 @@
     return false;
   }
 
-  SSL3_STATE *s3 = (SSL3_STATE *)OPENSSL_malloc(sizeof *s3);
-  if (s3 == NULL) {
+  UniquePtr<SSL3_STATE> s3 = MakeUnique<SSL3_STATE>();
+  if (!s3) {
     return false;
   }
-  OPENSSL_memset(s3, 0, sizeof *s3);
-  new (&s3->read_buffer) SSLBuffer();
-  new (&s3->write_buffer) SSLBuffer();
 
   s3->hs = ssl_handshake_new(ssl);
   if (s3->hs == NULL) {
-    OPENSSL_free(s3);
     return false;
   }
 
   s3->aead_read_ctx = aead_read_ctx.release();
   s3->aead_write_ctx = aead_write_ctx.release();
-  ssl->s3 = s3;
+  ssl->s3 = s3.release();
 
   // Set the version to the highest supported version.
   //
@@ -205,19 +226,7 @@
     return;
   }
 
-  ssl->s3->read_buffer.~SSLBuffer();
-  ssl->s3->write_buffer.~SSLBuffer();
-  ERR_SAVE_STATE_free(ssl->s3->read_error);
-  SSL_SESSION_free(ssl->s3->established_session);
-  ssl_handshake_free(ssl->s3->hs);
-  OPENSSL_free(ssl->s3->next_proto_negotiated);
-  OPENSSL_free(ssl->s3->alpn_selected);
-  OPENSSL_free(ssl->s3->hostname);
-  Delete(ssl->s3->aead_read_ctx);
-  Delete(ssl->s3->aead_write_ctx);
-  BUF_MEM_free(ssl->s3->pending_flight);
-
-  OPENSSL_free(ssl->s3);
+  Delete(ssl->s3);
   ssl->s3 = NULL;
 }