Collapse client Finished states together.

By resolving Channel ID earlier, we can take advantage of
flight-by-flight writes.

Change-Id: I31265bda3390eb1faec976ac13d7a01ba5f6dd5f
Reviewed-on: https://boringssl-review.googlesource.com/19925
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index ee8cf7a..49d931b 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -188,8 +188,6 @@
   state_send_client_certificate,
   state_send_client_key_exchange,
   state_send_client_certificate_verify,
-  state_send_second_client_flight,
-  state_send_channel_id,
   state_send_client_finished,
   state_finish_flight,
   state_read_session_ticket,
@@ -1397,7 +1395,7 @@
   SSL *const ssl = hs->ssl;
 
   if (!hs->cert_request || !ssl_has_certificate(ssl)) {
-    hs->state = state_send_second_client_flight;
+    hs->state = state_send_client_finished;
     return ssl_hs_ok;
   }
 
@@ -1473,12 +1471,23 @@
   // The handshake buffer is no longer necessary.
   hs->transcript.FreeBuffer();
 
-  hs->state = state_send_second_client_flight;
+  hs->state = state_send_client_finished;
   return ssl_hs_ok;
 }
 
-static enum ssl_hs_wait_t do_send_second_client_flight(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_client_finished(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
+  // Resolve Channel ID first, before any non-idempotent operations.
+  if (ssl->s3->tlsext_channel_id_valid) {
+    if (!ssl_do_channel_id_callback(ssl)) {
+      return ssl_hs_error;
+    }
+
+    if (ssl->tlsext_channel_id_private == NULL) {
+      hs->state = state_send_client_finished;
+      return ssl_hs_channel_id_lookup;
+    }
+  }
 
   if (!ssl->method->add_change_cipher_spec(ssl) ||
       !tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
@@ -1503,41 +1512,17 @@
     }
   }
 
-  hs->state = state_send_channel_id;
-  return ssl_hs_ok;
-}
-
-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;
+  if (ssl->s3->tlsext_channel_id_valid) {
+    ScopedCBB cbb;
+    CBB body;
+    if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CHANNEL_ID) ||
+        !tls1_write_channel_id(hs, &body) ||
+        !ssl_add_message_cbb(ssl, cbb.get())) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return ssl_hs_error;
+    }
   }
 
-  if (!ssl_do_channel_id_callback(ssl)) {
-    return ssl_hs_error;
-  }
-
-  if (ssl->tlsext_channel_id_private == NULL) {
-    hs->state = state_send_channel_id;
-    return ssl_hs_channel_id_lookup;
-  }
-
-  ScopedCBB cbb;
-  CBB body;
-  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CHANNEL_ID) ||
-      !tls1_write_channel_id(hs, &body) ||
-      !ssl_add_message_cbb(ssl, cbb.get())) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return ssl_hs_error;
-  }
-
-  hs->state = state_send_client_finished;
-  return ssl_hs_ok;
-}
-
-static enum ssl_hs_wait_t do_send_client_finished(SSL_HANDSHAKE *hs) {
   if (!ssl3_send_finished(hs)) {
     return ssl_hs_error;
   }
@@ -1674,7 +1659,7 @@
   }
 
   if (ssl->session != NULL) {
-    hs->state = state_send_second_client_flight;
+    hs->state = state_send_client_finished;
     return ssl_hs_ok;
   }
 
@@ -1765,12 +1750,6 @@
       case state_send_client_certificate_verify:
         ret = do_send_client_certificate_verify(hs);
         break;
-      case state_send_second_client_flight:
-        ret = do_send_second_client_flight(hs);
-        break;
-      case state_send_channel_id:
-        ret = do_send_channel_id(hs);
-        break;
       case state_send_client_finished:
         ret = do_send_client_finished(hs);
         break;
@@ -1839,10 +1818,6 @@
       return "TLS client send_client_key_exchange";
     case state_send_client_certificate_verify:
       return "TLS client send_client_certificate_verify";
-    case state_send_second_client_flight:
-      return "TLS client send_second_client_flight";
-    case state_send_channel_id:
-      return "TLS client send_channel_id";
     case state_send_client_finished:
       return "TLS client send_client_finished";
     case state_finish_flight: