Move state and next_state to SSL_HANDSHAKE.

state is now initialized to SSL_ST_INIT in SSL_HANDSHAKE. If there is no
handshake present, we report SSL_ST_OK. This saves 8 bytes of
per-connection post-handshake memory.

Change-Id: Idb3f7031045caed005bd7712bc8c4b42c81a1d04
Reviewed-on: https://boringssl-review.googlesource.com/12697
Reviewed-by: David Benjamin <davidben@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/include/openssl/ssl.h b/include/openssl/ssl.h
index b123b34..d4b17c9 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4058,9 +4058,6 @@
   /* version is the protocol version. */
   int version;
 
-  /* state contains one of the SSL3_ST_* values. */
-  int state;
-
   /* max_version is the maximum acceptable protocol version. Note this version
    * is normalized in DTLS. */
   uint16_t max_version;
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index b73215b..bae5365 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -195,11 +195,11 @@
   assert(!ssl->server);
 
   for (;;) {
-    state = ssl->state;
+    state = hs->state;
 
-    switch (ssl->state) {
+    switch (hs->state) {
       case SSL_ST_INIT:
-        ssl->state = SSL_ST_CONNECT;
+        hs->state = SSL_ST_CONNECT;
         skip = 1;
         break;
 
@@ -211,7 +211,7 @@
           goto end;
         }
 
-        ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
+        hs->state = SSL3_ST_CW_CLNT_HELLO_A;
         break;
 
       case SSL3_ST_CW_CLNT_HELLO_A:
@@ -222,11 +222,11 @@
         }
 
         if (!SSL_is_dtls(ssl) || ssl->d1->send_cookie) {
-          ssl->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
+          hs->next_state = SSL3_ST_CR_SRVR_HELLO_A;
         } else {
-          ssl->s3->tmp.next_state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
+          hs->next_state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
         }
-        ssl->state = SSL3_ST_CW_FLUSH;
+        hs->state = SSL3_ST_CW_FLUSH;
         break;
 
       case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
@@ -237,15 +237,15 @@
         }
         if (ssl->d1->send_cookie) {
           ssl->method->received_flight(ssl);
-          ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
+          hs->state = SSL3_ST_CW_CLNT_HELLO_A;
         } else {
-          ssl->state = SSL3_ST_CR_SRVR_HELLO_A;
+          hs->state = SSL3_ST_CR_SRVR_HELLO_A;
         }
         break;
 
       case SSL3_ST_CR_SRVR_HELLO_A:
         ret = ssl3_get_server_hello(hs);
-        if (ssl->state == SSL_ST_TLS13) {
+        if (hs->state == SSL_ST_TLS13) {
           break;
         }
         if (ret <= 0) {
@@ -253,9 +253,9 @@
         }
 
         if (ssl->session != NULL) {
-          ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
+          hs->state = SSL3_ST_CR_SESSION_TICKET_A;
         } else {
-          ssl->state = SSL3_ST_CR_CERT_A;
+          hs->state = SSL3_ST_CR_CERT_A;
         }
         break;
 
@@ -268,7 +268,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CR_CERT_STATUS_A;
+        hs->state = SSL3_ST_CR_CERT_STATUS_A;
         break;
 
       case SSL3_ST_CR_CERT_STATUS_A:
@@ -280,7 +280,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
+        hs->state = SSL3_ST_VERIFY_SERVER_CERT;
         break;
 
       case SSL3_ST_VERIFY_SERVER_CERT:
@@ -292,7 +292,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CR_KEY_EXCH_A;
+        hs->state = SSL3_ST_CR_KEY_EXCH_A;
         break;
 
       case SSL3_ST_CR_KEY_EXCH_A:
@@ -300,7 +300,7 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL3_ST_CR_CERT_REQ_A;
+        hs->state = SSL3_ST_CR_CERT_REQ_A;
         break;
 
       case SSL3_ST_CR_CERT_REQ_A:
@@ -312,7 +312,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CR_SRVR_DONE_A;
+        hs->state = SSL3_ST_CR_SRVR_DONE_A;
         break;
 
       case SSL3_ST_CR_SRVR_DONE_A:
@@ -321,7 +321,7 @@
           goto end;
         }
         ssl->method->received_flight(ssl);
-        ssl->state = SSL3_ST_CW_CERT_A;
+        hs->state = SSL3_ST_CW_CERT_A;
         break;
 
       case SSL3_ST_CW_CERT_A:
@@ -334,7 +334,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CW_KEY_EXCH_A;
+        hs->state = SSL3_ST_CW_KEY_EXCH_A;
         break;
 
       case SSL3_ST_CW_KEY_EXCH_A:
@@ -343,7 +343,7 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL3_ST_CW_CERT_VRFY_A;
+        hs->state = SSL3_ST_CW_CERT_VRFY_A;
         break;
 
       case SSL3_ST_CW_CERT_VRFY_A:
@@ -357,7 +357,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CW_CHANGE;
+        hs->state = SSL3_ST_CW_CHANGE;
         break;
 
       case SSL3_ST_CW_CHANGE:
@@ -366,7 +366,7 @@
           goto end;
         }
 
-        ssl->state = SSL3_ST_CW_NEXT_PROTO_A;
+        hs->state = SSL3_ST_CW_NEXT_PROTO_A;
 
         if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
           ret = -1;
@@ -385,7 +385,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
+        hs->state = SSL3_ST_CW_CHANNEL_ID_A;
         break;
 
       case SSL3_ST_CW_CHANNEL_ID_A:
@@ -398,7 +398,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CW_FINISHED_A;
+        hs->state = SSL3_ST_CW_FINISHED_A;
         break;
 
       case SSL3_ST_CW_FINISHED_A:
@@ -408,10 +408,10 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL3_ST_CW_FLUSH;
+        hs->state = SSL3_ST_CW_FLUSH;
 
         if (ssl->session != NULL) {
-          ssl->s3->tmp.next_state = SSL_ST_OK;
+          hs->next_state = SSL_ST_OK;
         } else {
           /* This is a non-resumption handshake. If it involves ChannelID, then
            * record the handshake hashes at this point in the session so that
@@ -426,15 +426,15 @@
               /* No False Start on renegotiation (would complicate the state
                * machine). */
               !ssl->s3->initial_handshake_complete) {
-            ssl->s3->tmp.next_state = SSL3_ST_FALSE_START;
+            hs->next_state = SSL3_ST_FALSE_START;
           } else {
-            ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
+            hs->next_state = SSL3_ST_CR_SESSION_TICKET_A;
           }
         }
         break;
 
       case SSL3_ST_FALSE_START:
-        ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
+        hs->state = SSL3_ST_CR_SESSION_TICKET_A;
         hs->in_false_start = 1;
 
         ssl_free_wbio_buffer(ssl);
@@ -450,7 +450,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_CR_CHANGE;
+        hs->state = SSL3_ST_CR_CHANGE;
         break;
 
       case SSL3_ST_CR_CHANGE:
@@ -463,7 +463,7 @@
           ret = -1;
           goto end;
         }
-        ssl->state = SSL3_ST_CR_FINISHED_A;
+        hs->state = SSL3_ST_CR_FINISHED_A;
         break;
 
       case SSL3_ST_CR_FINISHED_A:
@@ -474,9 +474,9 @@
         ssl->method->received_flight(ssl);
 
         if (ssl->session != NULL) {
-          ssl->state = SSL3_ST_CW_CHANGE;
+          hs->state = SSL3_ST_CW_CHANGE;
         } else {
-          ssl->state = SSL_ST_OK;
+          hs->state = SSL_ST_OK;
         }
         break;
 
@@ -486,8 +486,8 @@
           ret = -1;
           goto end;
         }
-        ssl->state = ssl->s3->tmp.next_state;
-        if (ssl->state != SSL_ST_OK) {
+        hs->state = hs->next_state;
+        if (hs->state != SSL_ST_OK) {
           ssl->method->expect_flight(ssl);
         }
         break;
@@ -497,7 +497,7 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL_ST_OK;
+        hs->state = SSL_ST_OK;
         break;
 
       case SSL_ST_OK:
@@ -516,7 +516,7 @@
           if (ssl->s3->established_session == NULL) {
             /* Do not stay in SSL_ST_OK, to avoid confusing |SSL_in_init|
              * callers. */
-            ssl->state = SSL_ST_ERROR;
+            hs->state = SSL_ST_ERROR;
             skip = 1;
             ret = -1;
             goto end;
@@ -552,11 +552,11 @@
         goto end;
     }
 
-    if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
-      int new_state = ssl->state;
-      ssl->state = state;
+    if (!ssl->s3->tmp.reuse_message && !skip && hs->state != state) {
+      int new_state = hs->state;
+      hs->state = state;
       ssl_do_info_callback(ssl, SSL_CB_CONNECT_LOOP, 1);
-      ssl->state = new_state;
+      hs->state = new_state;
     }
     skip = 0;
   }
@@ -722,7 +722,7 @@
 
 static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
+  if (hs->state == SSL3_ST_CW_CLNT_HELLO_B) {
     return ssl->method->write_message(ssl);
   }
 
@@ -739,7 +739,7 @@
   }
 
   uint16_t max_wire_version = ssl->method->version_to_wire(max_version);
-  assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A);
+  assert(hs->state == SSL3_ST_CW_CLNT_HELLO_A);
   if (!ssl->s3->have_version) {
     ssl->version = max_wire_version;
   }
@@ -778,7 +778,7 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_CW_CLNT_HELLO_B;
+  hs->state = SSL3_ST_CW_CLNT_HELLO_B;
   return ssl->method->write_message(ssl);
 }
 
@@ -888,7 +888,7 @@
   }
 
   if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
-    ssl->state = SSL_ST_TLS13;
+    hs->state = SSL_ST_TLS13;
     hs->do_tls13_handshake = tls13_client_handshake;
     return 1;
   }
@@ -1458,10 +1458,10 @@
 
 static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_CW_CERT_B) {
+  if (hs->state == SSL3_ST_CW_CERT_B) {
     return ssl->method->write_message(ssl);
   }
-  assert(ssl->state == SSL3_ST_CW_CERT_A);
+  assert(hs->state == SSL3_ST_CW_CERT_A);
 
   /* Call cert_cb to update the certificate. */
   if (ssl->cert->cert_cb) {
@@ -1492,7 +1492,7 @@
   if (!ssl3_output_cert_chain(ssl)) {
     return -1;
   }
-  ssl->state = SSL3_ST_CW_CERT_B;
+  hs->state = SSL3_ST_CW_CERT_B;
   return ssl->method->write_message(ssl);
 }
 
@@ -1501,10 +1501,10 @@
 
 static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
+  if (hs->state == SSL3_ST_CW_KEY_EXCH_B) {
     return ssl->method->write_message(ssl);
   }
-  assert(ssl->state == SSL3_ST_CW_KEY_EXCH_A);
+  assert(hs->state == SSL3_ST_CW_KEY_EXCH_A);
 
   uint8_t *pms = NULL;
   size_t pms_len = 0;
@@ -1672,7 +1672,7 @@
   if (!ssl_complete_message(ssl, &cbb)) {
     goto err;
   }
-  ssl->state = SSL3_ST_CW_KEY_EXCH_B;
+  hs->state = SSL3_ST_CW_KEY_EXCH_B;
 
   ssl->s3->new_session->master_key_length =
       tls1_generate_master_secret(ssl, ssl->s3->new_session->master_key, pms,
@@ -1698,7 +1698,7 @@
 
 static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
+  if (hs->state == SSL3_ST_CW_CERT_VRFY_C) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1732,7 +1732,7 @@
 
   size_t sig_len = max_sig_len;
   enum ssl_private_key_result_t sign_result;
-  if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) {
+  if (hs->state == SSL3_ST_CW_CERT_VRFY_A) {
     /* The SSL3 construction for CertificateVerify does not decompose into a
      * single final digest and signature, and must be special-cased. */
     if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
@@ -1771,7 +1771,7 @@
     /* The handshake buffer is no longer necessary. */
     ssl3_free_handshake_buffer(ssl);
   } else {
-    assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B);
+    assert(hs->state == SSL3_ST_CW_CERT_VRFY_B);
     sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
   }
 
@@ -1782,7 +1782,7 @@
       goto err;
     case ssl_private_key_retry:
       ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-      ssl->state = SSL3_ST_CW_CERT_VRFY_B;
+      hs->state = SSL3_ST_CW_CERT_VRFY_B;
       goto err;
   }
 
@@ -1791,7 +1791,7 @@
     goto err;
   }
 
-  ssl->state = SSL3_ST_CW_CERT_VRFY_C;
+  hs->state = SSL3_ST_CW_CERT_VRFY_C;
   return ssl->method->write_message(ssl);
 
 err:
@@ -1801,11 +1801,11 @@
 
 static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
+  if (hs->state == SSL3_ST_CW_NEXT_PROTO_B) {
     return ssl->method->write_message(ssl);
   }
 
-  assert(ssl->state == SSL3_ST_CW_NEXT_PROTO_A);
+  assert(hs->state == SSL3_ST_CW_NEXT_PROTO_A);
 
   static const uint8_t kZero[32] = {0};
   size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
@@ -1823,17 +1823,17 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_CW_NEXT_PROTO_B;
+  hs->state = SSL3_ST_CW_NEXT_PROTO_B;
   return ssl->method->write_message(ssl);
 }
 
 static int ssl3_send_channel_id(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
+  if (hs->state == SSL3_ST_CW_CHANNEL_ID_B) {
     return ssl->method->write_message(ssl);
   }
 
-  assert(ssl->state == SSL3_ST_CW_CHANNEL_ID_A);
+  assert(hs->state == SSL3_ST_CW_CHANNEL_ID_A);
 
   if (!ssl_do_channel_id_callback(ssl)) {
     return -1;
@@ -1853,7 +1853,7 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_CW_CHANNEL_ID_B;
+  hs->state = SSL3_ST_CW_CHANNEL_ID_B;
   return ssl->method->write_message(ssl);
 }
 
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index 628f2c2..5121f99 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -195,11 +195,11 @@
   assert(ssl->server);
 
   for (;;) {
-    state = ssl->state;
+    state = hs->state;
 
-    switch (ssl->state) {
+    switch (hs->state) {
       case SSL_ST_INIT:
-        ssl->state = SSL_ST_ACCEPT;
+        hs->state = SSL_ST_ACCEPT;
         skip = 1;
         break;
 
@@ -219,7 +219,7 @@
           goto end;
         }
 
-        ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
+        hs->state = SSL3_ST_SR_CLNT_HELLO_A;
         break;
 
       case SSL3_ST_SR_CLNT_HELLO_A:
@@ -228,14 +228,14 @@
       case SSL3_ST_SR_CLNT_HELLO_D:
       case SSL3_ST_SR_CLNT_HELLO_E:
         ret = ssl3_get_client_hello(hs);
-        if (ssl->state == SSL_ST_TLS13) {
+        if (hs->state == SSL_ST_TLS13) {
           break;
         }
         if (ret <= 0) {
           goto end;
         }
         ssl->method->received_flight(ssl);
-        ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
+        hs->state = SSL3_ST_SW_SRVR_HELLO_A;
         break;
 
       case SSL3_ST_SW_SRVR_HELLO_A:
@@ -245,9 +245,9 @@
           goto end;
         }
         if (ssl->session != NULL) {
-          ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
+          hs->state = SSL3_ST_SW_SESSION_TICKET_A;
         } else {
-          ssl->state = SSL3_ST_SW_CERT_A;
+          hs->state = SSL3_ST_SW_CERT_A;
         }
         break;
 
@@ -261,7 +261,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_SW_CERT_STATUS_A;
+        hs->state = SSL3_ST_SW_CERT_STATUS_A;
         break;
 
       case SSL3_ST_SW_CERT_STATUS_A:
@@ -274,7 +274,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_SW_KEY_EXCH_A;
+        hs->state = SSL3_ST_SW_KEY_EXCH_A;
         break;
 
       case SSL3_ST_SW_KEY_EXCH_A:
@@ -293,7 +293,7 @@
           skip = 1;
         }
 
-        ssl->state = SSL3_ST_SW_CERT_REQ_A;
+        hs->state = SSL3_ST_SW_CERT_REQ_A;
         break;
 
       case SSL3_ST_SW_CERT_REQ_A:
@@ -306,7 +306,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_SW_SRVR_DONE_A;
+        hs->state = SSL3_ST_SW_SRVR_DONE_A;
         break;
 
       case SSL3_ST_SW_SRVR_DONE_A:
@@ -315,8 +315,8 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
-        ssl->state = SSL3_ST_SW_FLUSH;
+        hs->next_state = SSL3_ST_SR_CERT_A;
+        hs->state = SSL3_ST_SW_FLUSH;
         break;
 
       case SSL3_ST_SR_CERT_A:
@@ -326,7 +326,7 @@
             goto end;
           }
         }
-        ssl->state = SSL3_ST_SR_KEY_EXCH_A;
+        hs->state = SSL3_ST_SR_KEY_EXCH_A;
         break;
 
       case SSL3_ST_SR_KEY_EXCH_A:
@@ -335,7 +335,7 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL3_ST_SR_CERT_VRFY_A;
+        hs->state = SSL3_ST_SR_CERT_VRFY_A;
         break;
 
       case SSL3_ST_SR_CERT_VRFY_A:
@@ -344,7 +344,7 @@
           goto end;
         }
 
-        ssl->state = SSL3_ST_SR_CHANGE;
+        hs->state = SSL3_ST_SR_CHANGE;
         break;
 
       case SSL3_ST_SR_CHANGE:
@@ -358,7 +358,7 @@
           goto end;
         }
 
-        ssl->state = SSL3_ST_SR_NEXT_PROTO_A;
+        hs->state = SSL3_ST_SR_NEXT_PROTO_A;
         break;
 
       case SSL3_ST_SR_NEXT_PROTO_A:
@@ -370,7 +370,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
+        hs->state = SSL3_ST_SR_CHANNEL_ID_A;
         break;
 
       case SSL3_ST_SR_CHANNEL_ID_A:
@@ -382,7 +382,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_SR_FINISHED_A;
+        hs->state = SSL3_ST_SR_FINISHED_A;
         break;
 
       case SSL3_ST_SR_FINISHED_A:
@@ -393,9 +393,9 @@
 
         ssl->method->received_flight(ssl);
         if (ssl->session != NULL) {
-          ssl->state = SSL_ST_OK;
+          hs->state = SSL_ST_OK;
         } else {
-          ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
+          hs->state = SSL3_ST_SW_SESSION_TICKET_A;
         }
 
         /* If this is a full handshake with ChannelID then record the handshake
@@ -419,7 +419,7 @@
         } else {
           skip = 1;
         }
-        ssl->state = SSL3_ST_SW_CHANGE;
+        hs->state = SSL3_ST_SW_CHANGE;
         break;
 
       case SSL3_ST_SW_CHANGE:
@@ -427,7 +427,7 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL3_ST_SW_FINISHED_A;
+        hs->state = SSL3_ST_SW_FINISHED_A;
 
         if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
           ret = -1;
@@ -442,11 +442,11 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL3_ST_SW_FLUSH;
+        hs->state = SSL3_ST_SW_FLUSH;
         if (ssl->session != NULL) {
-          ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
+          hs->next_state = SSL3_ST_SR_CHANGE;
         } else {
-          ssl->s3->tmp.next_state = SSL_ST_OK;
+          hs->next_state = SSL_ST_OK;
         }
         break;
 
@@ -457,8 +457,8 @@
           goto end;
         }
 
-        ssl->state = ssl->s3->tmp.next_state;
-        if (ssl->state != SSL_ST_OK) {
+        hs->state = hs->next_state;
+        if (hs->state != SSL_ST_OK) {
           ssl->method->expect_flight(ssl);
         }
         break;
@@ -468,7 +468,7 @@
         if (ret <= 0) {
           goto end;
         }
-        ssl->state = SSL_ST_OK;
+        hs->state = SSL_ST_OK;
         break;
 
       case SSL_ST_OK:
@@ -510,11 +510,11 @@
         goto end;
     }
 
-    if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
-      int new_state = ssl->state;
-      ssl->state = state;
+    if (!ssl->s3->tmp.reuse_message && !skip && hs->state != state) {
+      int new_state = hs->state;
+      hs->state = state;
       ssl_do_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 1);
-      ssl->state = new_state;
+      hs->state = new_state;
     }
     skip = 0;
   }
@@ -819,7 +819,7 @@
   int ret = -1;
   SSL_SESSION *session = NULL;
 
-  if (ssl->state == SSL3_ST_SR_CLNT_HELLO_A) {
+  if (hs->state == SSL3_ST_SR_CLNT_HELLO_A) {
     /* The first time around, read the ClientHello. */
     int msg_ret = ssl->method->ssl_get_message(ssl, SSL3_MT_CLIENT_HELLO,
                                                ssl_hash_message);
@@ -827,7 +827,7 @@
       return msg_ret;
     }
 
-    ssl->state = SSL3_ST_SR_CLNT_HELLO_B;
+    hs->state = SSL3_ST_SR_CLNT_HELLO_B;
   }
 
   SSL_CLIENT_HELLO client_hello;
@@ -838,10 +838,10 @@
     goto f_err;
   }
 
-  if (ssl->state == SSL3_ST_SR_CLNT_HELLO_B) {
+  if (hs->state == SSL3_ST_SR_CLNT_HELLO_B) {
     /* Unlike other callbacks, the early callback is not run a second time if
      * paused. */
-    ssl->state = SSL3_ST_SR_CLNT_HELLO_C;
+    hs->state = SSL3_ST_SR_CLNT_HELLO_C;
 
     /* Run the early callback. */
     if (ssl->ctx->select_certificate_cb != NULL) {
@@ -869,13 +869,13 @@
     }
 
     if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
-      ssl->state = SSL_ST_TLS13;
+      hs->state = SSL_ST_TLS13;
       hs->do_tls13_handshake = tls13_server_handshake;
       return 1;
     }
   }
 
-  if (ssl->state == SSL3_ST_SR_CLNT_HELLO_C) {
+  if (hs->state == SSL3_ST_SR_CLNT_HELLO_C) {
     /* Load the client random. */
     if (client_hello.random_len != SSL3_RANDOM_SIZE) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
@@ -898,10 +898,10 @@
       goto err;
     }
 
-    ssl->state = SSL3_ST_SR_CLNT_HELLO_D;
+    hs->state = SSL3_ST_SR_CLNT_HELLO_D;
   }
 
-  if (ssl->state == SSL3_ST_SR_CLNT_HELLO_D) {
+  if (hs->state == SSL3_ST_SR_CLNT_HELLO_D) {
     /* Call |cert_cb| to update server certificates if required. */
     if (ssl->cert->cert_cb != NULL) {
       int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
@@ -926,10 +926,10 @@
       goto f_err;
     }
 
-    ssl->state = SSL3_ST_SR_CLNT_HELLO_E;
+    hs->state = SSL3_ST_SR_CLNT_HELLO_E;
   }
 
-  assert(ssl->state == SSL3_ST_SR_CLNT_HELLO_E);
+  assert(hs->state == SSL3_ST_SR_CLNT_HELLO_E);
 
   /* Determine whether we are doing session resumption. */
   int tickets_supported = 0, renew_ticket = 0;
@@ -1052,11 +1052,11 @@
 
 static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) {
+  if (hs->state == SSL3_ST_SW_SRVR_HELLO_B) {
     return ssl->method->write_message(ssl);
   }
 
-  assert(ssl->state == SSL3_ST_SW_SRVR_HELLO_A);
+  assert(hs->state == SSL3_ST_SW_SRVR_HELLO_A);
 
   /* We only accept ChannelIDs on connections with ECDHE in order to avoid a
    * known attack while we fix ChannelID itself. */
@@ -1107,13 +1107,13 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_SW_SRVR_HELLO_B;
+  hs->state = SSL3_ST_SW_SRVR_HELLO_B;
   return ssl->method->write_message(ssl);
 }
 
 static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_CERT_B) {
+  if (hs->state == SSL3_ST_SW_CERT_B) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1125,13 +1125,13 @@
   if (!ssl3_output_cert_chain(ssl)) {
     return 0;
   }
-  ssl->state = SSL3_ST_SW_CERT_B;
+  hs->state = SSL3_ST_SW_CERT_B;
   return ssl->method->write_message(ssl);
 }
 
 static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_CERT_STATUS_B) {
+  if (hs->state == SSL3_ST_SW_CERT_STATUS_B) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1148,13 +1148,13 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_SW_CERT_STATUS_B;
+  hs->state = SSL3_ST_SW_CERT_STATUS_B;
   return ssl->method->write_message(ssl);
 }
 
 static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) {
+  if (hs->state == SSL3_ST_SW_KEY_EXCH_C) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1162,7 +1162,7 @@
   CBB_zero(&cbb);
 
   /* Put together the parameters. */
-  if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
+  if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
     uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
     uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
 
@@ -1275,7 +1275,7 @@
 
     size_t sig_len;
     enum ssl_private_key_result_t sign_result;
-    if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
+    if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
       CBB transcript;
       uint8_t *transcript_data;
       size_t transcript_len;
@@ -1299,7 +1299,7 @@
                                          transcript_len);
       OPENSSL_free(transcript_data);
     } else {
-      assert(ssl->state == SSL3_ST_SW_KEY_EXCH_B);
+      assert(hs->state == SSL3_ST_SW_KEY_EXCH_B);
       sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
     }
 
@@ -1313,7 +1313,7 @@
         goto err;
       case ssl_private_key_retry:
         ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-        ssl->state = SSL3_ST_SW_KEY_EXCH_B;
+        hs->state = SSL3_ST_SW_KEY_EXCH_B;
         goto err;
     }
   }
@@ -1326,7 +1326,7 @@
   hs->server_params = NULL;
   hs->server_params_len = 0;
 
-  ssl->state = SSL3_ST_SW_KEY_EXCH_C;
+  hs->state = SSL3_ST_SW_KEY_EXCH_C;
   return ssl->method->write_message(ssl);
 
 err:
@@ -1374,7 +1374,7 @@
 
 static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_CERT_REQ_B) {
+  if (hs->state == SSL3_ST_SW_CERT_REQ_B) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1405,7 +1405,7 @@
     goto err;
   }
 
-  ssl->state = SSL3_ST_SW_CERT_REQ_B;
+  hs->state = SSL3_ST_SW_CERT_REQ_B;
   return ssl->method->write_message(ssl);
 
 err:
@@ -1416,7 +1416,7 @@
 
 static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_SRVR_DONE_B) {
+  if (hs->state == SSL3_ST_SW_SRVR_DONE_B) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1428,7 +1428,7 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_SW_SRVR_DONE_B;
+  hs->state = SSL3_ST_SW_SRVR_DONE_B;
   return ssl->method->write_message(ssl);
 }
 
@@ -1545,7 +1545,7 @@
   unsigned psk_len = 0;
   uint8_t psk[PSK_MAX_PSK_LEN];
 
-  if (ssl->state == SSL3_ST_SR_KEY_EXCH_A) {
+  if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
     int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE,
                                            ssl_hash_message);
     if (ret <= 0) {
@@ -1617,7 +1617,7 @@
 
     enum ssl_private_key_result_t decrypt_result;
     size_t decrypt_len;
-    if (ssl->state == SSL3_ST_SR_KEY_EXCH_A) {
+    if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
       if (!ssl_has_private_key(ssl) ||
           ssl_private_key_type(ssl) != NID_rsaEncryption) {
         al = SSL_AD_HANDSHAKE_FAILURE;
@@ -1645,7 +1645,7 @@
           CBS_data(&encrypted_premaster_secret),
           CBS_len(&encrypted_premaster_secret));
     } else {
-      assert(ssl->state == SSL3_ST_SR_KEY_EXCH_B);
+      assert(hs->state == SSL3_ST_SR_KEY_EXCH_B);
       /* Complete async decrypt. */
       decrypt_result =
           ssl_private_key_complete(ssl, decrypt_buf, &decrypt_len, rsa_size);
@@ -1658,7 +1658,7 @@
         goto err;
       case ssl_private_key_retry:
         ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-        ssl->state = SSL3_ST_SR_KEY_EXCH_B;
+        hs->state = SSL3_ST_SR_KEY_EXCH_B;
         goto err;
     }
 
@@ -1962,7 +1962,7 @@
 
 static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == SSL3_ST_SW_SESSION_TICKET_B) {
+  if (hs->state == SSL3_ST_SW_SESSION_TICKET_B) {
     return ssl->method->write_message(ssl);
   }
 
@@ -1999,6 +1999,6 @@
     return -1;
   }
 
-  ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
+  hs->state = SSL3_ST_SW_SESSION_TICKET_B;
   return ssl->method->write_message(ssl);
 }
diff --git a/ssl/internal.h b/ssl/internal.h
index 69ea489..3b2f194 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -877,6 +877,12 @@
    * or |ssl_hs_ok| if none. */
   enum ssl_hs_wait_t wait;
 
+  /* state contains one of the SSL3_ST_* values. */
+  int state;
+
+  /* next_state is used when SSL_ST_FLUSH_DATA is entered */
+  int next_state;
+
   /* tls13_state is the internal state for the TLS 1.3 handshake. Its values
    * depend on |do_tls13_handshake| but the starting state is always zero. */
   int tls13_state;
@@ -1491,9 +1497,6 @@
 
     int message_type;
 
-    /* used when SSL_ST_FLUSH_DATA is entered */
-    int next_state;
-
     int reuse_message;
 
     uint8_t new_mac_secret_len;
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index d775cca..eeccab1 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -139,6 +139,7 @@
   memset(hs, 0, sizeof(SSL_HANDSHAKE));
   hs->ssl = ssl;
   hs->wait = ssl_hs_ok;
+  hs->state = SSL_ST_INIT;
   return hs;
 }
 
@@ -262,7 +263,7 @@
 
 int ssl3_send_finished(SSL_HANDSHAKE *hs, int a, int b) {
   SSL *const ssl = hs->ssl;
-  if (ssl->state == b) {
+  if (hs->state == b) {
     return ssl->method->write_message(ssl);
   }
 
@@ -306,7 +307,7 @@
     return -1;
   }
 
-  ssl->state = b;
+  hs->state = b;
   return ssl->method->write_message(ssl);
 }
 
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 2b73409..336689a 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -390,8 +390,6 @@
   ssl->min_version = ctx->min_version;
   ssl->max_version = ctx->max_version;
 
-  ssl->state = SSL_ST_INIT;
-
   /* RFC 6347 states that implementations SHOULD use an initial timer value of
    * 1 second. */
   ssl->initial_timeout_duration_ms = 1000;
@@ -722,7 +720,6 @@
   }
 
   ssl->s3->total_renegotiations++;
-  ssl->state = SSL_ST_INIT;
   return 1;
 
 no_renegotiation:
@@ -2297,7 +2294,14 @@
   return ssl->info_callback;
 }
 
-int SSL_state(const SSL *ssl) { return ssl->state; }
+int SSL_state(const SSL *ssl) {
+  if (ssl->s3->hs == NULL) {
+    assert(ssl->s3->initial_handshake_complete);
+    return SSL_ST_OK;
+  }
+
+  return ssl->s3->hs->state;
+}
 
 void SSL_set_state(SSL *ssl, int state) { }
 
@@ -2613,11 +2617,11 @@
 }
 
 int SSL_is_init_finished(const SSL *ssl) {
-  return ssl->state == SSL_ST_OK;
+  return SSL_state(ssl) == SSL_ST_OK;
 }
 
 int SSL_in_init(const SSL *ssl) {
-  return (ssl->state & SSL_ST_INIT) != 0;
+  return (SSL_state(ssl) & SSL_ST_INIT) != 0;
 }
 
 int SSL_in_false_start(const SSL *ssl) {
@@ -2886,7 +2890,6 @@
    * naturally reset at the right points between |SSL_new|, |SSL_clear|, and
    * |ssl3_new|. */
 
-  ssl->state = SSL_ST_INIT;
   ssl->rwstate = SSL_NOTHING;
 
   BUF_MEM_free(ssl->init_buf);
diff --git a/ssl/ssl_session.c b/ssl/ssl_session.c
index 1e6e21b..98d101c 100644
--- a/ssl/ssl_session.c
+++ b/ssl/ssl_session.c
@@ -837,7 +837,7 @@
 
 int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
   /* SSL_set_session may only be called before the handshake has started. */
-  if (ssl->state != SSL_ST_INIT || ssl->s3->initial_handshake_complete) {
+  if (SSL_state(ssl) != SSL_ST_INIT || ssl->s3->initial_handshake_complete) {
     abort();
   }
 
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index 51f6fd3..d657788 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -87,7 +87,7 @@
 
 
 const char *SSL_state_string_long(const SSL *ssl) {
-  switch (ssl->state) {
+  switch (SSL_state(ssl)) {
     case SSL_ST_ACCEPT:
       return "before accept initialization";
 
@@ -243,7 +243,7 @@
 }
 
 const char *SSL_state_string(const SSL *ssl) {
-  switch (ssl->state) {
+  switch (SSL_state(ssl)) {
     case SSL_ST_ACCEPT:
       return "AINIT ";