Revise SSL_cutthrough_complete and SSL_in_init.

This makes the following changes:

- SSL_cutthrough_complete no longer rederives whether cutthrough happened and
  just maintains a handshake bit.

- SSL_in_init no longer returns true if we are False Starting but haven't
  completed the handshake. That logic was awkward as it depended on querying
  in_read_app_data to force SSL_read to flush the entire handshake. Defaulting
  SSL_in_init to continue querying the full handshake and special-casing
  SSL_write is better. E.g. the check in bidirectional SSL_shutdown wants to know
  if we're in a handshake. No internal consumer of
  SSL_MODE_HANDSHAKE_CUTTHROUGH ever queries SSL_in_init directly.

- in_read_app_data is gone now that the final use is dead.

Change-Id: I05211a116d684054dfef53075cd277b1b30623b5
Reviewed-on: https://boringssl-review.googlesource.com/3336
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 6989bf6..e08caee 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1398,11 +1398,15 @@
 /* Is the SSL_connection established? */
 #define SSL_get_state(a) SSL_state(a)
 #define SSL_is_init_finished(a) (SSL_state(a) == SSL_ST_OK)
-#define SSL_in_init(a) \
-  ((SSL_state(a) & SSL_ST_INIT) && !SSL_cutthrough_complete(a))
+#define SSL_in_init(a) (SSL_state(a) & SSL_ST_INIT)
 #define SSL_in_before(a) (SSL_state(a) & SSL_ST_BEFORE)
 #define SSL_in_connect_init(a) (SSL_state(a) & SSL_ST_CONNECT)
 #define SSL_in_accept_init(a) (SSL_state(a) & SSL_ST_ACCEPT)
+
+/* SSL_cutthrough_complete returns one if |s| has a pending unfinished handshake
+ * that has completed cut-through. |SSL_write| may be called at this point
+ * without waiting for the peer, but |SSL_read| will require the handshake
+ * to be completed. */
 OPENSSL_EXPORT int SSL_cutthrough_complete(const SSL *s);
 
 /* The following 2 states are kept in ssl->rstate when reads fail,
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index 8745281..8dcc2c2 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -401,8 +401,6 @@
   int total_renegotiations;
   int num_renegotiations;
 
-  int in_read_app_data;
-
   /* State pertaining to the pending handshake.
    *
    * TODO(davidben): State is current spread all over the place. Move
@@ -486,6 +484,10 @@
     /* new_mac_secret_size is unused and exists only until wpa_supplicant can
      * be updated. It is only needed for EAP-FAST, which we don't support. */
     uint8_t new_mac_secret_size;
+
+    /* Client-only: cutthrough_complete is one if there is a pending handshake,
+     * but cut-through is completed so the client may write data. */
+    char cutthrough_complete;
   } tmp;
 
   /* Connection binding to prevent renegotiation attacks */
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 20fb2ec..42be93a 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -529,6 +529,7 @@
         } else {
           s->state = SSL3_ST_CR_CHANGE;
         }
+        s->s3->tmp.cutthrough_complete = 1;
 
         ssl_free_wbio_buffer(s);
         ret = 1;
@@ -549,6 +550,7 @@
         s->init_num = 0;
         s->renegotiate = 0;
         s->new_session = 0;
+        s->s3->tmp.cutthrough_complete = 0;
 
         ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
         if (s->hit) {
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 1e9958d..c230427 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1478,17 +1478,12 @@
 }
 
 static int ssl3_read_internal(SSL *s, void *buf, int len, int peek) {
-  int ret;
-
   ERR_clear_system_error();
   if (s->s3->renegotiate) {
     ssl3_renegotiate_check(s);
   }
-  s->s3->in_read_app_data = 1;
-  ret = s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len, peek);
-  s->s3->in_read_app_data = 0;
 
-  return ret;
+  return s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len, peek);
 }
 
 int ssl3_read(SSL *s, void *buf, int len) {
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index d37338f..57bb54b 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -427,7 +427,7 @@
   tot = s->s3->wnum;
   s->s3->wnum = 0;
 
-  if (SSL_in_init(s) && !s->in_handshake) {
+  if (!s->in_handshake && SSL_in_init(s) && !SSL_cutthrough_complete(s)) {
     i = s->handshake_func(s);
     if (i < 0) {
       return i;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index f090882..62ddaeb 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2902,18 +2902,7 @@
 }
 
 int SSL_cutthrough_complete(const SSL *s) {
-  return (
-      !s->server && /* cutthrough only applies to clients */
-      !s->hit &&    /* full-handshake */
-      s->version >= SSL3_VERSION &&
-      s->s3->in_read_app_data == 0 && /* cutthrough only applies to write() */
-      (SSL_get_mode((SSL *)s) &
-       SSL_MODE_HANDSHAKE_CUTTHROUGH) && /* cutthrough enabled */
-      ssl3_can_cutthrough(s) &&          /* cutthrough allowed */
-      s->s3->previous_server_finished_len ==
-          0 && /* not a renegotiation handshake */
-      (s->state == SSL3_ST_CR_SESSION_TICKET_A || /* ready to write app-data*/
-       s->state == SSL3_ST_CR_CHANGE || s->state == SSL3_ST_CR_FINISHED_A));
+  return s->s3->tmp.cutthrough_complete;
 }
 
 void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size,