Unify signing codepath of ssl3_send_client_verify.

Instead of, in the pre-TLS-1.2 case, reaching into the EVP and manually
signing, compute the digest separately from signing. Then use EVP_PKEY_sign.
This will make it easier to implement https://crbug.com/347404 by having only
one signing codepath as well as make that logic simpler.

Also add a bounds check while we're here, although the buffer is too large to
actually matter.

runner.go client auth tests should cover code changes.

Change-Id: I7d87181bbcc5a761660412452e508d24c4725327
Reviewed-on: https://boringssl-review.googlesource.com/1122
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 6f6cf3d..5f3e997 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -2674,28 +2674,32 @@
 
 int ssl3_send_client_verify(SSL *s)
 	{
-	unsigned char *p;
-	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+	unsigned char *buf, *p;
+	const EVP_MD *md;
+	uint8_t digest[EVP_MAX_MD_SIZE];
+	unsigned digest_length;
 	EVP_PKEY *pkey;
 	EVP_PKEY_CTX *pctx = NULL;
 	EVP_MD_CTX mctx;
-	unsigned signature_length = 0;
-	unsigned long n;
+	size_t signature_length = 0;
+	unsigned long n = 0;
 
 	EVP_MD_CTX_init(&mctx);
+	buf=(unsigned char *)s->init_buf->data;
 
 	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
 		{
 		p= ssl_handshake_start(s);
 		pkey = s->cert->key->privatekey;
-		/* For TLS v1.2 send signature algorithm and signature
-		 * using agreed digest and cached handshake records.
+		/* For TLS v1.2 send signature algorithm and signature using
+		 * agreed digest and cached handshake records. Otherwise, use
+		 * SHA1 or MD5 + SHA1 depending on key type.
 		 */
 		if (SSL_USE_SIGALGS(s))
 			{
 			long hdatalen = 0;
 			char *hdata;
-			const EVP_MD *md = s->cert->key->digest;
+			md = s->cert->key->digest;
 			hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
 								&hdata);
 			if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
@@ -2704,76 +2708,77 @@
 				goto err;
 				}
 			p += 2;
-#ifdef SSL_DEBUG
-			fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
-							EVP_MD_name(md));
-#endif
-			if (!EVP_SignInit_ex(&mctx, md, NULL)
-				|| !EVP_SignUpdate(&mctx, hdata, hdatalen)
-				|| !EVP_SignFinal(&mctx, p + 2,
-					&signature_length, pkey))
+			n += 2;
+			if (!EVP_DigestInit_ex(&mctx, md, NULL)
+				|| !EVP_DigestUpdate(&mctx, hdata, hdatalen)
+				|| !EVP_DigestFinal(&mctx, digest, &digest_length))
 				{
 				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
 				goto err;
 				}
-			s2n(signature_length, p);
-			n = signature_length + 4;
-			if (!ssl3_digest_cached_records(s))
-				goto err;
 			}
-		else
-		if (pkey->type == EVP_PKEY_RSA)
+		else if (pkey->type == EVP_PKEY_RSA)
 			{
-			s->method->ssl3_enc->cert_verify_mac(s, NID_md5, data);
+			s->method->ssl3_enc->cert_verify_mac(s, NID_md5, digest);
 			s->method->ssl3_enc->cert_verify_mac(s,
-				NID_sha1, &data[MD5_DIGEST_LENGTH]);
-			if (RSA_sign(NID_md5_sha1, data,
-					MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
-					&p[2], &signature_length, pkey->pkey.rsa) <= 0)
-				{
-				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_RSA_LIB);
-				goto err;
-				}
-			s2n(signature_length, p);
-			n = signature_length + 2;
+				NID_sha1, &digest[MD5_DIGEST_LENGTH]);
+			digest_length = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
+			/* Using a NULL signature MD makes EVP_PKEY_sign perform
+			 * a raw RSA signature, rather than wrapping in a
+			 * DigestInfo. */
+			md = NULL;
 			}
-		else
-#ifndef OPENSSL_NO_DSA
-		if (pkey->type == EVP_PKEY_DSA)
+		else if (pkey->type == EVP_PKEY_DSA || pkey->type == EVP_PKEY_EC)
 			{
-			s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, data);
-			if (!DSA_sign(pkey->save_type, data,
-					SHA_DIGEST_LENGTH, &(p[2]),
-					&signature_length, pkey->pkey.dsa))
-				{
-				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_DSA_LIB);
-				goto err;
-				}
-			s2n(signature_length, p);
-			n = signature_length + 2;
+			s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, digest);
+			digest_length = SHA_DIGEST_LENGTH;
+			md = EVP_sha1();
 			}
 		else
-#endif
-#ifndef OPENSSL_NO_ECDSA
-		if (pkey->type == EVP_PKEY_EC)
-			{
-			s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, data);
-			if (!ECDSA_sign(pkey->save_type, data,
-					SHA_DIGEST_LENGTH, &(p[2]),
-					&signature_length, pkey->pkey.ec))
-				{
-				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_ECDSA_LIB);
-				goto err;
-				}
-			s2n(signature_length, p);
-			n = signature_length + 2;
-			}
-		else
-#endif
 			{
 			OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
+
+		/* Sign the digest. */
+		pctx = EVP_PKEY_CTX_new(pkey, NULL);
+		if (pctx == NULL)
+			goto err;
+
+		/* Initialize the EVP_PKEY_CTX and determine the size of the signature. */
+		if (EVP_PKEY_sign_init(pctx) != 1 ||
+			EVP_PKEY_CTX_set_signature_md(pctx, md) != 1 ||
+			EVP_PKEY_sign(pctx, NULL, &signature_length,
+				digest, digest_length) != 1)
+			{
+			OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
+			goto err;
+			}
+
+		if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH)
+			{
+			OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, SSL_R_DATA_LENGTH_TOO_LONG);
+			goto err;
+			}
+
+		if (EVP_PKEY_sign(pctx, &p[2], &signature_length,
+				digest, digest_length) != 1)
+			{
+			OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
+			goto err;
+			}
+
+		s2n(signature_length, p);
+		n += signature_length + 2;
+
+		/* Now that client auth is completed, we no longer need cached
+		 * handshake records and can digest them. */
+		if (SSL_USE_SIGALGS(s))
+			{
+			if (!ssl3_digest_cached_records(s))
+				goto err;
+			}
+
 		ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
 		s->state=SSL3_ST_CW_CERT_VRFY_B;
 		}