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>
This commit is contained in:
David Benjamin 2014-11-26 16:38:00 -05:00 committed by David Benjamin
parent af9d9419a6
commit 00505ec2e1
6 changed files with 95 additions and 103 deletions

View File

@ -112,6 +112,10 @@ static const TEST_VECTOR kTestVectors[] = {
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1, "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" }, "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
/* MD5-SHA1 tests. */
{ &EVP_md5_sha1, NULL, "abc", 1,
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
}; };
static int compare_digest(const TEST_VECTOR *test, static int compare_digest(const TEST_VECTOR *test,

View File

@ -193,6 +193,45 @@ static const EVP_MD sha512_md = {
const EVP_MD *EVP_sha512(void) { return &sha512_md; } 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 { struct nid_to_digest {
int nid; int nid;
const EVP_MD *(*md_func)(); const EVP_MD *(*md_func)();
@ -205,6 +244,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
{ NID_sha256, EVP_sha256 }, { NID_sha256, EVP_sha256 },
{ NID_sha384, EVP_sha384 }, { NID_sha384, EVP_sha384 },
{ NID_sha512, EVP_sha512 }, { NID_sha512, EVP_sha512 },
{ NID_md5_sha1, EVP_md5_sha1 },
{ NID_dsaWithSHA, EVP_sha1 }, { NID_dsaWithSHA, EVP_sha1 },
{ NID_dsaWithSHA1, EVP_sha1 }, { NID_dsaWithSHA1, EVP_sha1 },
{ NID_ecdsa_with_SHA1, EVP_sha1 }, { NID_ecdsa_with_SHA1, EVP_sha1 },

View File

@ -84,6 +84,10 @@ OPENSSL_EXPORT const EVP_MD *EVP_sha256(void);
OPENSSL_EXPORT const EVP_MD *EVP_sha384(void); OPENSSL_EXPORT const EVP_MD *EVP_sha384(void);
OPENSSL_EXPORT const EVP_MD *EVP_sha512(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 /* EVP_get_digestbynid returns an |EVP_MD| for the given NID, or NULL if no
* such digest is known. */ * such digest is known. */
OPENSSL_EXPORT const EVP_MD *EVP_get_digestbynid(int nid); OPENSSL_EXPORT const EVP_MD *EVP_get_digestbynid(int nid);

View File

@ -523,10 +523,7 @@ int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, const EVP_MD **
NID_sha1, out + MD5_DIGEST_LENGTH) == 0) NID_sha1, out + MD5_DIGEST_LENGTH) == 0)
return 0; return 0;
*out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH; *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
/* Using a NULL signature MD makes EVP_PKEY_sign perform *out_md = EVP_md5_sha1();
* a raw RSA signature, rather than wrapping in a
* DigestInfo. */
*out_md = NULL;
} }
else if (pkey->type == EVP_PKEY_EC) else if (pkey->type == EVP_PKEY_EC)
{ {

View File

@ -1428,8 +1428,14 @@ int ssl3_get_server_key_exchange(SSL *s)
if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey))
goto f_err; goto f_err;
} }
else if (pkey->type == EVP_PKEY_RSA)
{
md = EVP_md5_sha1();
}
else else
{
md = EVP_sha1(); md = EVP_sha1();
}
/* The last field in |server_key_exchange| is the /* The last field in |server_key_exchange| is the
* signature. */ * signature. */
@ -1441,47 +1447,16 @@ int ssl3_get_server_key_exchange(SSL *s)
goto f_err; 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; /* bad signature */
unsigned char *q, md_buf[EVP_MAX_MD_SIZE*2]; al=SSL_AD_DECRYPT_ERROR;
size_t md_len = 0; OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
goto f_err;
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;
}
} }
} }
else else

View File

@ -1201,10 +1201,6 @@ int ssl3_send_server_done(SSL *s)
int ssl3_send_server_key_exchange(SSL *s) 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; DH *dh=NULL,*dhp;
EC_KEY *ecdh=NULL, *ecdhp; EC_KEY *ecdh=NULL, *ecdhp;
unsigned char *encodedPoint = NULL; unsigned char *encodedPoint = NULL;
@ -1506,68 +1502,44 @@ int ssl3_send_server_key_exchange(SSL *s)
{ {
/* n is the length of the params, they start at &(d[4]) /* n is the length of the params, they start at &(d[4])
* and p points to the space at the end. */ * 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; md = tls1_choose_signing_digest(s, pkey);
j=0; if (!tls12_get_sigandhash(p, pkey, md))
for (num=2; num > 0; num--)
{ {
EVP_DigestInit_ex(&md_ctx, /* Should never happen */
(num == 2) ? EVP_md5() : EVP_sha1(), NULL); al=SSL_AD_INTERNAL_ERROR;
EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR);
EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); goto f_err;
EVP_DigestUpdate(&md_ctx,d,n);
EVP_DigestFinal_ex(&md_ctx,q,
(unsigned int *)&i);
q+=i;
j+=i;
} }
if (RSA_sign(NID_md5_sha1, md_buf, j, p+=2;
&(p[2]), &u, pkey->pkey.rsa) <= 0) }
{ else if (pkey->type == EVP_PKEY_RSA)
OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_RSA); {
goto err; md = EVP_md5_sha1();
}
s2n(u,p);
n+=u+2;
} }
else else
{ {
const EVP_MD *md; md = EVP_sha1();
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;
} }
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); ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n);