From dc9f6c68dfbfe5b8d6413b76c5bb6b1353edabf6 Mon Sep 17 00:00:00 2001 From: Pascal Knecht Date: Sun, 17 Jan 2021 16:33:02 +0100 Subject: [PATCH] libtls: Add downgrade protection for TLS 1.3 and TLS 1.2 Section 4.1.3 in RFC 8446 defines a new downgrade protection mechanism that also affects TLS 1.2. --- src/libtls/tls.c | 9 ++++++++- src/libtls/tls.h | 8 +++++++- src/libtls/tls_peer.c | 20 +++++++++++++++++++- src/libtls/tls_server.c | 20 +++++++++++++++++++- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/libtls/tls.c b/src/libtls/tls.c index 8b9911a..da45f4b 100644 --- a/src/libtls/tls.c +++ b/src/libtls/tls.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2021 Tobias Brunner - * Copyright (C) 2020 Pascal Knecht + * Copyright (C) 2020-2021 Pascal Knecht * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2010 Martin Willi @@ -153,6 +153,13 @@ chunk_t tls_hello_retry_request_magic = chunk_from_chars( 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C, ); +chunk_t tls_downgrade_protection_tls11 = chunk_from_chars( + 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00, +); +chunk_t tls_downgrade_protection_tls12 = chunk_from_chars( + 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01, +); + /** * TLS record */ diff --git a/src/libtls/tls.h b/src/libtls/tls.h index 5a11f70..9de042b 100644 --- a/src/libtls/tls.h +++ b/src/libtls/tls.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2021 Tobias Brunner - * Copyright (C) 2020 Pascal Knecht + * Copyright (C) 2020-2021 Pascal Knecht * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2010 Martin Willi @@ -214,6 +214,12 @@ extern enum_name_t *tls_extension_names; extern chunk_t tls_hello_retry_request_magic; /** + * Magic values for downgrade protection (see RFC 8446, section 4.1.3) + */ +extern chunk_t tls_downgrade_protection_tls11; +extern chunk_t tls_downgrade_protection_tls12; + +/** * A bottom-up driven TLS stack, suitable for EAP implementations. */ struct tls_t { diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c index 9d797f3..dac3aca 100644 --- a/src/libtls/tls_peer.c +++ b/src/libtls/tls_peer.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2020 Tobias Brunner - * Copyright (C) 2020 Pascal Knecht + * Copyright (C) 2020-2021 Pascal Knecht * Copyright (C) 2020 Méline Sieber * HSR Hochschule fuer Technik Rapperswil * @@ -208,6 +208,7 @@ static status_t process_server_hello(private_tls_peer_t *this, chunk_t msg, random, session, ext = chunk_empty, key_share = chunk_empty; chunk_t cookie = chunk_empty; tls_cipher_suite_t suite = 0; + tls_version_t version_max; bool is_retry_request; msg = reader->peek(reader); @@ -286,6 +287,23 @@ static status_t process_server_hello(private_tls_peer_t *this, } extensions->destroy(extensions); + /* downgrade protection (see RFC 8446, section 4.1.3) */ + version_max = this->tls->get_version_max(this->tls); + if ((version_max == TLS_1_3 && version < TLS_1_3) || + (version_max == TLS_1_2 && version < TLS_1_2)) + { + chunk_t server_random_end = chunk_create(&this->server_random[24], 8); + + if (chunk_equals(server_random_end, tls_downgrade_protection_tls11) || + chunk_equals(server_random_end, tls_downgrade_protection_tls12)) + { + DBG1(DBG_TLS, "server random indicates downgrade attack to %N", + tls_version_names, version); + this->alert->add(this->alert, TLS_FATAL, TLS_ILLEGAL_PARAMETER); + return NEED_MORE; + } + } + if (!this->tls->set_version(this->tls, version, version)) { DBG1(DBG_TLS, "negotiated version %N not supported", diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c index eb3edf8..2753231 100644 --- a/src/libtls/tls_server.c +++ b/src/libtls/tls_server.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Pascal Knecht + * Copyright (C) 2020-2021 Pascal Knecht * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2010 Martin Willi @@ -338,6 +338,7 @@ static status_t process_client_hello(private_tls_server_t *this, chunk_t extension_data = chunk_empty; bio_reader_t *extensions, *extension; tls_cipher_suite_t *suites; + tls_version_t original_version_max; int count, i; rng_t *rng; @@ -456,6 +457,8 @@ static status_t process_client_hello(private_tls_server_t *this, } rng->destroy(rng); + original_version_max = this->tls->get_version_max(this->tls); + if (versions.len) { bio_reader_t *client_versions; @@ -482,6 +485,21 @@ static status_t process_client_hello(private_tls_server_t *this, this->client_version = version; } } + + /* downgrade protection (see RFC 8446, section 4.1.3) */ + if ((original_version_max == TLS_1_3 && version < TLS_1_3) || + (original_version_max == TLS_1_2 && version < TLS_1_2)) + { + chunk_t downgrade_protection = tls_downgrade_protection_tls11; + + if (version == TLS_1_2) + { + downgrade_protection = tls_downgrade_protection_tls12; + } + memcpy(&this->server_random[24], downgrade_protection.ptr, + downgrade_protection.len); + } + if (!this->client_version) { DBG1(DBG_TLS, "proposed version %N not supported", tls_version_names, -- 2.7.4