From 6f54ae7a9079983ea51593d4a91699d14a9c9a99 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 19 Oct 2018 14:01:22 +0100 Subject: [PATCH] Don't negotiate TLSv1.3 if our EC cert isn't TLSv1.3 capable TLSv1.3 is more restrictive about the curve used. There must be a matching sig alg defined for that curve. Therefore if we are using some other curve in our certificate then we should not negotiate TLSv1.3. Fixes #7435 Reviewed-by: Viktor Dukhovni (Merged from https://github.com/openssl/openssl/pull/7442) (cherry picked from commit de4dc598024fd0a9c2b7a466fd5323755d369522) --- ssl/ssl_locl.h | 1 + ssl/statem/statem_lib.c | 18 ++++++++++++++++-- ssl/t1_lib.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index c22c1f9ee8..46719b00ca 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -2564,6 +2564,7 @@ __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 tls_check_sigalg_curve(const SSL *s, int curve); __owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey); __owur int ssl_set_client_disabled(SSL *s); __owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int echde); diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 75cf321b98..dc2bd20e93 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1506,7 +1506,8 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method) */ static int is_tls13_capable(const SSL *s) { - int i; + int i, curve; + EC_KEY *eckey; #ifndef OPENSSL_NO_PSK if (s->psk_server_callback != NULL) @@ -1527,7 +1528,20 @@ static int is_tls13_capable(const SSL *s) default: break; } - if (ssl_has_cert(s, i)) + if (!ssl_has_cert(s, i)) + continue; + if (i != SSL_PKEY_ECC) + return 1; + /* + * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is + * more restrictive so check that our sig algs are consistent with this + * EC cert. See section 4.2.3 of RFC8446. + */ + eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); + if (eckey == NULL) + continue; + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + if (tls_check_sigalg_curve(s, curve)) return 1; } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index b8b9fbda39..8e73d06c61 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -949,6 +949,37 @@ size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs) } } +/* + * Called by servers only. Checks that we have a sig alg that supports the + * specified EC curve. + */ +int tls_check_sigalg_curve(const SSL *s, int curve) +{ + const uint16_t *sigs; + size_t siglen, i; + + if (s->cert->conf_sigalgs) { + sigs = s->cert->conf_sigalgs; + siglen = s->cert->conf_sigalgslen; + } else { + sigs = tls12_sigalgs; + siglen = OSSL_NELEM(tls12_sigalgs); + } + + for (i = 0; i < siglen; i++) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]); + + if (lu == NULL) + continue; + if (lu->sig == EVP_PKEY_EC + && lu->curve != NID_undef + && curve == lu->curve) + return 1; + } + + return 0; +} + /* * Check signature algorithm is consistent with sent supported signature * algorithms and if so set relevant digest and signature scheme in -- 2.25.1