Switch the handshake buffer from memory BIO to BUF_MEM.

A memory BIO is internally a BUF_MEM anyway. There's no need to bring
BIO_write into the mix. BUF_MEM is size_t clean.

Change-Id: I4ec6e4d22c72696bf47c95861771013483f75cab
Reviewed-on: https://boringssl-review.googlesource.com/5616
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index 93da2c3..7249f51 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -385,8 +385,8 @@
   int wpend_ret; /* number of bytes submitted */
   const uint8_t *wpend_buf;
 
-  /* used during startup, digest all incoming/outgoing packets */
-  BIO *handshake_buffer;
+  /* handshake_buffer, if non-NULL, contains the handshake transcript. */
+  BUF_MEM *handshake_buffer;
   /* When set of handshake digests is determined, buffer is hashed and freed
    * and MD_CTX-es for all required digests are stored in this array */
   EVP_MD_CTX **handshake_dgst;
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 85dc9d6..7580016 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -456,18 +456,13 @@
    * agreed digest and cached handshake records. Otherwise, use
    * SHA1 or MD5 + SHA1 depending on key type.  */
   if (SSL_USE_SIGALGS(s)) {
-    const uint8_t *hdata;
-    size_t hdatalen;
     EVP_MD_CTX mctx;
     unsigned len;
 
-    if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
     EVP_MD_CTX_init(&mctx);
     if (!EVP_DigestInit_ex(&mctx, *out_md, NULL) ||
-        !EVP_DigestUpdate(&mctx, hdata, hdatalen) ||
+        !EVP_DigestUpdate(&mctx, s->s3->handshake_buffer->data,
+                          s->s3->handshake_buffer->length) ||
         !EVP_DigestFinal(&mctx, out, &len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
       EVP_MD_CTX_cleanup(&mctx);
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index af72549..f860609 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -238,21 +238,14 @@
 int ssl3_init_handshake_buffer(SSL *ssl) {
   ssl3_free_handshake_buffer(ssl);
   ssl3_free_handshake_hash(ssl);
-  ssl->s3->handshake_buffer = BIO_new(BIO_s_mem());
-  if (ssl->s3->handshake_buffer == NULL) {
-    return 0;
-  }
-  BIO_set_close(ssl->s3->handshake_buffer, BIO_CLOSE);
-
-  return 1;
+  ssl->s3->handshake_buffer = BUF_MEM_new();
+  return ssl->s3->handshake_buffer != NULL;
 }
 
 int ssl3_init_handshake_hash(SSL *ssl) {
   int i;
   uint32_t mask;
   const EVP_MD *md;
-  const uint8_t *hdata;
-  size_t hdatalen;
 
   /* Allocate handshake_dgst array */
   ssl3_free_handshake_hash(ssl);
@@ -262,12 +255,7 @@
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return 0;
   }
-
   memset(ssl->s3->handshake_dgst, 0, SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
-  if (!BIO_mem_contents(ssl->s3->handshake_buffer, &hdata, &hdatalen)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_LENGTH);
-    return 0;
-  }
 
   /* Loop through bits of algorithm_prf field and create MD_CTX-es */
   for (i = 0; ssl_get_handshake_digest(&mask, &md, i); i++) {
@@ -283,7 +271,9 @@
         OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
         return 0;
       }
-      EVP_DigestUpdate(ssl->s3->handshake_dgst[i], hdata, hdatalen);
+      EVP_DigestUpdate(ssl->s3->handshake_dgst[i],
+                       ssl->s3->handshake_buffer->data,
+                       ssl->s3->handshake_buffer->length);
     } else {
       ssl->s3->handshake_dgst[i] = NULL;
     }
@@ -307,7 +297,7 @@
 }
 
 void ssl3_free_handshake_buffer(SSL *ssl) {
-  BIO_free(ssl->s3->handshake_buffer);
+  BUF_MEM_free(ssl->s3->handshake_buffer);
   ssl->s3->handshake_buffer = NULL;
 }
 
@@ -315,11 +305,16 @@
   /* Depending on the state of the handshake, either the handshake buffer may be
    * active, the rolling hash, or both. */
 
-  /* TODO(davidben): Replace |handshake_buffer| with a simpler type that doesn't
-   * require a cast. */
-  if (ssl->s3->handshake_buffer != NULL &&
-      BIO_write(ssl->s3->handshake_buffer, in, (int)in_len) < 0) {
-    return 0;
+  if (ssl->s3->handshake_buffer != NULL) {
+    size_t new_len = ssl->s3->handshake_buffer->length + in_len;
+    if (new_len < in_len) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+      return 0;
+    }
+    if (!BUF_MEM_grow(ssl->s3->handshake_buffer, new_len)) {
+      return 0;
+    }
+    memcpy(ssl->s3->handshake_buffer->data + new_len - in_len, in, in_len);
   }
 
   if (ssl->s3->handshake_dgst != NULL) {