From ff41f1d0a860685f2df0b12dd65ad4f9f2da36c0 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 10 Dec 2017 15:26:28 +0100 Subject: handshake: check SCSVs prior to resuming a session This ensures that extensions which are also available as SCSVs are parsed prior to resuming a session. This resolves an issue with openssl sending SCSV instead of an extension for the safe renegotiation. Resolves #259 Signed-off-by: Nikos Mavrogiannopoulos --- lib/gnutls_handshake.c | 16 ++++++++++++++-- lib/gnutls_handshake.h | 2 +- lib/gnutls_v2_compat.c | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index dd773428be..cef29c35da 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -553,8 +553,13 @@ read_client_hello(gnutls_session_t session, uint8_t * data, pos += 2; DECR_LEN(len, suite_size); + suite_ptr = &data[pos]; pos += suite_size; + ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1); + if (ret < 0) + return gnutls_assert_val(ret); + DECR_LEN(len, 1); comp_size = data[pos++]; /* z is the number of compression methods */ DECR_LEN(len, comp_size); @@ -653,6 +658,10 @@ read_client_hello(gnutls_session_t session, uint8_t * data, max_record_send_size = session->security_parameters.max_record_send_size; + ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1); + if (ret < 0) + return gnutls_assert_val(ret); + ret = resume_copy_required_values(session); if (ret < 0) return gnutls_assert_val(ret); @@ -662,7 +671,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data, /* select an appropriate cipher suite */ - ret = _gnutls_server_select_suite(session, suite_ptr, suite_size); + ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 0); if (ret < 0) { gnutls_assert(); return ret; @@ -900,7 +909,7 @@ server_find_pk_algos_in_ciphersuites(const uint8_t * */ int _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data, - unsigned int datalen) + unsigned int datalen, unsigned scsv_only) { int ret; unsigned int i, j, cipher_suites_size; @@ -935,6 +944,9 @@ _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data, } } + if (scsv_only) + return 0; + pk_algos_size = MAX_ALGOS; ret = server_find_pk_algos_in_ciphersuites(data, datalen, pk_algos, diff --git a/lib/gnutls_handshake.h b/lib/gnutls_handshake.h index 88a4169b6d..ddb589ee1b 100644 --- a/lib/gnutls_handshake.h +++ b/lib/gnutls_handshake.h @@ -38,7 +38,7 @@ int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd); int _gnutls_find_pk_algos_in_ciphersuites(uint8_t * data, int datalen); int _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data, - unsigned int datalen); + unsigned int datalen, unsigned scsv_only); int _gnutls_negotiate_version(gnutls_session_t session, gnutls_protocol_t adv_version); diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c index 42fd3c5491..267aeabf01 100644 --- a/lib/gnutls_v2_compat.c +++ b/lib/gnutls_v2_compat.c @@ -74,7 +74,7 @@ _gnutls_handshake_select_v2_suite(gnutls_session_t session, } } - ret = _gnutls_server_select_suite(session, _data, _datalen); + ret = _gnutls_server_select_suite(session, _data, _datalen, 0); gnutls_free(_data); return ret; -- cgit v1.2.1