Handle signature algorithms with no associated digest

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3585)
This commit is contained in:
Dr. Stephen Henson 2017-06-14 16:54:08 +01:00
parent 3d234c9e5c
commit 168067b631
3 changed files with 48 additions and 23 deletions

View file

@ -2382,6 +2382,7 @@ __owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt);
__owur int tls1_process_sigalgs(SSL *s);
__owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey);
__owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd);
__owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs);
__owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey);
void ssl_set_client_disabled(SSL *s);

View file

@ -221,9 +221,8 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
goto err;
}
pkey = s->s3->tmp.cert->privatekey;
md = ssl_md(lu->hash_idx);
if (pkey == NULL || md == NULL) {
if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
@ -369,7 +368,11 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
goto f_err;
}
md = ssl_md(s->s3->tmp.peer_sigalg->hash_idx);
if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
/* Check for broken implementations of GOST ciphersuites */
/*

View file

@ -819,6 +819,25 @@ static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg)
}
return NULL;
}
/* Lookup hash: return 0 if invalid or not enabled */
int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
{
const EVP_MD *md;
if (lu == NULL)
return 0;
/* lu->hash == NID_undef means no associated digest */
if (lu->hash == NID_undef) {
md = NULL;
} else {
md = ssl_md(lu->hash_idx);
if (md == NULL)
return 0;
}
if (pmd)
*pmd = md;
return 1;
}
/*
* Return a signature algorithm for TLS < 1.2 where the signature type
* is fixed by the certificate type.
@ -830,9 +849,8 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
if (lu == NULL || ssl_md(lu->hash_idx) == NULL) {
if (!tls1_lookup_md(lu, NULL))
return NULL;
}
return lu;
}
return &legacy_rsa_sigalg;
@ -990,22 +1008,23 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
md = ssl_md(lu->hash_idx);
if (md == NULL) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
return 0;
if (!tls1_lookup_md(lu, &md)) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
return 0;
}
/*
* Make sure security callback allows algorithm. For historical reasons we
* have to pass the sigalg as a two byte char array.
*/
sigalgstr[0] = (sig >> 8) & 0xff;
sigalgstr[1] = sig & 0xff;
if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
EVP_MD_size(md) * 4, EVP_MD_type(md),
(void *)sigalgstr)) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
if (md != NULL) {
/*
* Make sure security callback allows algorithm. For historical
* reasons we have to pass the sigalg as a two byte char array.
*/
sigalgstr[0] = (sig >> 8) & 0xff;
sigalgstr[1] = sig & 0xff;
if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
EVP_MD_size(md) * 4, EVP_MD_type(md),
(void *)sigalgstr)) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
/* Store the sigalg the peer uses */
s->s3->tmp.peer_sigalg = lu;
@ -1423,7 +1442,7 @@ static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu)
int secbits;
/* See if sigalgs is recognised and if hash is enabled */
if (lu == NULL || ssl_md(lu->hash_idx) == NULL)
if (!tls1_lookup_md(lu, NULL))
return 0;
/* DSA is not allowed in TLS 1.3 */
if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
@ -1431,6 +1450,8 @@ static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu)
/* See if public key algorithm allowed */
if (tls12_get_pkey_idx(lu->sig) == -1)
return 0;
if (lu->hash == NID_undef)
return 1;
/* Security bits: half digest bits */
secbits = EVP_MD_size(ssl_md(lu->hash_idx)) * 4;
/* Finally see if security callback allows it */
@ -1772,7 +1793,7 @@ static int sig_cb(const char *elem, int len, void *arg)
get_sigorhash(&sig_alg, &hash_alg, p);
}
if (sig_alg == NID_undef || hash_alg == NID_undef)
if (sig_alg == NID_undef || (p != NULL && hash_alg == NID_undef))
return 0;
for (i = 0; i < sarg->sigalgcnt; i += 2) {
@ -2305,7 +2326,7 @@ int tls_choose_sigalg(SSL *s, int *al)
|| lu->sig == EVP_PKEY_DSA
|| lu->sig == EVP_PKEY_RSA)
continue;
if (ssl_md(lu->hash_idx) == NULL)
if (!tls1_lookup_md(lu, NULL))
continue;
idx = lu->sig_idx;
if (!ssl_has_cert(s, idx))