summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2018-10-19 14:01:22 +0100
committerMatt Caswell <matt@openssl.org>2018-11-12 11:19:58 +0000
commit6f54ae7a9079983ea51593d4a91699d14a9c9a99 (patch)
tree589c98c8074d40879fe96687a4d6d38b61138512 /ssl
parent61e78e7ace6c5d65910379556d7da7d23492291c (diff)
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 <viktor@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7442) (cherry picked from commit de4dc598024fd0a9c2b7a466fd5323755d369522)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/ssl_locl.h1
-rw-r--r--ssl/statem/statem_lib.c18
-rw-r--r--ssl/t1_lib.c31
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
@@ -950,6 +950,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
* s.