Add EVP_md5_sha1.

Use it in ssl3_cert_verify_hash so signing a pre-TLS-1.2 handshake hash can go
through RSA_sign and be intercepted via RSA_METHOD appropriately. This avoids
Windows needing to intercept sign_raw. (CAPI keys cannot provide sign_raw,
unless the input size happens to be that of NID_md5_sha1.)

Also use it in processing ServerKeyExchange to avoid special-casing RSA.

BUG=crbug.com/437023

Change-Id: Ia07433f468b75fdf7bfc8fa90c9751639b2478e6
Reviewed-on: https://boringssl-review.googlesource.com/2420
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/digest/digest_test.c b/crypto/digest/digest_test.c
index 7c37cb5..6c73e95 100644
--- a/crypto/digest/digest_test.c
+++ b/crypto/digest/digest_test.c
@@ -112,6 +112,10 @@
       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
       "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
       "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
+
+    /* MD5-SHA1 tests. */
+    { &EVP_md5_sha1, NULL, "abc", 1,
+      "900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
 };
 
 static int compare_digest(const TEST_VECTOR *test,
diff --git a/crypto/digest/digests.c b/crypto/digest/digests.c
index e3d3a87..52d446f 100644
--- a/crypto/digest/digests.c
+++ b/crypto/digest/digests.c
@@ -193,6 +193,45 @@
 
 const EVP_MD *EVP_sha512(void) { return &sha512_md; }
 
+
+typedef struct {
+  MD5_CTX md5;
+  SHA_CTX sha1;
+} MD5_SHA1_CTX;
+
+static int md5_sha1_init(EVP_MD_CTX *md_ctx) {
+  MD5_SHA1_CTX *ctx = md_ctx->md_data;
+  return MD5_Init(&ctx->md5) && SHA1_Init(&ctx->sha1);
+}
+
+static int md5_sha1_update(EVP_MD_CTX *md_ctx, const void *data, size_t count) {
+  MD5_SHA1_CTX *ctx = md_ctx->md_data;
+  return MD5_Update(&ctx->md5, data, count) && SHA1_Update(&ctx->sha1, data, count);
+}
+
+static int md5_sha1_final(EVP_MD_CTX *md_ctx, unsigned char *out) {
+  MD5_SHA1_CTX *ctx = md_ctx->md_data;
+  if (!MD5_Final(out, &ctx->md5) ||
+      !SHA1_Final(out + MD5_DIGEST_LENGTH, &ctx->sha1)) {
+    return 0;
+  }
+  return 1;
+}
+
+static const EVP_MD md5_sha1_md = {
+    NID_md5_sha1,
+    MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+    0 /* flags */,
+    md5_sha1_init,
+    md5_sha1_update,
+    md5_sha1_final,
+    64 /* block size */,
+    sizeof(MD5_SHA1_CTX),
+};
+
+const EVP_MD *EVP_md5_sha1(void) { return &md5_sha1_md; }
+
+
 struct nid_to_digest {
   int nid;
   const EVP_MD *(*md_func)();
@@ -205,6 +244,7 @@
   { NID_sha256, EVP_sha256 },
   { NID_sha384, EVP_sha384 },
   { NID_sha512, EVP_sha512 },
+  { NID_md5_sha1, EVP_md5_sha1 },
   { NID_dsaWithSHA, EVP_sha1 },
   { NID_dsaWithSHA1, EVP_sha1 },
   { NID_ecdsa_with_SHA1, EVP_sha1 },
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index a453ea3..864917e 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -84,6 +84,10 @@
 OPENSSL_EXPORT const EVP_MD *EVP_sha384(void);
 OPENSSL_EXPORT const EVP_MD *EVP_sha512(void);
 
+/* EVP_md5_sha1 is a TLS-specific |EVP_MD| which computes the concatenation of
+ * MD5 and SHA-1, as used in TLS 1.1 and below. */
+OPENSSL_EXPORT const EVP_MD *EVP_md5_sha1(void);
+
 /* EVP_get_digestbynid returns an |EVP_MD| for the given NID, or NULL if no
  * such digest is known. */
 OPENSSL_EXPORT const EVP_MD *EVP_get_digestbynid(int nid);
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index d040317..17d18d4 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -523,10 +523,7 @@
 				NID_sha1, out + MD5_DIGEST_LENGTH) == 0)
 			return 0;
 		*out_len = 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. */
-		*out_md = NULL;
+		*out_md = EVP_md5_sha1();
 		}
 	else if (pkey->type == EVP_PKEY_EC)
 		{
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 17b4f9a..cbde84f 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1428,8 +1428,14 @@
 			if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey))
 				goto f_err;
 			}
+		else if (pkey->type == EVP_PKEY_RSA)
+			{
+			md = EVP_md5_sha1();
+			}
 		else
+			{
 			md = EVP_sha1();
+			}
 
 		/* The last field in |server_key_exchange| is the
 		 * signature. */
@@ -1441,47 +1447,16 @@
 			goto f_err;
 			}
 
-		if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s))
+		if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
+			!EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
+			!EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
+			!EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter), CBS_len(&parameter)) ||
+			!EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature)))
 			{
-			int num;
-			unsigned char *q, md_buf[EVP_MAX_MD_SIZE*2];
-			size_t md_len = 0;
-
-			q=md_buf;
-			for (num=2; num > 0; num--)
-				{
-				unsigned int digest_len;
-				EVP_DigestInit_ex(&md_ctx,
-					(num == 2) ? EVP_md5() : EVP_sha1(), NULL);
-				EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
-				EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-				EVP_DigestUpdate(&md_ctx, CBS_data(&parameter), CBS_len(&parameter));
-				EVP_DigestFinal_ex(&md_ctx, q, &digest_len);
-				q += digest_len;
-				md_len += digest_len;
-				}
-			if (!RSA_verify(NID_md5_sha1, md_buf, md_len,
-					CBS_data(&signature), CBS_len(&signature),
-					pkey->pkey.rsa))
-				{
-				al = SSL_AD_DECRYPT_ERROR;
-				OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
-				goto f_err;
-				}
-			}
-		else
-			{
-			if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
-				!EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
-				!EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
-				!EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter), CBS_len(&parameter)) ||
-				!EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature)))
-				{
-				/* bad signature */
-				al=SSL_AD_DECRYPT_ERROR;
-				OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
-				goto f_err;
-				}
+			/* bad signature */
+			al=SSL_AD_DECRYPT_ERROR;
+			OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
+			goto f_err;
 			}
 		}
 	else
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index d915fc8..998f1b4 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1201,10 +1201,6 @@
 
 int ssl3_send_server_key_exchange(SSL *s)
 	{
-	unsigned char *q;
-	int j,num;
-	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
-	unsigned int u;
 	DH *dh=NULL,*dhp;
 	EC_KEY *ecdh=NULL, *ecdhp;
 	unsigned char *encodedPoint = NULL;
@@ -1506,68 +1502,44 @@
 			{
 			/* n is the length of the params, they start at &(d[4])
 			 * and p points to the space at the end. */
-			if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s))
+			const EVP_MD *md;
+			size_t sig_len = EVP_PKEY_size(pkey);
+
+			/* Determine signature algorithm. */
+			if (SSL_USE_SIGALGS(s))
 				{
-				q=md_buf;
-				j=0;
-				for (num=2; num > 0; num--)
+				md = tls1_choose_signing_digest(s, pkey);
+				if (!tls12_get_sigandhash(p, pkey, md))
 					{
-					EVP_DigestInit_ex(&md_ctx,
-						(num == 2) ? EVP_md5() : EVP_sha1(), NULL);
-					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
-					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-					EVP_DigestUpdate(&md_ctx,d,n);
-					EVP_DigestFinal_ex(&md_ctx,q,
-						(unsigned int *)&i);
-					q+=i;
-					j+=i;
+					/* Should never happen */
+					al=SSL_AD_INTERNAL_ERROR;
+					OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR);
+					goto f_err;
 					}
-				if (RSA_sign(NID_md5_sha1, md_buf, j,
-					&(p[2]), &u, pkey->pkey.rsa) <= 0)
-					{
-					OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_RSA);
-					goto err;
-					}
-				s2n(u,p);
-				n+=u+2;
+				p+=2;
+				}
+			else if (pkey->type == EVP_PKEY_RSA)
+				{
+				md = EVP_md5_sha1();
 				}
 			else
 				{
-				const EVP_MD *md;
-				size_t sig_len = EVP_PKEY_size(pkey);
-
-
-				/* send signature algorithm */
-				if (SSL_USE_SIGALGS(s))
-					{
-					md = tls1_choose_signing_digest(s, pkey);
-					if (!tls12_get_sigandhash(p, pkey, md))
-						{
-						/* Should never happen */
-						al=SSL_AD_INTERNAL_ERROR;
-						OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR);
-						goto f_err;
-						}
-					p+=2;
-					}
-				else
-					{
-					md = EVP_sha1();
-					}
-				if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) ||
-					!EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
-					!EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
-					!EVP_DigestSignUpdate(&md_ctx, d, n) ||
-					!EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len))
-					{
-					OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP);
-					goto err;
-					}
-				s2n(sig_len, p);
-				n += sig_len + 2;
-				if (SSL_USE_SIGALGS(s))
-					n += 2;
+				md = EVP_sha1();
 				}
+
+			if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) ||
+				!EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
+				!EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
+				!EVP_DigestSignUpdate(&md_ctx, d, n) ||
+				!EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len))
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP);
+				goto err;
+				}
+			s2n(sig_len, p);
+			n += sig_len + 2;
+			if (SSL_USE_SIGALGS(s))
+				n += 2;
 			}
 
 		ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n);