external/boringssl: Sync to b2ff2623a88a65fd4db42d3820f3d8c64e8ab180.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/6d50f475e319de153a43e1dba5a1beca95948c63..b2ff2623a88a65fd4db42d3820f3d8c64e8ab180

Change-Id: I649281e093369d99e863b4882a2ff6a5ad8a64d1
Test: ATP's cts/libcore/gce-net (go/gce-net)
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index 492884f..8d2657f 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -180,33 +180,56 @@
   OPENSSL_free(hs);
 }
 
-/* ssl3_do_write sends |ssl->init_buf| in records of type 'type'
- * (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC). It returns 1 on success
- * and <= 0 on error. */
-static int ssl3_do_write(SSL *ssl, int type, const uint8_t *data, size_t len) {
-  int ret = ssl3_write_bytes(ssl, type, data, len);
-  if (ret <= 0) {
-    return ret;
+int ssl_check_message_type(SSL *ssl, int type) {
+  if (ssl->s3->tmp.message_type != type) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+    ERR_add_error_dataf("got type %d, wanted type %d",
+                        ssl->s3->tmp.message_type, type);
+    return 0;
   }
 
-  /* ssl3_write_bytes writes the data in its entirety. */
-  assert((size_t)ret == len);
-  ssl_do_msg_callback(ssl, 1 /* write */, type, data, len);
+  return 1;
+}
+
+static int add_record_to_flight(SSL *ssl, uint8_t type, const uint8_t *in,
+                                size_t in_len) {
+  /* We'll never add a flight while in the process of writing it out. */
+  assert(ssl->s3->pending_flight_offset == 0);
+
+  if (ssl->s3->pending_flight == NULL) {
+    ssl->s3->pending_flight = BUF_MEM_new();
+    if (ssl->s3->pending_flight == NULL) {
+      return 0;
+    }
+  }
+
+  size_t max_out = in_len + SSL_max_seal_overhead(ssl);
+  size_t new_cap = ssl->s3->pending_flight->length + max_out;
+  if (max_out < in_len || new_cap < max_out) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  size_t len;
+  if (!BUF_MEM_reserve(ssl->s3->pending_flight, new_cap) ||
+      !tls_seal_record(ssl, (uint8_t *)ssl->s3->pending_flight->data +
+                                ssl->s3->pending_flight->length,
+                       &len, max_out, type, in, in_len)) {
+    return 0;
+  }
+
+  ssl->s3->pending_flight->length += len;
   return 1;
 }
 
 int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type) {
-  CBB_zero(cbb);
-  if (ssl->s3->pending_message != NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-
   /* Pick a modest size hint to save most of the |realloc| calls. */
   if (!CBB_init(cbb, 64) ||
       !CBB_add_u8(cbb, type) ||
       !CBB_add_u24_length_prefixed(cbb, body)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(cbb);
     return 0;
   }
 
@@ -223,56 +246,113 @@
   return 1;
 }
 
-int ssl3_queue_message(SSL *ssl, uint8_t *msg, size_t len) {
-  if (ssl->s3->pending_message != NULL ||
-      len > 0xffffffffu) {
-    OPENSSL_free(msg);
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
+  /* Add the message to the current flight, splitting into several records if
+   * needed. */
+  int ret = 0;
+  size_t added = 0;
+  do {
+    size_t todo = len - added;
+    if (todo > ssl->max_send_fragment) {
+      todo = ssl->max_send_fragment;
+    }
+
+    if (!add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, msg + added, todo)) {
+      goto err;
+    }
+    added += todo;
+  } while (added < len);
+
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
+  ssl3_update_handshake_hash(ssl, msg, len);
+  ret = 1;
+
+err:
+  OPENSSL_free(msg);
+  return ret;
+}
+
+int ssl3_add_change_cipher_spec(SSL *ssl) {
+  static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS};
+
+  if (!add_record_to_flight(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
+                            sizeof(kChangeCipherSpec))) {
     return 0;
   }
 
-  ssl3_update_handshake_hash(ssl, msg, len);
-
-  ssl->s3->pending_message = msg;
-  ssl->s3->pending_message_len = (uint32_t)len;
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_CHANGE_CIPHER_SPEC,
+                      kChangeCipherSpec, sizeof(kChangeCipherSpec));
   return 1;
 }
 
-int ssl_complete_message(SSL *ssl, CBB *cbb) {
+int ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc) {
+  uint8_t alert[2] = {level, desc};
+  if (!add_record_to_flight(ssl, SSL3_RT_ALERT, alert, sizeof(alert))) {
+    return 0;
+  }
+
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, alert, sizeof(alert));
+  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, ((int)level << 8) | desc);
+  return 1;
+}
+
+int ssl_add_message_cbb(SSL *ssl, CBB *cbb) {
   uint8_t *msg;
   size_t len;
   if (!ssl->method->finish_message(ssl, cbb, &msg, &len) ||
-      !ssl->method->queue_message(ssl, msg, len)) {
+      !ssl->method->add_message(ssl, msg, len)) {
     return 0;
   }
 
   return 1;
 }
 
-int ssl3_write_message(SSL *ssl) {
-  if (ssl->s3->pending_message == NULL) {
+int ssl3_flush_flight(SSL *ssl) {
+  if (ssl->s3->pending_flight == NULL) {
+    return 1;
+  }
+
+  if (ssl->s3->pending_flight->length > 0xffffffff ||
+      ssl->s3->pending_flight->length > INT_MAX) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
+    return -1;
   }
 
-  int ret = ssl3_do_write(ssl, SSL3_RT_HANDSHAKE, ssl->s3->pending_message,
-                          ssl->s3->pending_message_len);
-  if (ret <= 0) {
-    return ret;
+  /* The handshake flight buffer is mutually exclusive with application data.
+   *
+   * TODO(davidben): This will not be true when closure alerts use this. */
+  if (ssl_write_buffer_is_pending(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
   }
 
-  OPENSSL_free(ssl->s3->pending_message);
-  ssl->s3->pending_message = NULL;
-  ssl->s3->pending_message_len = 0;
+  /* Write the pending flight. */
+  while (ssl->s3->pending_flight_offset < ssl->s3->pending_flight->length) {
+    int ret = BIO_write(
+        ssl->wbio,
+        ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
+        ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset);
+    if (ret <= 0) {
+      ssl->rwstate = SSL_WRITING;
+      return ret;
+    }
+
+    ssl->s3->pending_flight_offset += ret;
+  }
+
+  if (BIO_flush(ssl->wbio) <= 0) {
+    ssl->rwstate = SSL_WRITING;
+    return -1;
+  }
+
+  BUF_MEM_free(ssl->s3->pending_flight);
+  ssl->s3->pending_flight = NULL;
+  ssl->s3->pending_flight_offset = 0;
   return 1;
 }
 
-int ssl3_send_finished(SSL_HANDSHAKE *hs, int a, int b) {
+int ssl3_send_finished(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  if (hs->state == b) {
-    return ssl->method->write_message(ssl);
-  }
-
   uint8_t finished[EVP_MAX_MD_SIZE];
   size_t finished_len =
       ssl->s3->enc_method->final_finish_mac(ssl, ssl->server, finished);
@@ -307,24 +387,26 @@
   CBB cbb, body;
   if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
       !CBB_add_bytes(&body, finished, finished_len) ||
-      !ssl_complete_message(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, &cbb)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     CBB_cleanup(&cbb);
     return -1;
   }
 
-  hs->state = b;
-  return ssl->method->write_message(ssl);
+  return 1;
 }
 
 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);
+  int ret = ssl->method->ssl_get_message(ssl);
   if (ret <= 0) {
     return ret;
   }
 
+  if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED)) {
+    return -1;
+  }
+
   /* Snapshot the finished hash before incorporating the new message. */
   uint8_t finished[EVP_MAX_MD_SIZE];
   size_t finished_len =
@@ -365,18 +447,11 @@
   return 1;
 }
 
-int ssl3_send_change_cipher_spec(SSL *ssl) {
-  static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS};
-
-  return ssl3_do_write(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
-                       sizeof(kChangeCipherSpec));
-}
-
 int ssl3_output_cert_chain(SSL *ssl) {
   CBB cbb, body;
   if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
       !ssl_add_cert_chain(ssl, &body) ||
-      !ssl_complete_message(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, &cbb)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     CBB_cleanup(&cbb);
     return 0;
@@ -431,7 +506,7 @@
   return 1;
 }
 
-static int read_v2_client_hello(SSL *ssl, int *out_is_v2_client_hello) {
+static int read_v2_client_hello(SSL *ssl) {
   /* Read the first 5 bytes, the size of the TLS record header. This is
    * sufficient to detect a V2ClientHello and ensures that we never read beyond
    * the first record. */
@@ -459,7 +534,6 @@
   if ((p[0] & 0x80) == 0 || p[2] != SSL2_MT_CLIENT_HELLO ||
       p[3] != SSL3_VERSION_MAJOR) {
     /* Not a V2ClientHello. */
-    *out_is_v2_client_hello = 0;
     return 1;
   }
 
@@ -581,12 +655,13 @@
   ssl_read_buffer_consume(ssl, 2 + msg_length);
   ssl_read_buffer_discard(ssl);
 
-  *out_is_v2_client_hello = 1;
+  ssl->s3->is_v2_hello = 1;
+  /* This is the first message, so hs must be non-NULL. */
+  ssl->s3->hs->v2_clienthello = 1;
   return 1;
 }
 
-int ssl3_get_message(SSL *ssl, int msg_type,
-                     enum ssl_hash_message_t hash_message) {
+int ssl3_get_message(SSL *ssl) {
 again:
   /* Re-create the handshake buffer if needed. */
   if (ssl->init_buf == NULL) {
@@ -598,28 +673,17 @@
 
   if (ssl->server && !ssl->s3->v2_hello_done) {
     /* Bypass the record layer for the first message to handle V2ClientHello. */
-    assert(hash_message == ssl_hash_message);
-    int is_v2_client_hello = 0;
-    int ret = read_v2_client_hello(ssl, &is_v2_client_hello);
+    int ret = read_v2_client_hello(ssl);
     if (ret <= 0) {
       return ret;
     }
-    if (is_v2_client_hello) {
-      /* V2ClientHello is hashed separately. */
-      hash_message = ssl_dont_hash_message;
-    }
     ssl->s3->v2_hello_done = 1;
   }
 
   if (ssl->s3->tmp.reuse_message) {
-    /* A ssl_dont_hash_message call cannot be combined with reuse_message; the
-     * ssl_dont_hash_message would have to have been applied to the previous
-     * call. */
-    assert(hash_message == ssl_hash_message);
+    /* There must be a current message. */
     assert(ssl->init_msg != NULL);
-
     ssl->s3->tmp.reuse_message = 0;
-    hash_message = ssl_dont_hash_message;
   } else {
     ssl3_release_current_message(ssl, 0 /* don't free buffer */);
   }
@@ -663,17 +727,6 @@
     goto again;
   }
 
-  if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-    return -1;
-  }
-
-  /* Feed this message into MAC computation. */
-  if (hash_message == ssl_hash_message && !ssl_hash_current_message(ssl)) {
-    return -1;
-  }
-
   return 1;
 }
 
@@ -682,6 +735,11 @@
 }
 
 int ssl_hash_current_message(SSL *ssl) {
+  /* V2ClientHellos are hashed implicitly. */
+  if (ssl->s3->is_v2_hello) {
+    return 1;
+  }
+
   CBS cbs;
   ssl->method->get_current_message(ssl, &cbs);
   return ssl3_update_handshake_hash(ssl, CBS_data(&cbs), CBS_len(&cbs));
@@ -696,6 +754,7 @@
     ssl->init_msg = NULL;
     ssl->init_num = 0;
     ssl->init_buf->length = 0;
+    ssl->s3->is_v2_hello = 0;
   }
 
   if (free_buffer) {