Make SSL_state_string_long work for TLS 1.3.

SSL_state_string_long and SSL_state_string are often used for debugging
purposes. The latter's 6-letter codes are absurd, but
SSL_state_string_long is plausible. So we don't lose this when
converging state machines or switching to TLS 1.3, add this to TLS 1.3.

Bug: 128
Change-Id: Iec6529a4d9eddcf08bc9610137b4ccf9ea2681a6
Reviewed-on: https://boringssl-review.googlesource.com/19524
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/internal.h b/ssl/internal.h
index ea883e5..40e4e4e 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1336,6 +1336,11 @@
 enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs);
 enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs);
 
+/* The following functions return human-readable representations of the TLS 1.3
+ * handshake states for debugging. */
+const char *tls13_client_handshake_state(SSL_HANDSHAKE *hs);
+const char *tls13_server_handshake_state(SSL_HANDSHAKE *hs);
+
 /* tls13_post_handshake processes a post-handshake message. It returns one on
  * success and zero on failure. */
 int tls13_post_handshake(SSL *ssl, const SSLMessage &msg);
diff --git a/ssl/ssl_stat.cc b/ssl/ssl_stat.cc
index 56e4f2b..31cce4d 100644
--- a/ssl/ssl_stat.cc
+++ b/ssl/ssl_stat.cc
@@ -195,6 +195,10 @@
     case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
       return "DTLS1 read hello verify request A";
 
+    case SSL_ST_TLS13:
+      return ssl->server ? tls13_server_handshake_state(ssl->s3->hs)
+                         : tls13_client_handshake_state(ssl->s3->hs);
+
     default:
       return "unknown state";
   }
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 98e70a7..6608404 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -733,6 +733,10 @@
         break;
     }
 
+    if (hs->state != state) {
+      ssl_do_info_callback(hs->ssl, SSL_CB_CONNECT_LOOP, 1);
+    }
+
     if (ret != ssl_hs_ok) {
       return ret;
     }
@@ -741,6 +745,43 @@
   return ssl_hs_ok;
 }
 
+const char *tls13_client_handshake_state(SSL_HANDSHAKE *hs) {
+  enum client_hs_state_t state =
+      static_cast<enum client_hs_state_t>(hs->tls13_state);
+  switch (state) {
+    case state_read_hello_retry_request:
+      return "TLS 1.3 client read_hello_retry_request";
+    case state_send_second_client_hello:
+      return "TLS 1.3 client send_second_client_hello";
+    case state_read_server_hello:
+      return "TLS 1.3 client read_server_hello";
+    case state_process_change_cipher_spec:
+      return "TLS 1.3 client process_change_cipher_spec";
+    case state_read_encrypted_extensions:
+      return "TLS 1.3 client read_encrypted_extensions";
+    case state_read_certificate_request:
+      return "TLS 1.3 client read_certificate_request";
+    case state_read_server_certificate:
+      return "TLS 1.3 client read_server_certificate";
+    case state_read_server_certificate_verify:
+      return "TLS 1.3 client read_server_certificate_verify";
+    case state_read_server_finished:
+      return "TLS 1.3 client read_server_finished";
+    case state_send_end_of_early_data:
+      return "TLS 1.3 client send_end_of_early_data";
+    case state_send_client_certificate:
+      return "TLS 1.3 client send_client_certificate";
+    case state_send_client_certificate_verify:
+      return "TLS 1.3 client send_client_certificate_verify";
+    case state_complete_second_flight:
+      return "TLS 1.3 client complete_second_flight";
+    case state_done:
+      return "TLS 1.3 client done";
+  }
+
+  return "TLS 1.3 client unknown";
+}
+
 int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) {
   UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(ssl->s3->established_session,
                                                  SSL_SESSION_INCLUDE_NONAUTH));
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index a3ed8a7..894fa87 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -922,6 +922,10 @@
         break;
     }
 
+    if (hs->state != state) {
+      ssl_do_info_callback(hs->ssl, SSL_CB_ACCEPT_LOOP, 1);
+    }
+
     if (ret != ssl_hs_ok) {
       return ret;
     }
@@ -930,4 +934,45 @@
   return ssl_hs_ok;
 }
 
+const char *tls13_server_handshake_state(SSL_HANDSHAKE *hs) {
+  enum server_hs_state_t state =
+      static_cast<enum server_hs_state_t>(hs->tls13_state);
+  switch (state) {
+    case state_select_parameters:
+      return "TLS 1.3 server select_parameters";
+    case state_select_session:
+      return "TLS 1.3 server select_session";
+    case state_send_hello_retry_request:
+      return "TLS 1.3 server send_hello_retry_request";
+    case state_read_second_client_hello:
+      return "TLS 1.3 server read_second_client_hello";
+    case state_send_server_hello:
+      return "TLS 1.3 server send_server_hello";
+    case state_send_server_certificate_verify:
+      return "TLS 1.3 server send_server_certificate_verify";
+    case state_send_server_finished:
+      return "TLS 1.3 server send_server_finished";
+    case state_read_second_client_flight:
+      return "TLS 1.3 server read_second_client_flight";
+    case state_process_change_cipher_spec:
+      return "TLS 1.3 server process_change_cipher_spec";
+    case state_process_end_of_early_data:
+      return "TLS 1.3 server process_end_of_early_data";
+    case state_read_client_certificate:
+      return "TLS 1.3 server read_client_certificate";
+    case state_read_client_certificate_verify:
+      return "TLS 1.3 server read_client_certificate_verify";
+    case state_read_channel_id:
+      return "TLS 1.3 server read_channel_id";
+    case state_read_client_finished:
+      return "TLS 1.3 server read_client_finished";
+    case state_send_new_session_ticket:
+      return "TLS 1.3 server send_new_session_ticket";
+    case state_done:
+      return "TLS 1.3 server done";
+  }
+
+  return "TLS 1.3 server unknown";
+}
+
 }  // namespace bssl
diff --git a/tool/client.cc b/tool/client.cc
index 138a096..a5254b2 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -139,6 +139,10 @@
         "Allow renegotiations from the peer.",
     },
     {
+        "-debug", kBooleanArgument,
+        "Print debug information about the handshake",
+    },
+    {
         "", kOptionalArgument, "",
     },
 };
@@ -325,6 +329,20 @@
   return false;
 }
 
+static void InfoCallback(const SSL *ssl, int type, int value) {
+  switch (type) {
+    case SSL_CB_HANDSHAKE_START:
+      fprintf(stderr, "Handshake started.\n");
+      break;
+    case SSL_CB_HANDSHAKE_DONE:
+      fprintf(stderr, "Handshake done.\n");
+      break;
+    case SSL_CB_CONNECT_LOOP:
+      fprintf(stderr, "Handshake progress: %s\n", SSL_state_string_long(ssl));
+      break;
+  }
+}
+
 bool Client(const std::vector<std::string> &args) {
   if (!InitSocketLibrary()) {
     return false;
@@ -505,6 +523,10 @@
     SSL_CTX_set_ed25519_enabled(ctx.get(), 1);
   }
 
+  if (args_map.count("-debug") != 0) {
+    SSL_CTX_set_info_callback(ctx.get(), InfoCallback);
+  }
+
   if (args_map.count("-test-resumption") != 0) {
     if (args_map.count("-session-in") != 0) {
       fprintf(stderr,
diff --git a/tool/server.cc b/tool/server.cc
index 3b125ad..4cc183b 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -71,6 +71,10 @@
         "-tls13-variant", kBooleanArgument, "Enable TLS 1.3 variants",
     },
     {
+        "-debug", kBooleanArgument,
+        "Print debug information about the handshake",
+    },
+    {
         "", kOptionalArgument, "",
     },
 };
@@ -142,6 +146,20 @@
   return x509;
 }
 
+static void InfoCallback(const SSL *ssl, int type, int value) {
+  switch (type) {
+    case SSL_CB_HANDSHAKE_START:
+      fprintf(stderr, "Handshake started.\n");
+      break;
+    case SSL_CB_HANDSHAKE_DONE:
+      fprintf(stderr, "Handshake done.\n");
+      break;
+    case SSL_CB_ACCEPT_LOOP:
+      fprintf(stderr, "Handshake progress: %s\n", SSL_state_string_long(ssl));
+      break;
+  }
+}
+
 bool Server(const std::vector<std::string> &args) {
   if (!InitSocketLibrary()) {
     return false;
@@ -241,6 +259,10 @@
     SSL_CTX_set_tls13_variant(ctx.get(), tls13_experiment);
   }
 
+  if (args_map.count("-debug") != 0) {
+    SSL_CTX_set_info_callback(ctx.get(), InfoCallback);
+  }
+
   Listener listener;
   if (!listener.Init(args_map["-accept"])) {
     return false;