diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2019-02-02 09:13:40 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2019-02-06 12:52:41 +0100 |
commit | aaf286293050a4a2dbcd98d9eb2d69eca99c502a (patch) | |
tree | b8e74a52a784152ebc2d733f999e66add9e30bb7 /lib | |
parent | daf6650142f63c0f602b99c92ba941ff1d9f851c (diff) | |
download | gnutls-aaf286293050a4a2dbcd98d9eb2d69eca99c502a.tar.gz |
Fallback to TLS 1.2 when incompatible with signature certs are provided
This only takes into account certificates in the credentials structure.
If certificates are provided in a callback, these must be checked by
the provider. For that we assume that the credentials structure is
filled when associated with a session; if not then the fallback mechanism
will not work and the handshake will fail.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/algorithms/ciphersuites.c | 2 | ||||
-rw-r--r-- | lib/auth.c | 23 | ||||
-rw-r--r-- | lib/auth/cert.h | 3 | ||||
-rw-r--r-- | lib/handshake.c | 8 |
4 files changed, 33 insertions, 3 deletions
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c index b97bbc82db..7269861ffe 100644 --- a/lib/algorithms/ciphersuites.c +++ b/lib/algorithms/ciphersuites.c @@ -1578,7 +1578,7 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session, /* RFC7919 requires that we reply with insufficient security if we have * negotiated an FFDHE group, but cannot find a common ciphersuite. However, * we must also distinguish between not matching a ciphersuite due to an - * incompatible certificate which we traditionally return GNUTLS_E_INSUFFICIENT_SECURITY. + * incompatible certificate which we traditionally return GNUTLS_E_NO_CIPHER_SUITES. */ if (!no_cert_found && (session->internals.hsk_flags & HSK_HAVE_FFDHE) && session->internals.priorities->groups.have_ffdhe && !version->tls13_sem) diff --git a/lib/auth.c b/lib/auth.c index 91a67c9afa..dd3fc861fb 100644 --- a/lib/auth.c +++ b/lib/auth.c @@ -138,6 +138,29 @@ gnutls_credentials_set(gnutls_session_t session, } } + /* sanity tests */ + if (type == GNUTLS_CRD_CERTIFICATE) { + gnutls_certificate_credentials_t c = cred; + unsigned i; + bool allow_tls13 = 0; + unsigned key_usage; + + if (c != NULL && c->ncerts != 0) { + for (i = 0; i < c->ncerts; i++) { + key_usage = get_key_usage(session, c->certs[i].cert_list[0].pubkey); + if (key_usage == 0 || (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) { + allow_tls13 = 1; + break; + } + } + + if (!allow_tls13) { + /* to prevent the server random indicate TLS1.3 support */ + session->internals.flags |= INT_FLAG_NO_TLS13; + } + } + } + return 0; } diff --git a/lib/auth/cert.h b/lib/auth/cert.h index 3d653cb81c..fd66628820 100644 --- a/lib/auth/cert.h +++ b/lib/auth/cert.h @@ -174,7 +174,8 @@ int _gnutls_proc_rawpk_crt(gnutls_session_t session, inline static unsigned get_key_usage(gnutls_session_t session, gnutls_pubkey_t pubkey) { - if (unlikely(session->internals.priorities->allow_server_key_usage_violation)) + if (unlikely(session->internals.priorities && + session->internals.priorities->allow_server_key_usage_violation)) return 0; else return pubkey->key_usage; diff --git a/lib/handshake.c b/lib/handshake.c index 70b4486266..481210ebc0 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -444,6 +444,9 @@ _gnutls_negotiate_version(gnutls_session_t session, if (aversion && aversion->id == GNUTLS_TLS1_2) { vers = _gnutls_version_max(session); + if (unlikely(vers == NULL)) + return gnutls_assert_val(GNUTLS_E_NO_CIPHER_SUITES); + if (vers->id >= GNUTLS_TLS1_2) { session->security_parameters.pversion = aversion; return 0; @@ -2138,7 +2141,10 @@ static int send_client_hello(gnutls_session_t session, int again) if (hver == NULL) { gnutls_assert(); - ret = GNUTLS_E_NO_PRIORITIES_WERE_SET; + if (session->internals.flags & INT_FLAG_NO_TLS13) + ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS; + else + ret = GNUTLS_E_NO_PRIORITIES_WERE_SET; goto cleanup; } |