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:
parent
af9d9419a6
commit
00505ec2e1
@ -112,6 +112,10 @@ static const TEST_VECTOR kTestVectors[] = {
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
|
||||
|
||||
/* MD5-SHA1 tests. */
|
||||
{ &EVP_md5_sha1, NULL, "abc", 1,
|
||||
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
|
||||
};
|
||||
|
||||
static int compare_digest(const TEST_VECTOR *test,
|
||||
|
@ -193,6 +193,45 @@ static const EVP_MD 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 {
|
||||
int nid;
|
||||
const EVP_MD *(*md_func)();
|
||||
@ -205,6 +244,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
|
||||
{ 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 },
|
||||
|
@ -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_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);
|
||||
|
@ -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)
|
||||
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)
|
||||
{
|
||||
|
@ -1428,8 +1428,14 @@ int ssl3_get_server_key_exchange(SSL *s)
|
||||
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 @@ int ssl3_get_server_key_exchange(SSL *s)
|
||||
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(¶meter), CBS_len(¶meter)) ||
|
||||
!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(¶meter), CBS_len(¶meter));
|
||||
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(¶meter), CBS_len(¶meter)) ||
|
||||
!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
|
||||
|
@ -1201,10 +1201,6 @@ int ssl3_send_server_done(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;
|
||||
EC_KEY *ecdh=NULL, *ecdhp;
|
||||
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])
|
||||
* 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);
|
||||
|
Loading…
Reference in New Issue
Block a user