From c3f6a3f82855fa5e55e21aca8c85d4a612ba89d7 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 28 Sep 2017 07:47:40 +0200 Subject: handshake: only attempt to detect downgrade attacks if TLS1.3 is supported Otherwise, connections under TLS 1.2 may fail, even if client never enabled TLS 1.3 support. Signed-off-by: Nikos Mavrogiannopoulos --- lib/handshake.c | 101 +++++++++++++++++++++++++++++------------------------ lib/handshake.h | 2 +- lib/sslv2_compat.c | 2 +- 3 files changed, 57 insertions(+), 48 deletions(-) diff --git a/lib/handshake.c b/lib/handshake.c index 7f249f845f..3e9da188d1 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -193,60 +193,69 @@ int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd) return 0; } +static int _gnutls_set_server_random(gnutls_session_t session, int version, uint8_t * rnd) +{ + memcpy(session->security_parameters.server_random, rnd, + GNUTLS_RANDOM_SIZE); + + /* check whether the server random value is set according to + * to TLS 1.3. p4.1.3 requirements */ + if (!IS_DTLS(session) && version <= GNUTLS_TLS1_2 && + _gnutls_version_is_supported(session, GNUTLS_TLS1_3)) { + if (version == GNUTLS_TLS1_2 && + memcmp(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], + "\x44\x4F\x57\x4E\x47\x52\x44\x01", 8) == 0) { + _gnutls_audit_log(session, + "Detected downgrade to TLS 1.2 from TLS 1.3\n"); + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } else if (version <= GNUTLS_TLS1_1 && + memcmp(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], + "\x44\x4F\x57\x4E\x47\x52\x44\x00", 8) == 0) { + _gnutls_audit_log(session, + "Detected downgrade to TLS 1.1 or earlier from TLS 1.3\n"); + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + } + + return 0; +} + +int _gnutls_gen_server_random(gnutls_session_t session, int version) { int ret; - if (rnd != NULL) { /* client */ - memcpy(session->security_parameters.server_random, rnd, + if (session->internals.sc_random_set != 0) { + memcpy(session->security_parameters.server_random, + session->internals. + resumed_security_parameters.server_random, GNUTLS_RANDOM_SIZE); + return 0; + } - /* check whether the server random value is set according to - * to TLS 1.3. p4.1.3 requirements */ - if (version <= GNUTLS_TLS1_2 && _gnutls_version_is_supported(session, GNUTLS_TLS1_3)) { - if (version == GNUTLS_TLS1_2 && - memcmp(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], - "\x44\x4F\x57\x4E\x47\x52\x44\x01", 8) == 0) { - _gnutls_audit_log(session, - "Detected downgrade to TLS 1.2 from TLS 1.3\n"); - return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); - } else if (version <= GNUTLS_TLS1_1 && - memcmp(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], - "\x44\x4F\x57\x4E\x47\x52\x44\x00", 8) == 0) { - _gnutls_audit_log(session, - "Detected downgrade to TLS 1.1 or earlier from TLS 1.3\n"); - return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); - } - } - - } else { /* server */ - if (session->internals.sc_random_set != 0) { - memcpy(session->security_parameters.server_random, - session->internals. - resumed_security_parameters.server_random, - GNUTLS_RANDOM_SIZE); + if (!IS_DTLS(session) && _gnutls_version_is_supported(session, GNUTLS_TLS1_3) && + version <= GNUTLS_TLS1_2) { + if (version == GNUTLS_TLS1_2) { + memcpy(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], + "\x44\x4F\x57\x4E\x47\x52\x44\x01", 8); + ret = + gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE-8); } else { - if (version == GNUTLS_TLS1_2) { - memcpy(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], - "\x44\x4F\x57\x4E\x47\x52\x44\x01", 8); - ret = - gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE-8); - } else if (version <= GNUTLS_TLS1_1) { - memcpy(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], - "\x44\x4F\x57\x4E\x47\x52\x44\x00", 8); - ret = - gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE-8); - } else { - ret = - gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); - } - - if (ret < 0) { - gnutls_assert(); - return ret; - } + memcpy(&session->security_parameters.server_random[GNUTLS_RANDOM_SIZE-8-1], + "\x44\x4F\x57\x4E\x47\x52\x44\x00", 8); + ret = + gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE-8); } + } else { + ret = + gnutls_rnd(GNUTLS_RND_NONCE, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); + } + + if (ret < 0) { + gnutls_assert(); + return ret; } + return 0; } @@ -487,7 +496,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data, pos += GNUTLS_RANDOM_SIZE; - ret = _gnutls_set_server_random(session, neg_version, NULL); + ret = _gnutls_gen_server_random(session, neg_version); if (ret < 0) return gnutls_assert_val(ret); diff --git a/lib/handshake.h b/lib/handshake.h index 0e63ee39b4..b491ba1e51 100644 --- a/lib/handshake.h +++ b/lib/handshake.h @@ -61,7 +61,7 @@ int _gnutls_recv_handshake(gnutls_session_t session, gnutls_handshake_description_t type, unsigned int optional, gnutls_buffer_st * buf); int _gnutls_generate_session_id(uint8_t * session_id, uint8_t * len); -int _gnutls_set_server_random(gnutls_session_t session, int version, uint8_t * rnd); +int _gnutls_gen_server_random(gnutls_session_t session, int version); int _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd); int _gnutls_find_pk_algos_in_ciphersuites(uint8_t * data, int datalen); diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c index f8eff3b151..43890f3c94 100644 --- a/lib/sslv2_compat.c +++ b/lib/sslv2_compat.c @@ -213,7 +213,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data, return gnutls_assert_val(ret); /* generate server random value */ - ret = _gnutls_set_server_random(session, neg_version, NULL); + ret = _gnutls_gen_server_random(session, neg_version); if (ret < 0) return gnutls_assert_val(ret); -- cgit v1.2.1