Convert ssl3_send_cert_verify to CBB.

In doing so, make the asynchronous portion look more like
ssl3_send_server_key_exchange. This is a considerably simpler structure,
so the save/resume doesn't need any state.

Mostly this means writing out the signature algorithm can now go through
CBB rather than a uint8_t* without bounds check.

Change-Id: If99fcffd0d41a84514c3d23034062c582f1bccb2
Reviewed-on: https://boringssl-review.googlesource.com/6771
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 7f61c89..85c0408 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1852,82 +1852,94 @@
   return -1;
 }
 
-int ssl3_send_cert_verify(SSL *s) {
-  if (s->state == SSL3_ST_CW_CERT_VRFY_A ||
-      s->state == SSL3_ST_CW_CERT_VRFY_B) {
-    enum ssl_private_key_result_t sign_result;
-    uint8_t *p = ssl_handshake_start(s);
-    size_t signature_length = 0;
-    unsigned long n = 0;
-    assert(ssl_has_private_key(s));
-
-    if (s->state == SSL3_ST_CW_CERT_VRFY_A) {
-      uint8_t *buf = (uint8_t *)s->init_buf->data;
-      const EVP_MD *md = NULL;
-      uint8_t digest[EVP_MAX_MD_SIZE];
-      size_t digest_length;
-
-      /* Write out the digest type if need be. */
-      if (SSL_USE_SIGALGS(s)) {
-        md = tls1_choose_signing_digest(s);
-        if (!tls12_get_sigandhash(s, p, md)) {
-          OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-          return -1;
-        }
-        p += 2;
-        n += 2;
-      }
-
-      /* Compute the digest. */
-      const int pkey_type = ssl_private_key_type(s);
-      if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey_type)) {
-        return -1;
-      }
-
-      /* The handshake buffer is no longer necessary. */
-      ssl3_free_handshake_buffer(s);
-
-      /* Sign the digest. */
-      signature_length = ssl_private_key_max_signature_len(s);
-      if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
-        return -1;
-      }
-
-      s->rwstate = SSL_PRIVATE_KEY_OPERATION;
-      sign_result = ssl_private_key_sign(s, &p[2], &signature_length,
-                                         signature_length, md, digest,
-                                         digest_length);
-    } else {
-      if (SSL_USE_SIGALGS(s)) {
-        /* The digest has already been selected and written. */
-        p += 2;
-        n += 2;
-      }
-      signature_length = ssl_private_key_max_signature_len(s);
-      s->rwstate = SSL_PRIVATE_KEY_OPERATION;
-      sign_result = ssl_private_key_sign_complete(s, &p[2], &signature_length,
-                                                  signature_length);
-    }
-
-    if (sign_result == ssl_private_key_retry) {
-      s->state = SSL3_ST_CW_CERT_VRFY_B;
-      return -1;
-    }
-    s->rwstate = SSL_NOTHING;
-    if (sign_result != ssl_private_key_success) {
-      return -1;
-    }
-
-    s2n(signature_length, p);
-    n += signature_length + 2;
-    if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) {
-      return -1;
-    }
-    s->state = SSL3_ST_CW_CERT_VRFY_C;
+int ssl3_send_cert_verify(SSL *ssl) {
+  if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
+    return ssl_do_write(ssl);
   }
 
-  return ssl_do_write(s);
+  CBB cbb, child;
+  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
+    goto err;
+  }
+
+  assert(ssl_has_private_key(ssl));
+
+  const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
+  size_t sig_len;
+  enum ssl_private_key_result_t sign_result;
+  if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) {
+    /* Select and write out the digest type in TLS 1.2. */
+    const EVP_MD *md = NULL;
+    if (SSL_USE_SIGALGS(ssl)) {
+      md = tls1_choose_signing_digest(ssl);
+      if (!tls12_add_sigandhash(ssl, &cbb, md)) {
+        OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+        goto err;
+      }
+    }
+
+    /* Compute the digest. In TLS 1.1 and below, the digest type is also
+     * selected here. */
+    uint8_t digest[EVP_MAX_MD_SIZE];
+    size_t digest_len;
+    if (!ssl3_cert_verify_hash(ssl, digest, &digest_len, &md,
+                               ssl_private_key_type(ssl))) {
+      goto err;
+    }
+
+    /* The handshake buffer is no longer necessary. */
+    ssl3_free_handshake_buffer(ssl);
+
+    /* Sign the digest. */
+    uint8_t *ptr;
+    if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+        !CBB_reserve(&child, &ptr, max_sig_len)) {
+      goto err;
+    }
+    sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
+                                       digest, digest_len);
+  } else {
+    assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B);
+
+    /* Skip over the already written signature algorithm and retry the
+     * signature. */
+    uint8_t *ptr;
+    if ((SSL_USE_SIGALGS(ssl) && !CBB_did_write(&cbb, 2)) ||
+        !CBB_add_u16_length_prefixed(&cbb, &child) ||
+        !CBB_reserve(&child, &ptr, max_sig_len)) {
+      goto err;
+    }
+    sign_result =
+        ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
+  }
+
+  switch (sign_result) {
+    case ssl_private_key_success:
+      ssl->rwstate = SSL_NOTHING;
+      break;
+    case ssl_private_key_failure:
+      ssl->rwstate = SSL_NOTHING;
+      goto err;
+    case ssl_private_key_retry:
+      ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+      ssl->state = SSL3_ST_CW_CERT_VRFY_B;
+      goto err;
+  }
+
+  size_t length;
+  if (!CBB_did_write(&child, sig_len) ||
+      !CBB_finish(&cbb, NULL, &length) ||
+      !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_VERIFY, length)) {
+    goto err;
+  }
+
+  ssl->state = SSL3_ST_CW_CERT_VRFY_C;
+  return ssl_do_write(ssl);
+
+err:
+  CBB_cleanup(&cbb);
+  return -1;
 }
 
 /* ssl3_has_client_certificate returns true if a client certificate is