Match state machine functions with new calling convention.

This cuts down on a lot of unchecked ssl->s3->hs accesses. Next is
probably the mass of extensions callbacks, and then we can play
whack-a-mole with git grep.

Change-Id: I81c506ea25c2569a51ceda903853465b8b567b0f
Reviewed-on: https://boringssl-review.googlesource.com/12237
Reviewed-by: Steven Valdez <svaldez@google.com>
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/ssl/handshake_client.c b/ssl/handshake_client.c
index 8d503a5..c981de0 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -170,21 +170,21 @@
 #include "internal.h"
 
 
-static int ssl3_send_client_hello(SSL *ssl);
-static int dtls1_get_hello_verify(SSL *ssl);
-static int ssl3_get_server_hello(SSL *ssl);
-static int ssl3_get_server_certificate(SSL *ssl);
-static int ssl3_get_cert_status(SSL *ssl);
-static int ssl3_verify_server_cert(SSL *ssl);
-static int ssl3_get_server_key_exchange(SSL *ssl);
-static int ssl3_get_certificate_request(SSL *ssl);
-static int ssl3_get_server_hello_done(SSL *ssl);
-static int ssl3_send_client_certificate(SSL *ssl);
-static int ssl3_send_client_key_exchange(SSL *ssl);
-static int ssl3_send_cert_verify(SSL *ssl);
-static int ssl3_send_next_proto(SSL *ssl);
-static int ssl3_send_channel_id(SSL *ssl);
-static int ssl3_get_new_session_ticket(SSL *ssl);
+static int ssl3_send_client_hello(SSL_HANDSHAKE *hs);
+static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_hello(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_get_cert_status(SSL_HANDSHAKE *hs);
+static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs);
+static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs);
+static int ssl3_send_next_proto(SSL_HANDSHAKE *hs);
+static int ssl3_send_channel_id(SSL_HANDSHAKE *hs);
+static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs);
 
 int ssl3_connect(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
@@ -216,7 +216,7 @@
 
       case SSL3_ST_CW_CLNT_HELLO_A:
       case SSL3_ST_CW_CLNT_HELLO_B:
-        ret = ssl3_send_client_hello(ssl);
+        ret = ssl3_send_client_hello(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -231,7 +231,7 @@
 
       case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
         assert(SSL_is_dtls(ssl));
-        ret = dtls1_get_hello_verify(ssl);
+        ret = dtls1_get_hello_verify(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -244,7 +244,7 @@
         break;
 
       case SSL3_ST_CR_SRVR_HELLO_A:
-        ret = ssl3_get_server_hello(ssl);
+        ret = ssl3_get_server_hello(hs);
         if (ssl->state == SSL_ST_TLS13) {
           break;
         }
@@ -261,7 +261,7 @@
 
       case SSL3_ST_CR_CERT_A:
         if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_get_server_certificate(ssl);
+          ret = ssl3_get_server_certificate(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -273,7 +273,7 @@
 
       case SSL3_ST_CR_CERT_STATUS_A:
         if (hs->certificate_status_expected) {
-          ret = ssl3_get_cert_status(ssl);
+          ret = ssl3_get_cert_status(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -285,7 +285,7 @@
 
       case SSL3_ST_VERIFY_SERVER_CERT:
         if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_verify_server_cert(ssl);
+          ret = ssl3_verify_server_cert(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -296,7 +296,7 @@
         break;
 
       case SSL3_ST_CR_KEY_EXCH_A:
-        ret = ssl3_get_server_key_exchange(ssl);
+        ret = ssl3_get_server_key_exchange(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -305,7 +305,7 @@
 
       case SSL3_ST_CR_CERT_REQ_A:
         if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_get_certificate_request(ssl);
+          ret = ssl3_get_certificate_request(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -316,7 +316,7 @@
         break;
 
       case SSL3_ST_CR_SRVR_DONE_A:
-        ret = ssl3_get_server_hello_done(ssl);
+        ret = ssl3_get_server_hello_done(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -328,7 +328,7 @@
       case SSL3_ST_CW_CERT_B:
       case SSL3_ST_CW_CERT_C:
         if (hs->cert_request) {
-          ret = ssl3_send_client_certificate(ssl);
+          ret = ssl3_send_client_certificate(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -340,7 +340,7 @@
 
       case SSL3_ST_CW_KEY_EXCH_A:
       case SSL3_ST_CW_KEY_EXCH_B:
-        ret = ssl3_send_client_key_exchange(ssl);
+        ret = ssl3_send_client_key_exchange(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -351,7 +351,7 @@
       case SSL3_ST_CW_CERT_VRFY_B:
       case SSL3_ST_CW_CERT_VRFY_C:
         if (hs->cert_request) {
-          ret = ssl3_send_cert_verify(ssl);
+          ret = ssl3_send_cert_verify(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -379,7 +379,7 @@
       case SSL3_ST_CW_NEXT_PROTO_A:
       case SSL3_ST_CW_NEXT_PROTO_B:
         if (hs->next_proto_neg_seen) {
-          ret = ssl3_send_next_proto(ssl);
+          ret = ssl3_send_next_proto(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -392,7 +392,7 @@
       case SSL3_ST_CW_CHANNEL_ID_A:
       case SSL3_ST_CW_CHANNEL_ID_B:
         if (ssl->s3->tlsext_channel_id_valid) {
-          ret = ssl3_send_channel_id(ssl);
+          ret = ssl3_send_channel_id(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -404,7 +404,7 @@
 
       case SSL3_ST_CW_FINISHED_A:
       case SSL3_ST_CW_FINISHED_B:
-        ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A,
+        ret = ssl3_send_finished(hs, SSL3_ST_CW_FINISHED_A,
                                  SSL3_ST_CW_FINISHED_B);
         if (ret <= 0) {
           goto end;
@@ -444,7 +444,7 @@
 
       case SSL3_ST_CR_SESSION_TICKET_A:
         if (hs->ticket_expected) {
-          ret = ssl3_get_new_session_ticket(ssl);
+          ret = ssl3_get_new_session_ticket(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -468,7 +468,7 @@
         break;
 
       case SSL3_ST_CR_FINISHED_A:
-        ret = ssl3_get_finished(ssl);
+        ret = ssl3_get_finished(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -494,7 +494,7 @@
         break;
 
       case SSL_ST_TLS13:
-        ret = tls13_handshake(ssl);
+        ret = tls13_handshake(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -720,7 +720,8 @@
   return 0;
 }
 
-static int ssl3_send_client_hello(SSL *ssl) {
+static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
     return ssl->method->write_message(ssl);
   }
@@ -781,7 +782,8 @@
   return ssl->method->write_message(ssl);
 }
 
-static int dtls1_get_hello_verify(SSL *ssl) {
+static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int al;
   CBS hello_verify_request, cookie;
   uint16_t server_version;
@@ -823,7 +825,8 @@
   return -1;
 }
 
-static int ssl3_get_server_hello(SSL *ssl) {
+static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   CERT *ct = ssl->cert;
   int al = SSL_AD_INTERNAL_ERROR;
   CBS server_hello, server_random, session_id;
@@ -886,7 +889,7 @@
 
   if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
     ssl->state = SSL_ST_TLS13;
-    ssl->s3->hs->do_tls13_handshake = tls13_client_handshake;
+    hs->do_tls13_handshake = tls13_client_handshake;
     return 1;
   }
 
@@ -1027,7 +1030,8 @@
   return -1;
 }
 
-static int ssl3_get_server_certificate(SSL *ssl) {
+static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret =
       ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message);
   if (ret <= 0) {
@@ -1071,7 +1075,8 @@
   return -1;
 }
 
-static int ssl3_get_cert_status(SSL *ssl) {
+static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int al;
   CBS certificate_status, ocsp_response;
   uint8_t status_type;
@@ -1112,7 +1117,8 @@
   return -1;
 }
 
-static int ssl3_verify_server_cert(SSL *ssl) {
+static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
                              ssl->s3->new_session->x509_chain)) {
     return -1;
@@ -1121,7 +1127,8 @@
   return 1;
 }
 
-static int ssl3_get_server_key_exchange(SSL *ssl) {
+static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int al;
   EVP_PKEY *pkey = NULL;
   DH *dh = NULL;
@@ -1184,7 +1191,7 @@
      * empty hint. Having different capabilities is odd, so we interpret empty
      * and missing as identical. */
     if (CBS_len(&psk_identity_hint) != 0 &&
-        !CBS_strdup(&psk_identity_hint, &ssl->s3->hs->peer_psk_identity_hint)) {
+        !CBS_strdup(&psk_identity_hint, &hs->peer_psk_identity_hint)) {
       al = SSL_AD_INTERNAL_ERROR;
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto f_err;
@@ -1227,11 +1234,11 @@
       goto err;
     }
 
-    SSL_ECDH_CTX_init_for_dhe(&ssl->s3->hs->ecdh_ctx, dh);
+    SSL_ECDH_CTX_init_for_dhe(&hs->ecdh_ctx, dh);
     dh = NULL;
 
     /* Save the peer public key for later. */
-    if (!CBS_stow(&dh_Ys, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
+    if (!CBS_stow(&dh_Ys, &hs->peer_key, &hs->peer_key_len)) {
       goto err;
     }
   } else if (alg_k & SSL_kECDHE) {
@@ -1257,12 +1264,12 @@
     }
 
     /* Initialize ECDH and save the peer public key for later. */
-    if (!SSL_ECDH_CTX_init(&ssl->s3->hs->ecdh_ctx, group_id) ||
-        !CBS_stow(&point, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
+    if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+        !CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
       goto err;
     }
   } else if (alg_k & SSL_kCECPQ1) {
-    SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->hs->ecdh_ctx);
+    SSL_ECDH_CTX_init_for_cecpq1(&hs->ecdh_ctx);
     CBS key;
     if (!CBS_get_u16_length_prefixed(&server_key_exchange, &key)) {
       al = SSL_AD_DECODE_ERROR;
@@ -1270,7 +1277,7 @@
       goto f_err;
     }
 
-    if (!CBS_stow(&key, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
+    if (!CBS_stow(&key, &hs->peer_key, &hs->peer_key_len)) {
       goto err;
     }
   } else if (!(alg_k & SSL_kPSK)) {
@@ -1375,7 +1382,8 @@
   return -1;
 }
 
-static int ssl3_get_certificate_request(SSL *ssl) {
+static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int msg_ret = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message);
   if (msg_ret <= 0) {
     return msg_ret;
@@ -1406,8 +1414,8 @@
     return -1;
   }
 
-  if (!CBS_stow(&certificate_types, &ssl->s3->hs->certificate_types,
-                &ssl->s3->hs->num_certificate_types)) {
+  if (!CBS_stow(&certificate_types, &hs->certificate_types,
+                &hs->num_certificate_types)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return -1;
   }
@@ -1436,13 +1444,14 @@
     return -1;
   }
 
-  ssl->s3->hs->cert_request = 1;
-  sk_X509_NAME_pop_free(ssl->s3->hs->ca_names, X509_NAME_free);
-  ssl->s3->hs->ca_names = ca_sk;
+  hs->cert_request = 1;
+  sk_X509_NAME_pop_free(hs->ca_names, X509_NAME_free);
+  hs->ca_names = ca_sk;
   return 1;
 }
 
-static int ssl3_get_server_hello_done(SSL *ssl) {
+static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO_DONE,
                                          ssl_hash_message);
   if (ret <= 0) {
@@ -1459,7 +1468,8 @@
   return 1;
 }
 
-static int ssl3_send_client_certificate(SSL *ssl) {
+static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_CW_CERT_A) {
     /* Call cert_cb to update the certificate. */
     if (ssl->cert->cert_cb) {
@@ -1489,7 +1499,7 @@
     }
 
     if (!ssl_has_certificate(ssl)) {
-      ssl->s3->hs->cert_request = 0;
+      hs->cert_request = 0;
       /* Without a client certificate, the handshake buffer may be released. */
       ssl3_free_handshake_buffer(ssl);
 
@@ -1513,7 +1523,8 @@
 OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
                        SIZE_T_IS_SMALLER_THAN_UNSIGNED);
 
-static int ssl3_send_client_key_exchange(SSL *ssl) {
+static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
     return ssl->method->write_message(ssl);
   }
@@ -1541,9 +1552,9 @@
 
     char identity[PSK_MAX_IDENTITY_LEN + 1];
     memset(identity, 0, sizeof(identity));
-    psk_len = ssl->psk_client_callback(
-        ssl, ssl->s3->hs->peer_psk_identity_hint, identity, sizeof(identity),
-        psk, sizeof(psk));
+    psk_len =
+        ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint, identity,
+                                 sizeof(identity), psk, sizeof(psk));
     if (psk_len == 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1620,15 +1631,14 @@
   } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
     /* Generate a keypair and serialize the public half. */
     CBB child;
-    if (!SSL_ECDH_CTX_add_key(&ssl->s3->hs->ecdh_ctx, &body, &child)) {
+    if (!SSL_ECDH_CTX_add_key(&hs->ecdh_ctx, &body, &child)) {
       goto err;
     }
 
     /* Compute the premaster. */
     uint8_t alert;
-    if (!SSL_ECDH_CTX_accept(&ssl->s3->hs->ecdh_ctx, &child, &pms, &pms_len,
-                             &alert, ssl->s3->hs->peer_key,
-                             ssl->s3->hs->peer_key_len)) {
+    if (!SSL_ECDH_CTX_accept(&hs->ecdh_ctx, &child, &pms, &pms_len, &alert,
+                             hs->peer_key, hs->peer_key_len)) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
       goto err;
     }
@@ -1637,10 +1647,10 @@
     }
 
     /* The key exchange state may now be discarded. */
-    SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
-    OPENSSL_free(ssl->s3->hs->peer_key);
-    ssl->s3->hs->peer_key = NULL;
-    ssl->s3->hs->peer_key_len = 0;
+    SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+    OPENSSL_free(hs->peer_key);
+    hs->peer_key = NULL;
+    hs->peer_key_len = 0;
   } else if (alg_k & SSL_kPSK) {
     /* For plain PSK, other_secret is a block of 0s with the same length as
      * the pre-shared key. */
@@ -1710,7 +1720,8 @@
   return -1;
 }
 
-static int ssl3_send_cert_verify(SSL *ssl) {
+static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
     return ssl->method->write_message(ssl);
   }
@@ -1812,7 +1823,8 @@
   return -1;
 }
 
-static int ssl3_send_next_proto(SSL *ssl) {
+static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
     return ssl->method->write_message(ssl);
   }
@@ -1839,7 +1851,8 @@
   return ssl->method->write_message(ssl);
 }
 
-static int ssl3_send_channel_id(SSL *ssl) {
+static int ssl3_send_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
     return ssl->method->write_message(ssl);
   }
@@ -1868,7 +1881,8 @@
   return ssl->method->write_message(ssl);
 }
 
-static int ssl3_get_new_session_ticket(SSL *ssl) {
+static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_NEW_SESSION_TICKET,
                                          ssl_hash_message);
   if (ret <= 0) {
@@ -1890,7 +1904,7 @@
     /* RFC 5077 allows a server to change its mind and send no ticket after
      * negotiating the extension. The value of |ticket_expected| is checked in
      * |ssl_update_cache| so is cleared here to avoid an unnecessary update. */
-    ssl->s3->hs->ticket_expected = 0;
+    hs->ticket_expected = 0;
     return 1;
   }
 
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index ccf0e8b..9c21b12 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -171,19 +171,19 @@
 #include "../crypto/internal.h"
 
 
-static int ssl3_get_client_hello(SSL *ssl);
-static int ssl3_send_server_hello(SSL *ssl);
-static int ssl3_send_server_certificate(SSL *ssl);
-static int ssl3_send_certificate_status(SSL *ssl);
-static int ssl3_send_server_key_exchange(SSL *ssl);
-static int ssl3_send_certificate_request(SSL *ssl);
-static int ssl3_send_server_hello_done(SSL *ssl);
-static int ssl3_get_client_certificate(SSL *ssl);
-static int ssl3_get_client_key_exchange(SSL *ssl);
-static int ssl3_get_cert_verify(SSL *ssl);
-static int ssl3_get_next_proto(SSL *ssl);
-static int ssl3_get_channel_id(SSL *ssl);
-static int ssl3_send_new_session_ticket(SSL *ssl);
+static int ssl3_get_client_hello(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_hello(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs);
+static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs);
+static int ssl3_get_next_proto(SSL_HANDSHAKE *hs);
+static int ssl3_get_channel_id(SSL_HANDSHAKE *hs);
+static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs);
 
 int ssl3_accept(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
@@ -227,7 +227,7 @@
       case SSL3_ST_SR_CLNT_HELLO_C:
       case SSL3_ST_SR_CLNT_HELLO_D:
       case SSL3_ST_SR_CLNT_HELLO_E:
-        ret = ssl3_get_client_hello(ssl);
+        ret = ssl3_get_client_hello(hs);
         if (ssl->state == SSL_ST_TLS13) {
           break;
         }
@@ -240,7 +240,7 @@
 
       case SSL3_ST_SW_SRVR_HELLO_A:
       case SSL3_ST_SW_SRVR_HELLO_B:
-        ret = ssl3_send_server_hello(ssl);
+        ret = ssl3_send_server_hello(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -254,7 +254,7 @@
       case SSL3_ST_SW_CERT_A:
       case SSL3_ST_SW_CERT_B:
         if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_send_server_certificate(ssl);
+          ret = ssl3_send_server_certificate(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -267,7 +267,7 @@
       case SSL3_ST_SW_CERT_STATUS_A:
       case SSL3_ST_SW_CERT_STATUS_B:
         if (hs->certificate_status_expected) {
-          ret = ssl3_send_certificate_status(ssl);
+          ret = ssl3_send_certificate_status(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -285,7 +285,7 @@
         /* PSK ciphers send ServerKeyExchange if there is an identity hint. */
         if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
             ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
-          ret = ssl3_send_server_key_exchange(ssl);
+          ret = ssl3_send_server_key_exchange(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -299,7 +299,7 @@
       case SSL3_ST_SW_CERT_REQ_A:
       case SSL3_ST_SW_CERT_REQ_B:
         if (hs->cert_request) {
-          ret = ssl3_send_certificate_request(ssl);
+          ret = ssl3_send_certificate_request(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -311,7 +311,7 @@
 
       case SSL3_ST_SW_SRVR_DONE_A:
       case SSL3_ST_SW_SRVR_DONE_B:
-        ret = ssl3_send_server_hello_done(ssl);
+        ret = ssl3_send_server_hello_done(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -321,7 +321,7 @@
 
       case SSL3_ST_SR_CERT_A:
         if (hs->cert_request) {
-          ret = ssl3_get_client_certificate(ssl);
+          ret = ssl3_get_client_certificate(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -331,7 +331,7 @@
 
       case SSL3_ST_SR_KEY_EXCH_A:
       case SSL3_ST_SR_KEY_EXCH_B:
-        ret = ssl3_get_client_key_exchange(ssl);
+        ret = ssl3_get_client_key_exchange(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -339,7 +339,7 @@
         break;
 
       case SSL3_ST_SR_CERT_VRFY_A:
-        ret = ssl3_get_cert_verify(ssl);
+        ret = ssl3_get_cert_verify(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -363,7 +363,7 @@
 
       case SSL3_ST_SR_NEXT_PROTO_A:
         if (hs->next_proto_neg_seen) {
-          ret = ssl3_get_next_proto(ssl);
+          ret = ssl3_get_next_proto(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -375,7 +375,7 @@
 
       case SSL3_ST_SR_CHANNEL_ID_A:
         if (ssl->s3->tlsext_channel_id_valid) {
-          ret = ssl3_get_channel_id(ssl);
+          ret = ssl3_get_channel_id(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -386,7 +386,7 @@
         break;
 
       case SSL3_ST_SR_FINISHED_A:
-        ret = ssl3_get_finished(ssl);
+        ret = ssl3_get_finished(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -412,7 +412,7 @@
       case SSL3_ST_SW_SESSION_TICKET_A:
       case SSL3_ST_SW_SESSION_TICKET_B:
         if (hs->ticket_expected) {
-          ret = ssl3_send_new_session_ticket(ssl);
+          ret = ssl3_send_new_session_ticket(hs);
           if (ret <= 0) {
             goto end;
           }
@@ -437,7 +437,7 @@
 
       case SSL3_ST_SW_FINISHED_A:
       case SSL3_ST_SW_FINISHED_B:
-        ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
+        ret = ssl3_send_finished(hs, SSL3_ST_SW_FINISHED_A,
                                  SSL3_ST_SW_FINISHED_B);
         if (ret <= 0) {
           goto end;
@@ -464,7 +464,7 @@
         break;
 
       case SSL_ST_TLS13:
-        ret = tls13_handshake(ssl);
+        ret = tls13_handshake(hs);
         if (ret <= 0) {
           goto end;
         }
@@ -653,7 +653,8 @@
   return 0;
 }
 
-static int ssl3_get_client_hello(SSL *ssl) {
+static int ssl3_get_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   uint8_t al = SSL_AD_INTERNAL_ERROR;
   int ret = -1;
   SSL_SESSION *session = NULL;
@@ -709,7 +710,7 @@
 
     if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
       ssl->state = SSL_ST_TLS13;
-      ssl->s3->hs->do_tls13_handshake = tls13_server_handshake;
+      hs->do_tls13_handshake = tls13_server_handshake;
       return 1;
     }
   }
@@ -805,12 +806,12 @@
 
   if (session != NULL) {
     /* Use the old session. */
-    ssl->s3->hs->ticket_expected = renew_ticket;
+    hs->ticket_expected = renew_ticket;
     ssl->session = session;
     session = NULL;
     ssl->s3->session_reused = 1;
   } else {
-    ssl->s3->hs->ticket_expected = tickets_supported;
+    hs->ticket_expected = tickets_supported;
     ssl_set_session(ssl, NULL);
     if (!ssl_get_new_session(ssl, 1 /* server */)) {
       goto err;
@@ -834,8 +835,8 @@
     ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;
 
     /* On new sessions, stash the SNI value in the session. */
-    if (ssl->s3->hs->hostname != NULL) {
-      ssl->s3->new_session->tlsext_hostname = BUF_strdup(ssl->s3->hs->hostname);
+    if (hs->hostname != NULL) {
+      ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
       if (ssl->s3->new_session->tlsext_hostname == NULL) {
         al = SSL_AD_INTERNAL_ERROR;
         goto f_err;
@@ -843,18 +844,18 @@
     }
 
     /* Determine whether to request a client certificate. */
-    ssl->s3->hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+    hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
     /* Only request a certificate if Channel ID isn't negotiated. */
     if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
         ssl->s3->tlsext_channel_id_valid) {
-      ssl->s3->hs->cert_request = 0;
+      hs->cert_request = 0;
     }
     /* CertificateRequest may only be sent in certificate-based ciphers. */
     if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
-      ssl->s3->hs->cert_request = 0;
+      hs->cert_request = 0;
     }
 
-    if (!ssl->s3->hs->cert_request) {
+    if (!hs->cert_request) {
       /* OpenSSL returns X509_V_OK when no certificates are requested. This is
        * classed by them as a bug, but it's assumed by at least NGINX. */
       ssl->s3->new_session->verify_result = X509_V_OK;
@@ -873,7 +874,7 @@
   }
 
   /* Release the handshake buffer if client authentication isn't required. */
-  if (!ssl->s3->hs->cert_request) {
+  if (!hs->cert_request) {
     ssl3_free_handshake_buffer(ssl);
   }
 
@@ -889,7 +890,8 @@
   return ret;
 }
 
-static int ssl3_send_server_hello(SSL *ssl) {
+static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) {
     return ssl->method->write_message(ssl);
   }
@@ -949,7 +951,8 @@
   return ssl->method->write_message(ssl);
 }
 
-static int ssl3_send_server_certificate(SSL *ssl) {
+static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_SW_CERT_B) {
     return ssl->method->write_message(ssl);
   }
@@ -966,7 +969,8 @@
   return ssl->method->write_message(ssl);
 }
 
-static int ssl3_send_certificate_status(SSL *ssl) {
+static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_SW_CERT_STATUS_B) {
     return ssl->method->write_message(ssl);
   }
@@ -988,7 +992,8 @@
   return ssl->method->write_message(ssl);
 }
 
-static int ssl3_send_server_key_exchange(SSL *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) {
     return ssl->method->write_message(ssl);
   }
@@ -1036,13 +1041,13 @@
         goto err;
       }
 
-      SSL_ECDH_CTX_init_for_dhe(&ssl->s3->hs->ecdh_ctx, dh);
+      SSL_ECDH_CTX_init_for_dhe(&hs->ecdh_ctx, dh);
       if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
           !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
           !CBB_add_u16_length_prefixed(&cbb, &child) ||
           !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
           !CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
+          !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
         goto err;
       }
     } else if (alg_k & SSL_kECDHE) {
@@ -1056,25 +1061,24 @@
       ssl->s3->new_session->key_exchange_info = group_id;
 
       /* Set up ECDH, generate a key, and emit the public half. */
-      if (!SSL_ECDH_CTX_init(&ssl->s3->hs->ecdh_ctx, group_id) ||
+      if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
           !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
           !CBB_add_u16(&cbb, group_id) ||
           !CBB_add_u8_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
+          !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
         goto err;
       }
     } else if (alg_k & SSL_kCECPQ1) {
-      SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->hs->ecdh_ctx);
+      SSL_ECDH_CTX_init_for_cecpq1(&hs->ecdh_ctx);
       if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
+          !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
         goto err;
       }
     } else {
       assert(alg_k & SSL_kPSK);
     }
 
-    if (!CBB_finish(&cbb, &ssl->s3->hs->server_params,
-                    &ssl->s3->hs->server_params_len)) {
+    if (!CBB_finish(&cbb, &hs->server_params, &hs->server_params_len)) {
       goto err;
     }
   }
@@ -1083,8 +1087,7 @@
   CBB body;
   if (!ssl->method->init_message(ssl, &cbb, &body,
                                  SSL3_MT_SERVER_KEY_EXCHANGE) ||
-      !CBB_add_bytes(&body, ssl->s3->hs->server_params,
-                     ssl->s3->hs->server_params_len)) {
+      !CBB_add_bytes(&body, hs->server_params, hs->server_params_len)) {
     goto err;
   }
 
@@ -1123,11 +1126,13 @@
       uint8_t *transcript_data;
       size_t transcript_len;
       if (!CBB_init(&transcript,
-                    2*SSL3_RANDOM_SIZE + ssl->s3->hs->server_params_len) ||
-          !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
-          !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
-          !CBB_add_bytes(&transcript, ssl->s3->hs->server_params,
-                         ssl->s3->hs->server_params_len) ||
+                    2 * SSL3_RANDOM_SIZE + hs->server_params_len) ||
+          !CBB_add_bytes(&transcript, ssl->s3->client_random,
+                         SSL3_RANDOM_SIZE) ||
+          !CBB_add_bytes(&transcript, ssl->s3->server_random,
+                         SSL3_RANDOM_SIZE) ||
+          !CBB_add_bytes(&transcript, hs->server_params,
+                         hs->server_params_len) ||
           !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
         CBB_cleanup(&transcript);
         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
@@ -1163,9 +1168,9 @@
     goto err;
   }
 
-  OPENSSL_free(ssl->s3->hs->server_params);
-  ssl->s3->hs->server_params = NULL;
-  ssl->s3->hs->server_params_len = 0;
+  OPENSSL_free(hs->server_params);
+  hs->server_params = NULL;
+  hs->server_params_len = 0;
 
   ssl->state = SSL3_ST_SW_KEY_EXCH_C;
   return ssl->method->write_message(ssl);
@@ -1213,7 +1218,8 @@
   return 1;
 }
 
-static int ssl3_send_certificate_request(SSL *ssl) {
+static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_SW_CERT_REQ_B) {
     return ssl->method->write_message(ssl);
   }
@@ -1254,7 +1260,8 @@
   return -1;
 }
 
-static int ssl3_send_server_hello_done(SSL *ssl) {
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_SW_SRVR_DONE_B) {
     return ssl->method->write_message(ssl);
   }
@@ -1271,8 +1278,9 @@
   return ssl->method->write_message(ssl);
 }
 
-static int ssl3_get_client_certificate(SSL *ssl) {
-  assert(ssl->s3->hs->cert_request);
+static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  assert(hs->cert_request);
 
   int msg_ret = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message);
   if (msg_ret <= 0) {
@@ -1370,7 +1378,8 @@
   return -1;
 }
 
-static int ssl3_get_client_key_exchange(SSL *ssl) {
+static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int al;
   CBS client_key_exchange;
   uint32_t alg_k;
@@ -1553,8 +1562,7 @@
   } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
     /* Parse the ClientKeyExchange. */
     CBS peer_key;
-    if (!SSL_ECDH_CTX_get_key(&ssl->s3->hs->ecdh_ctx, &client_key_exchange,
-                              &peer_key) ||
+    if (!SSL_ECDH_CTX_get_key(&hs->ecdh_ctx, &client_key_exchange, &peer_key) ||
         CBS_len(&client_key_exchange) != 0) {
       al = SSL_AD_DECODE_ERROR;
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
@@ -1563,7 +1571,7 @@
 
     /* Compute the premaster. */
     uint8_t alert;
-    if (!SSL_ECDH_CTX_finish(&ssl->s3->hs->ecdh_ctx, &premaster_secret,
+    if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, &premaster_secret,
                              &premaster_secret_len, &alert, CBS_data(&peer_key),
                              CBS_len(&peer_key))) {
       al = alert;
@@ -1571,7 +1579,7 @@
     }
 
     /* The key exchange state may now be discarded. */
-    SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
+    SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
   } else if (alg_k & SSL_kPSK) {
     /* For plain PSK, other_secret is a block of 0s with the same length as the
      * pre-shared key. */
@@ -1639,7 +1647,8 @@
   return -1;
 }
 
-static int ssl3_get_cert_verify(SSL *ssl) {
+static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int al, ret = 0;
   CBS certificate_verify, signature;
   X509 *peer = ssl->s3->new_session->x509_peer;
@@ -1755,7 +1764,8 @@
 
 /* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
  * sets the next_proto member in s if found */
-static int ssl3_get_next_proto(SSL *ssl) {
+static int ssl3_get_next_proto(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret =
       ssl->method->ssl_get_message(ssl, SSL3_MT_NEXT_PROTO, ssl_hash_message);
   if (ret <= 0) {
@@ -1781,7 +1791,8 @@
 }
 
 /* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
-static int ssl3_get_channel_id(SSL *ssl) {
+static int ssl3_get_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int msg_ret = ssl->method->ssl_get_message(ssl, SSL3_MT_CHANNEL_ID,
                                              ssl_dont_hash_message);
   if (msg_ret <= 0) {
@@ -1795,7 +1806,8 @@
   return 1;
 }
 
-static int ssl3_send_new_session_ticket(SSL *ssl) {
+static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == SSL3_ST_SW_SESSION_TICKET_B) {
     return ssl->method->write_message(ssl);
   }
diff --git a/ssl/internal.h b/ssl/internal.h
index af833fb..273615f 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -889,7 +889,7 @@
   /* do_tls13_handshake runs the TLS 1.3 handshake. On completion, it returns
    * |ssl_hs_ok|. Otherwise, it returns a value corresponding to what operation
    * is needed to progress. */
-  enum ssl_hs_wait_t (*do_tls13_handshake)(SSL *ssl);
+  enum ssl_hs_wait_t (*do_tls13_handshake)(SSL_HANDSHAKE *hs);
 
   int state;
 
@@ -1034,12 +1034,12 @@
 
 /* tls13_handshake runs the TLS 1.3 handshake. It returns one on success and <=
  * 0 on error. */
-int tls13_handshake(SSL *ssl);
+int tls13_handshake(SSL_HANDSHAKE *hs);
 
 /* The following are implementations of |do_tls13_handshake| for the client and
  * server. */
-enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl);
-enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl);
+enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs);
+enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs);
 
 /* tls13_post_handshake processes a post-handshake message. It returns one on
  * success and zero on failure. */
@@ -1730,7 +1730,7 @@
 
 int ssl_verify_alarm_type(long type);
 
-int ssl3_get_finished(SSL *ssl);
+int ssl3_get_finished(SSL_HANDSHAKE *hs);
 int ssl3_send_change_cipher_spec(SSL *ssl);
 int ssl3_send_alert(SSL *ssl, int level, int desc);
 int ssl3_get_message(SSL *ssl, int msg_type,
@@ -1745,7 +1745,7 @@
 int ssl3_cert_verify_hash(SSL *ssl, const EVP_MD **out_md, uint8_t *out,
                           size_t *out_len, uint16_t signature_algorithm);
 
-int ssl3_send_finished(SSL *ssl, int a, int b);
+int ssl3_send_finished(SSL_HANDSHAKE *hs, int a, int b);
 int ssl3_supports_cipher(const SSL_CIPHER *cipher);
 int ssl3_dispatch_alert(SSL *ssl);
 int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index b27938a..d775cca 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -260,7 +260,8 @@
   return 1;
 }
 
-int ssl3_send_finished(SSL *ssl, int a, int b) {
+int ssl3_send_finished(SSL_HANDSHAKE *hs, int a, int b) {
+  SSL *const ssl = hs->ssl;
   if (ssl->state == b) {
     return ssl->method->write_message(ssl);
   }
@@ -309,7 +310,8 @@
   return ssl->method->write_message(ssl);
 }
 
-int ssl3_get_finished(SSL *ssl) {
+int ssl3_get_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_FINISHED,
                                          ssl_dont_hash_message);
   if (ret <= 0) {
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index c8d32a1..7d61304 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -34,9 +34,8 @@
  * without being able to return application data. */
 static const uint8_t kMaxKeyUpdates = 32;
 
-int tls13_handshake(SSL *ssl) {
-  SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+int tls13_handshake(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   for (;;) {
     /* Resolve the operation the handshake was waiting on. */
     switch (hs->wait) {
@@ -95,7 +94,7 @@
     }
 
     /* Run the state machine again. */
-    hs->wait = hs->do_tls13_handshake(ssl);
+    hs->wait = hs->do_tls13_handshake(hs);
     if (hs->wait == ssl_hs_error) {
       /* Don't loop around to avoid a stray |SSL_R_SSL_HANDSHAKE_FAILURE| the
        * first time around. */
diff --git a/ssl/tls13_client.c b/ssl/tls13_client.c
index 5a1a90d..9e71f31 100644
--- a/ssl/tls13_client.c
+++ b/ssl/tls13_client.c
@@ -50,8 +50,8 @@
 
 static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
 
-static enum ssl_hs_wait_t do_process_hello_retry_request(SSL *ssl,
-                                                         SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
     hs->state = state_process_server_hello;
     return ssl_hs_ok;
@@ -142,9 +142,8 @@
   return ssl_hs_ok;
 }
 
-static enum ssl_hs_wait_t do_send_second_client_hello(SSL *ssl,
-                                                      SSL_HANDSHAKE *hs) {
-  if (!ssl_write_client_hello(ssl)) {
+static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) {
+  if (!ssl_write_client_hello(hs->ssl)) {
     return ssl_hs_error;
   }
 
@@ -152,13 +151,13 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_flush_second_client_hello(SSL *ssl,
-                                                       SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush_second_client_hello(SSL_HANDSHAKE *hs) {
   hs->state = state_process_server_hello;
   return ssl_hs_flush_and_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
     return ssl_hs_error;
   }
@@ -321,8 +320,8 @@
   return ssl_hs_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL *ssl,
-                                                          SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS)) {
     return ssl_hs_error;
   }
@@ -347,8 +346,8 @@
   return ssl_hs_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_certificate_request(SSL *ssl,
-                                                         SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* CertificateRequest may only be sent in non-resumption handshakes. */
   if (ssl->s3->session_reused) {
     hs->state = state_process_server_finished;
@@ -391,9 +390,9 @@
     return ssl_hs_error;
   }
 
-  ssl->s3->hs->cert_request = 1;
-  sk_X509_NAME_pop_free(ssl->s3->hs->ca_names, X509_NAME_free);
-  ssl->s3->hs->ca_names = ca_sk;
+  hs->cert_request = 1;
+  sk_X509_NAME_pop_free(hs->ca_names, X509_NAME_free);
+  hs->ca_names = ca_sk;
 
   if (!ssl_hash_current_message(ssl)) {
     return ssl_hs_error;
@@ -403,8 +402,8 @@
   return ssl_hs_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_server_certificate(SSL *ssl,
-                                                        SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
       !tls13_process_certificate(ssl, 0 /* certificate required */) ||
       !ssl_hash_current_message(ssl)) {
@@ -416,7 +415,8 @@
 }
 
 static enum ssl_hs_wait_t do_process_server_certificate_verify(
-    SSL *ssl, SSL_HANDSHAKE *hs) {
+    SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
       !tls13_process_certificate_verify(ssl) ||
       !ssl_hash_current_message(ssl)) {
@@ -427,8 +427,8 @@
   return ssl_hs_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_server_finished(SSL *ssl,
-                                                     SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_server_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
       !tls13_process_finished(ssl) ||
       !ssl_hash_current_message(ssl) ||
@@ -443,9 +443,10 @@
   return ssl_hs_ok;
 }
 
-static enum ssl_hs_wait_t do_certificate_callback(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_certificate_callback(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* The peer didn't request a certificate. */
-  if (!ssl->s3->hs->cert_request) {
+  if (!hs->cert_request) {
     hs->state = state_send_channel_id;
     return ssl_hs_ok;
   }
@@ -468,8 +469,8 @@
   return ssl_hs_ok;
 }
 
-static enum ssl_hs_wait_t do_send_client_certificate(SSL *ssl,
-                                                     SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* Call client_cert_cb to update the certificate. */
   int should_retry;
   if (!ssl_do_client_cert_cb(ssl, &should_retry)) {
@@ -488,9 +489,9 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL *ssl,
-                                                            SSL_HANDSHAKE *hs,
+static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
                                                             int is_first_run) {
+  SSL *const ssl = hs->ssl;
   /* Don't send CertificateVerify if there is no certificate. */
   if (!ssl_has_certificate(ssl)) {
     hs->state = state_send_channel_id;
@@ -514,7 +515,8 @@
   return ssl_hs_error;
 }
 
-static enum ssl_hs_wait_t do_send_channel_id(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!ssl->s3->tlsext_channel_id_valid) {
     hs->state = state_send_client_finished;
     return ssl_hs_ok;
@@ -540,8 +542,8 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_send_client_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
-  if (!tls13_prepare_finished(ssl)) {
+static enum ssl_hs_wait_t do_send_client_finished(SSL_HANDSHAKE *hs) {
+  if (!tls13_prepare_finished(hs->ssl)) {
     return ssl_hs_error;
   }
 
@@ -549,7 +551,8 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->server_traffic_secret_0,
                              hs->hash_len) ||
       !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_traffic_secret_0,
@@ -562,60 +565,58 @@
   return ssl_hs_flush;
 }
 
-enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl) {
-  SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
   while (hs->state != state_done) {
     enum ssl_hs_wait_t ret = ssl_hs_error;
     enum client_hs_state_t state = hs->state;
     switch (state) {
       case state_process_hello_retry_request:
-        ret = do_process_hello_retry_request(ssl, hs);
+        ret = do_process_hello_retry_request(hs);
         break;
       case state_send_second_client_hello:
-        ret = do_send_second_client_hello(ssl, hs);
+        ret = do_send_second_client_hello(hs);
         break;
       case state_flush_second_client_hello:
-        ret = do_flush_second_client_hello(ssl, hs);
+        ret = do_flush_second_client_hello(hs);
         break;
       case state_process_server_hello:
-        ret = do_process_server_hello(ssl, hs);
+        ret = do_process_server_hello(hs);
         break;
       case state_process_encrypted_extensions:
-        ret = do_process_encrypted_extensions(ssl, hs);
+        ret = do_process_encrypted_extensions(hs);
         break;
       case state_process_certificate_request:
-        ret = do_process_certificate_request(ssl, hs);
+        ret = do_process_certificate_request(hs);
         break;
       case state_process_server_certificate:
-        ret = do_process_server_certificate(ssl, hs);
+        ret = do_process_server_certificate(hs);
         break;
       case state_process_server_certificate_verify:
-        ret = do_process_server_certificate_verify(ssl, hs);
+        ret = do_process_server_certificate_verify(hs);
         break;
       case state_process_server_finished:
-        ret = do_process_server_finished(ssl, hs);
+        ret = do_process_server_finished(hs);
         break;
       case state_certificate_callback:
-        ret = do_certificate_callback(ssl, hs);
+        ret = do_certificate_callback(hs);
         break;
       case state_send_client_certificate:
-        ret = do_send_client_certificate(ssl, hs);
+        ret = do_send_client_certificate(hs);
         break;
       case state_send_client_certificate_verify:
-        ret = do_send_client_certificate_verify(ssl, hs, 1 /* first run */);
+        ret = do_send_client_certificate_verify(hs, 1 /* first run */);
         break;
       case state_complete_client_certificate_verify:
-        ret = do_send_client_certificate_verify(ssl, hs, 0 /* complete */);
+        ret = do_send_client_certificate_verify(hs, 0 /* complete */);
         break;
       case state_send_channel_id:
-        ret = do_send_channel_id(ssl, hs);
+        ret = do_send_channel_id(hs);
         break;
       case state_send_client_finished:
-        ret = do_send_client_finished(ssl, hs);
+        ret = do_send_client_finished(hs);
         break;
       case state_flush:
-        ret = do_flush(ssl, hs);
+        ret = do_flush(hs);
         break;
       case state_done:
         ret = ssl_hs_ok;
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index e10e88e..eaeab06 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -87,7 +87,8 @@
   return ok;
 }
 
-static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
     return ssl_hs_error;
   }
@@ -173,7 +174,8 @@
   return best;
 }
 
-static enum ssl_hs_wait_t do_select_parameters(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* 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);
@@ -317,8 +319,8 @@
   return ssl_hs_ok;
 }
 
-static enum ssl_hs_wait_t do_send_hello_retry_request(SSL *ssl,
-                                                      SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   CBB cbb, body, extensions;
   uint16_t group_id;
   if (!ssl->method->init_message(ssl, &cbb, &body,
@@ -338,14 +340,13 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL *ssl,
-                                                       SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL_HANDSHAKE *hs) {
   hs->state = state_process_second_client_hello;
   return ssl_hs_flush_and_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl,
-                                                      SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
     return ssl_hs_error;
   }
@@ -377,7 +378,8 @@
   return ssl_hs_ok;
 }
 
-static enum ssl_hs_wait_t do_send_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   CBB cbb, body, extensions;
   if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
       !CBB_add_u16(&body, ssl->version) ||
@@ -399,8 +401,8 @@
   return ssl_hs_error;
 }
 
-static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
-                                                       SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_set_handshake_traffic(ssl)) {
     return ssl_hs_error;
   }
@@ -418,16 +420,16 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
-                                                      SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* Determine whether to request a client certificate. */
-  ssl->s3->hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+  hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
   /* CertificateRequest may only be sent in non-resumption handshakes. */
   if (ssl->s3->session_reused) {
-    ssl->s3->hs->cert_request = 0;
+    hs->cert_request = 0;
   }
 
-  if (!ssl->s3->hs->cert_request) {
+  if (!hs->cert_request) {
     /* Skip this state. */
     hs->state = state_send_server_certificate;
     return ssl_hs_ok;
@@ -466,8 +468,8 @@
   return ssl_hs_error;
 }
 
-static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
-                                                     SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->s3->session_reused) {
     hs->state = state_send_server_finished;
     return ssl_hs_ok;
@@ -486,10 +488,9 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL *ssl,
-                                                            SSL_HANDSHAKE *hs,
+static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
                                                             int is_first_run) {
-  switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
+  switch (tls13_prepare_certificate_verify(hs->ssl, is_first_run)) {
     case ssl_private_key_success:
       hs->state = state_send_server_finished;
       return ssl_hs_write_message;
@@ -506,8 +507,8 @@
   return ssl_hs_error;
 }
 
-static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
-  if (!tls13_prepare_finished(ssl)) {
+static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
+  if (!tls13_prepare_finished(hs->ssl)) {
     return ssl_hs_error;
   }
 
@@ -515,7 +516,8 @@
   return ssl_hs_write_message;
 }
 
-static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* Update the secret to the master secret and derive traffic keys. */
   if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
       !tls13_derive_application_secrets(ssl) ||
@@ -528,9 +530,9 @@
   return ssl_hs_flush_and_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
-                                                        SSL_HANDSHAKE *hs) {
-  if (!ssl->s3->hs->cert_request) {
+static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!hs->cert_request) {
     /* OpenSSL returns X509_V_OK when no certificates are requested. This is
      * classed by them as a bug, but it's assumed by at least NGINX. */
     ssl->s3->new_session->verify_result = X509_V_OK;
@@ -560,7 +562,8 @@
 }
 
 static enum ssl_hs_wait_t do_process_client_certificate_verify(
-    SSL *ssl, SSL_HANDSHAKE *hs) {
+    SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (ssl->s3->new_session->x509_peer == NULL) {
     /* Skip this state. */
     hs->state = state_process_channel_id;
@@ -577,7 +580,8 @@
   return ssl_hs_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_channel_id(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!ssl->s3->tlsext_channel_id_valid) {
     hs->state = state_process_client_finished;
     return ssl_hs_ok;
@@ -593,8 +597,8 @@
   return ssl_hs_read_message;
 }
 
-static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl,
-                                                     SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
       !tls13_process_finished(ssl) ||
       !ssl_hash_current_message(ssl) ||
@@ -618,8 +622,8 @@
  * client makes several connections before getting a renewal. */
 static const int kNumTickets = 2;
 
-static enum ssl_hs_wait_t do_send_new_session_ticket(SSL *ssl,
-                                                     SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* If the client doesn't accept resumption with PSK_DHE_KE, don't send a
    * session ticket. */
   if (!hs->accept_psk_mode) {
@@ -671,75 +675,72 @@
   return ssl_hs_error;
 }
 
-static enum ssl_hs_wait_t do_flush_new_session_tickets(SSL *ssl,
-                                                       SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush_new_session_tickets(SSL_HANDSHAKE *hs) {
   hs->state = state_done;
   return ssl_hs_flush;
 }
 
-enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
-  SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
   while (hs->state != state_done) {
     enum ssl_hs_wait_t ret = ssl_hs_error;
     enum server_hs_state_t state = hs->state;
     switch (state) {
       case state_process_client_hello:
-        ret = do_process_client_hello(ssl, hs);
+        ret = do_process_client_hello(hs);
         break;
       case state_select_parameters:
-        ret = do_select_parameters(ssl, hs);
+        ret = do_select_parameters(hs);
         break;
       case state_send_hello_retry_request:
-        ret = do_send_hello_retry_request(ssl, hs);
+        ret = do_send_hello_retry_request(hs);
         break;
       case state_flush_hello_retry_request:
-        ret = do_flush_hello_retry_request(ssl, hs);
+        ret = do_flush_hello_retry_request(hs);
         break;
       case state_process_second_client_hello:
-        ret = do_process_second_client_hello(ssl, hs);
+        ret = do_process_second_client_hello(hs);
         break;
       case state_send_server_hello:
-        ret = do_send_server_hello(ssl, hs);
+        ret = do_send_server_hello(hs);
         break;
       case state_send_encrypted_extensions:
-        ret = do_send_encrypted_extensions(ssl, hs);
+        ret = do_send_encrypted_extensions(hs);
         break;
       case state_send_certificate_request:
-        ret = do_send_certificate_request(ssl, hs);
+        ret = do_send_certificate_request(hs);
         break;
       case state_send_server_certificate:
-        ret = do_send_server_certificate(ssl, hs);
+        ret = do_send_server_certificate(hs);
         break;
       case state_send_server_certificate_verify:
-        ret = do_send_server_certificate_verify(ssl, hs, 1 /* first run */);
+        ret = do_send_server_certificate_verify(hs, 1 /* first run */);
       break;
       case state_complete_server_certificate_verify:
-        ret = do_send_server_certificate_verify(ssl, hs, 0 /* complete */);
+        ret = do_send_server_certificate_verify(hs, 0 /* complete */);
       break;
       case state_send_server_finished:
-        ret = do_send_server_finished(ssl, hs);
+        ret = do_send_server_finished(hs);
         break;
       case state_flush:
-        ret = do_flush(ssl, hs);
+        ret = do_flush(hs);
         break;
       case state_process_client_certificate:
-        ret = do_process_client_certificate(ssl, hs);
+        ret = do_process_client_certificate(hs);
         break;
       case state_process_client_certificate_verify:
-        ret = do_process_client_certificate_verify(ssl, hs);
+        ret = do_process_client_certificate_verify(hs);
         break;
       case state_process_channel_id:
-        ret = do_process_channel_id(ssl, hs);
+        ret = do_process_channel_id(hs);
         break;
       case state_process_client_finished:
-        ret = do_process_client_finished(ssl, hs);
+        ret = do_process_client_finished(hs);
         break;
       case state_send_new_session_ticket:
-        ret = do_send_new_session_ticket(ssl, hs);
+        ret = do_send_new_session_ticket(hs);
         break;
       case state_flush_new_session_tickets:
-        ret = do_flush_new_session_tickets(ssl, hs);
+        ret = do_flush_new_session_tickets(hs);
         break;
       case state_done:
         ret = ssl_hs_ok;