Switch handshake_client and handshake_server to C++.

Bug: 132
Change-Id: Ic68252de7b3a8f90d60f052a3cb707730d5a2b16
Reviewed-on: https://boringssl-review.googlesource.com/17744
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 94a1741..e45ba1f 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -11,8 +11,8 @@
   d1_srtp.cc
   dtls_method.cc
   dtls_record.cc
-  handshake_client.c
-  handshake_server.c
+  handshake_client.cc
+  handshake_server.cc
   s3_both.cc
   s3_lib.cc
   s3_pkt.cc
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.cc
similarity index 98%
rename from ssl/handshake_client.c
rename to ssl/handshake_client.cc
index 78bd1de..2c37ec0 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.cc
@@ -647,9 +647,10 @@
 
 int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  CBB cbb, body;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO)) {
-    goto err;
+  bssl::ScopedCBB cbb;
+  CBB body;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO)) {
+    return 0;
   }
 
   /* Renegotiations do not participate in session resumption. */
@@ -661,13 +662,13 @@
   if (!CBB_add_u16(&body, hs->client_version) ||
       !CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
       !CBB_add_u8_length_prefixed(&body, &child)) {
-    goto err;
+    return 0;
   }
 
   if (has_session_id) {
     if (!CBB_add_bytes(&child, ssl->session->session_id,
                        ssl->session->session_id_length)) {
-      goto err;
+      return 0;
     }
   } else {
     /* In TLS 1.3 experimental encodings, send a fake placeholder session ID
@@ -675,14 +676,14 @@
     if (hs->max_version >= TLS1_3_VERSION &&
         ssl->tls13_variant != tls13_default &&
         !CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) {
-      goto err;
+      return 0;
     }
   }
 
   if (SSL_is_dtls(ssl)) {
     if (!CBB_add_u8_length_prefixed(&body, &child) ||
         !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
-      goto err;
+      return 0;
     }
   }
 
@@ -692,13 +693,13 @@
       !CBB_add_u8(&body, 1 /* one compression method */) ||
       !CBB_add_u8(&body, 0 /* null compression */) ||
       !ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) {
-    goto err;
+    return 0;
   }
 
   uint8_t *msg = NULL;
   size_t len;
-  if (!ssl->method->finish_message(ssl, &cbb, &msg, &len)) {
-    goto err;
+  if (!ssl->method->finish_message(ssl, cbb.get(), &msg, &len)) {
+    return 0;
   }
 
   /* Now that the length prefixes have been computed, fill in the placeholder
@@ -706,14 +707,10 @@
   if (hs->needs_psk_binder &&
       !tls13_write_psk_binder(hs, msg, len)) {
     OPENSSL_free(msg);
-    goto err;
+    return 0;
   }
 
   return ssl->method->add_message(ssl, msg, len);
-
- err:
-  CBB_cleanup(&cbb);
-  return 0;
 }
 
 static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
@@ -1498,14 +1495,15 @@
 
 static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  uint8_t *pms = NULL;
-  size_t pms_len = 0;
-  CBB cbb, body;
-  if (!ssl->method->init_message(ssl, &cbb, &body,
+  bssl::ScopedCBB cbb;
+  CBB body;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_CLIENT_KEY_EXCHANGE)) {
-    goto err;
+    return -1;
   }
 
+  uint8_t *pms = NULL;
+  size_t pms_len = 0;
   uint32_t alg_k = hs->new_cipher->algorithm_mkey;
   uint32_t alg_a = hs->new_cipher->algorithm_auth;
 
@@ -1550,7 +1548,7 @@
   /* Depending on the key exchange method, compute |pms| and |pms_len|. */
   if (alg_k & SSL_kRSA) {
     pms_len = SSL_MAX_MASTER_KEY_LENGTH;
-    pms = OPENSSL_malloc(pms_len);
+    pms = (uint8_t *)OPENSSL_malloc(pms_len);
     if (pms == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
@@ -1613,7 +1611,7 @@
     /* For plain PSK, other_secret is a block of 0s with the same length as
      * the pre-shared key. */
     pms_len = psk_len;
-    pms = OPENSSL_malloc(pms_len);
+    pms = (uint8_t *)OPENSSL_malloc(pms_len);
     if (pms == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
@@ -1651,7 +1649,7 @@
 
   /* The message must be added to the finished hash before calculating the
    * master secret. */
-  if (!ssl_add_message_cbb(ssl, &cbb)) {
+  if (!ssl_add_message_cbb(ssl, cbb.get())) {
     goto err;
   }
 
@@ -1667,7 +1665,6 @@
   return 1;
 
 err:
-  CBB_cleanup(&cbb);
   if (pms != NULL) {
     OPENSSL_cleanse(pms, pms_len);
     OPENSSL_free(pms);
@@ -1679,21 +1676,22 @@
   SSL *const ssl = hs->ssl;
   assert(ssl_has_private_key(ssl));
 
-  CBB cbb, body, child;
-  if (!ssl->method->init_message(ssl, &cbb, &body,
+  bssl::ScopedCBB cbb;
+  CBB body, child;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_CERTIFICATE_VERIFY)) {
-    goto err;
+    return -1;
   }
 
   uint16_t signature_algorithm;
   if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
-    goto err;
+    return -1;
   }
   if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
     /* Write out the digest type in TLS 1.2. */
     if (!CBB_add_u16(&body, signature_algorithm)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
+      return -1;
     }
   }
 
@@ -1702,7 +1700,7 @@
   uint8_t *ptr;
   if (!CBB_add_u16_length_prefixed(&body, &child) ||
       !CBB_reserve(&child, &ptr, max_sig_len)) {
-    goto err;
+    return -1;
   }
 
   size_t sig_len = max_sig_len;
@@ -1711,7 +1709,7 @@
   if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
     if (ssl->cert->key_method != NULL) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
-      goto err;
+      return -1;
     }
 
     uint8_t digest[EVP_MAX_MD_SIZE];
@@ -1719,7 +1717,7 @@
     if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
                                               &digest_len, hs->new_session,
                                               signature_algorithm)) {
-      goto err;
+      return -1;
     }
 
     EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
@@ -1728,7 +1726,7 @@
              EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len);
     EVP_PKEY_CTX_free(pctx);
     if (!ok) {
-      goto err;
+      return -1;
     }
   } else {
     switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
@@ -1738,25 +1736,21 @@
       case ssl_private_key_success:
         break;
       case ssl_private_key_failure:
-        goto err;
+        return -1;
       case ssl_private_key_retry:
         ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-        goto err;
+        return -1;
     }
   }
 
   if (!CBB_did_write(&child, sig_len) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
-    goto err;
+      !ssl_add_message_cbb(ssl, cbb.get())) {
+    return -1;
   }
 
   /* The handshake buffer is no longer necessary. */
   SSL_TRANSCRIPT_free_buffer(&hs->transcript);
   return 1;
-
-err:
-  CBB_cleanup(&cbb);
-  return -1;
 }
 
 static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) {
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.cc
similarity index 96%
rename from ssl/handshake_server.c
rename to ssl/handshake_server.cc
index 64abd5d..ee5358c 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.cc
@@ -800,9 +800,6 @@
 
 static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  int ret = -1;
-  SSL_SESSION *session = NULL;
-
   SSL_CLIENT_HELLO client_hello;
   if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
                              ssl->init_num)) {
@@ -811,49 +808,52 @@
 
   /* Determine whether we are doing session resumption. */
   int tickets_supported = 0, renew_ticket = 0;
-  switch (ssl_get_prev_session(ssl, &session, &tickets_supported, &renew_ticket,
-                               &client_hello)) {
+  /* TODO(davidben): Switch |ssl_get_prev_session| to take a |bssl::UniquePtr|
+   * output and simplify this. */
+  SSL_SESSION *session_raw = nullptr;
+  auto session_ret = ssl_get_prev_session(ssl, &session_raw, &tickets_supported,
+                                          &renew_ticket, &client_hello);
+  bssl::UniquePtr<SSL_SESSION> session(session_raw);
+  switch (session_ret) {
     case ssl_session_success:
       break;
     case ssl_session_error:
-      goto err;
+      return -1;
     case ssl_session_retry:
       ssl->rwstate = SSL_PENDING_SESSION;
-      goto err;
+      return -1;
     case ssl_session_ticket_retry:
       ssl->rwstate = SSL_PENDING_TICKET;
-      goto err;
+      return -1;
   }
 
-  if (session != NULL) {
+  if (session) {
     if (session->extended_master_secret && !hs->extended_master_secret) {
       /* A ClientHello without EMS that attempts to resume a session with EMS
        * is fatal to the connection. */
       OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-      goto err;
+      return -1;
     }
 
-    if (!ssl_session_is_resumable(hs, session) ||
+    if (!ssl_session_is_resumable(hs, session.get()) ||
         /* If the client offers the EMS extension, but the previous session
          * didn't use it, then negotiate a new session. */
         hs->extended_master_secret != session->extended_master_secret) {
-      SSL_SESSION_free(session);
-      session = NULL;
+      session.reset();
     }
   }
 
-  if (session != NULL) {
+  if (session) {
     /* Use the old session. */
     hs->ticket_expected = renew_ticket;
-    ssl->session = session;
-    session = NULL;
+    ssl->session = session.release();
     ssl->s3->session_reused = 1;
   } else {
     hs->ticket_expected = tickets_supported;
     ssl_set_session(ssl, NULL);
     if (!ssl_get_new_session(hs, 1 /* server */)) {
-      goto err;
+      return -1;
     }
 
     /* Clear the session ID if we want the session to be single-use. */
@@ -867,7 +867,7 @@
     /* Connection rejected for DOS reasons. */
     OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    goto err;
+    return -1;
   }
 
   if (ssl->session == NULL) {
@@ -879,7 +879,7 @@
       hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
       if (hs->new_session->tlsext_hostname == NULL) {
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        goto err;
+        return -1;
       }
     }
 
@@ -907,7 +907,7 @@
   uint8_t alert = SSL_AD_DECODE_ERROR;
   if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
-    goto err;
+    return -1;
   }
 
   /* Now that all parameters are known, initialize the handshake hash and hash
@@ -916,7 +916,7 @@
                                 hs->new_cipher->algorithm_prf) ||
       !ssl_hash_current_message(hs)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    goto err;
+    return -1;
   }
 
   /* Release the handshake buffer if client authentication isn't required. */
@@ -924,11 +924,7 @@
     SSL_TRANSCRIPT_free_buffer(&hs->transcript);
   }
 
-  ret = 1;
-
-err:
-  SSL_SESSION_free(session);
-  return ret;
+  return 1;
 }
 
 static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
@@ -988,32 +984,30 @@
 
 static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  int ret = -1;
-  CBB cbb;
-  CBB_zero(&cbb);
+  bssl::ScopedCBB cbb;
 
   if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
     if (!ssl_has_certificate(ssl)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
-      goto err;
+      return -1;
     }
 
     if (!ssl3_output_cert_chain(ssl)) {
-      goto err;
+      return -1;
     }
 
     if (hs->certificate_status_expected) {
       CBB body, ocsp_response;
-      if (!ssl->method->init_message(ssl, &cbb, &body,
+      if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                      SSL3_MT_CERTIFICATE_STATUS) ||
           !CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
           !CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
           !CBB_add_bytes(&ocsp_response,
                          CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
                          CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
-          !ssl_add_message_cbb(ssl, &cbb)) {
+          !ssl_add_message_cbb(ssl, cbb.get())) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return -1;
       }
     }
   }
@@ -1027,20 +1021,20 @@
     /* Pre-allocate enough room to comfortably fit an ECDHE public key. Prepend
      * the client and server randoms for the signing transcript. */
     CBB child;
-    if (!CBB_init(&cbb, SSL3_RANDOM_SIZE * 2 + 128) ||
-        !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
-        !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
-      goto err;
+    if (!CBB_init(cbb.get(), SSL3_RANDOM_SIZE * 2 + 128) ||
+        !CBB_add_bytes(cbb.get(), ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+        !CBB_add_bytes(cbb.get(), ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+      return -1;
     }
 
     /* PSK ciphers begin with an identity hint. */
     if (alg_a & SSL_aPSK) {
       size_t len =
           (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint);
-      if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+      if (!CBB_add_u16_length_prefixed(cbb.get(), &child) ||
           !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint,
                          len)) {
-        goto err;
+        return -1;
       }
     }
 
@@ -1050,32 +1044,28 @@
       if (!tls1_get_shared_group(hs, &group_id)) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        goto err;
-      }
+        return -1;
+       }
       hs->new_session->group_id = group_id;
 
       /* Set up ECDH, generate a key, and emit the public half. */
       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) ||
+          !CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) ||
+          !CBB_add_u16(cbb.get(), group_id) ||
+          !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
           !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
-        goto err;
+        return -1;
       }
     } else {
       assert(alg_k & SSL_kPSK);
     }
 
-    if (!CBB_finish(&cbb, &hs->server_params, &hs->server_params_len)) {
-      goto err;
+    if (!CBB_finish(cbb.get(), &hs->server_params, &hs->server_params_len)) {
+      return -1;
     }
   }
 
-  ret = 1;
-
-err:
-  CBB_cleanup(&cbb);
-  return ret;
+  return 1;
 }
 
 static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
@@ -1348,7 +1338,7 @@
 
     /* Allocate a buffer large enough for an RSA decryption. */
     const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey);
-    decrypt_buf = OPENSSL_malloc(rsa_size);
+    decrypt_buf = (uint8_t *)OPENSSL_malloc(rsa_size);
     if (decrypt_buf == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
@@ -1379,7 +1369,7 @@
     /* Prepare a random premaster, to be used on invalid padding. See RFC 5246,
      * section 7.4.7.1. */
     premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
-    premaster_secret = OPENSSL_malloc(premaster_secret_len);
+    premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len);
     if (premaster_secret == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
@@ -1476,7 +1466,7 @@
       /* In plain PSK, other_secret is a block of 0s with the same length as the
        * pre-shared key. */
       premaster_secret_len = psk_len;
-      premaster_secret = OPENSSL_malloc(premaster_secret_len);
+      premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len);
       if (premaster_secret == NULL) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
         goto err;