diff options
author | Kurt Roeckx <kurt@roeckx.be> | 2020-02-09 19:28:15 +0100 |
---|---|---|
committer | Kurt Roeckx <kurt@roeckx.be> | 2020-02-16 11:55:42 +0100 |
commit | 57225c99ef848f0d0d1a7ab586a61ef71740f1ff (patch) | |
tree | b4c91a0e0eeadf0504c64f20388b16f183f2fd88 /ssl | |
parent | 42fc47964727fb2b12024eaf390c28fcb3caf561 (diff) |
Check that ed25519 and ed448 are allowed by the security level
Signature algorithms not using an MD weren't checked that they're
allowed by the security level.
Reviewed-by: Tomáš Mráz <tmraz@fedoraproject.org>
GH: #11062
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/t1_lib.c | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index d7ce6541d3..445ed7fc59 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -992,6 +992,31 @@ int tls_check_sigalg_curve(const SSL *s, int curve) #endif /* + * Return the number of security bits for the signature algorithm, or 0 on + * error. + */ +static int sigalg_security_bits(const SIGALG_LOOKUP *lu) +{ + const EVP_MD *md = NULL; + int secbits = 0; + + if (!tls1_lookup_md(lu, &md)) + return 0; + if (md != NULL) + { + /* Security bits: half digest bits */ + secbits = EVP_MD_size(md) * 4; + } else { + /* Values from https://tools.ietf.org/html/rfc8032#section-8.5 */ + if (lu->sigalg == TLSEXT_SIGALG_ed25519) + secbits = 128; + else if (lu->sigalg == TLSEXT_SIGALG_ed448) + secbits = 224; + } + return secbits; +} + +/* * Check signature algorithm is consistent with sent supported signature * algorithms and if so set relevant digest and signature scheme in * s. @@ -1004,6 +1029,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey) size_t sent_sigslen, i, cidx; int pkeyid = EVP_PKEY_id(pkey); const SIGALG_LOOKUP *lu; + int secbits = 0; /* Should never happen */ if (pkeyid == -1) @@ -1105,20 +1131,20 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey) SSL_R_UNKNOWN_DIGEST); 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)) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG, - SSL_R_WRONG_SIGNATURE_TYPE); - 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; + secbits = sigalg_security_bits(lu); + if (secbits == 0 || + !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits, + md != NULL ? EVP_MD_type(md) : NID_undef, + (void *)sigalgstr)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, 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; @@ -1625,11 +1651,8 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu) } } - 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 */ + secbits = sigalg_security_bits(lu); sigalgstr[0] = (lu->sigalg >> 8) & 0xff; sigalgstr[1] = lu->sigalg & 0xff; return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr); |