diff options
author | @Ajit <ajeetsinghchahar2@gmail.com> | 2023-04-01 23:05:00 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2023-04-01 23:05:00 +0000 |
commit | b6b71c8b70061eb5a489443ba82c90df948da95b (patch) | |
tree | f7f2681f3ef0a6af8ec6148ef260ef151775d0d8 /lib | |
parent | b3fe5c229474a4dd0e74e955afb6bdc5d54c462d (diff) | |
download | gnutls-b6b71c8b70061eb5a489443ba82c90df948da95b.tar.gz |
hello_ext: add ClientHello extension permutation
This adds a mechanism to randomize the order of TLS extensions in the
ClientHello to make fingerprinting harder. The mechanism is enabled by
default and a new priority keyword %NO_EXTS_SHUFFLE has been added to
turn it off.
Signed-off-by: peonix <ajeetsinghchahar2@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gnutls_int.h | 3 | ||||
-rw-r--r-- | lib/hello_ext.c | 49 | ||||
-rw-r--r-- | lib/priority.c | 5 | ||||
-rw-r--r-- | lib/priority_options.gperf | 1 |
4 files changed, 57 insertions, 1 deletions
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index d4b2e280e0..a3ee5e6f20 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -948,6 +948,9 @@ struct gnutls_priority_st { /* to disable record padding */ bool no_extensions; + /* to disable extensions shuffling */ + bool no_exts_shuffle; + safe_renegotiation_t sr; bool min_record_version; bool server_precedence; diff --git a/lib/hello_ext.c b/lib/hello_ext.c index 6870db8a81..a15e91876a 100644 --- a/lib/hello_ext.c +++ b/lib/hello_ext.c @@ -408,6 +408,30 @@ int hello_ext_send(void *_ctx, gnutls_buffer_st * buf) return 0; } +static inline void swap_exts(extensions_t * exts1, extensions_t * exts2) +{ + extensions_t temp = *exts1; + *exts1 = *exts2; + *exts2 = temp; +} + +static +int shuffle_exts(extensions_t * exts, size_t size) +{ + /* generating random permutation of extensions */ + extensions_t rnd_n; + for (size_t i = size - 1; i > 0; i--) { + int ret = gnutls_rnd(GNUTLS_RND_RANDOM, (void *)&rnd_n, + sizeof(extensions_t)); + if (ret < 0) + return ret; + extensions_t j = rnd_n % (i + 1); + swap_exts(&exts[i], &exts[j]); + } + + return 0; +} + int _gnutls_gen_hello_extensions(gnutls_session_t session, gnutls_buffer_st * buf, @@ -446,9 +470,32 @@ _gnutls_gen_hello_extensions(gnutls_session_t session, ret - 4); } + /* To shuffle extension sending order */ + extensions_t shuffled_exts[MAX_EXT_TYPES]; + + /* Initializing extensions array */ + for (i = 0; i < MAX_EXT_TYPES; i++) { + shuffled_exts[i] = i; + } + + /* ordering dumbfw and pre_shared_key as last extensions */ + swap_exts(&shuffled_exts[MAX_EXT_TYPES - 2], + &shuffled_exts[GNUTLS_EXTENSION_DUMBFW]); + swap_exts(&shuffled_exts[MAX_EXT_TYPES - 1], + &shuffled_exts[GNUTLS_EXTENSION_PRE_SHARED_KEY]); + + if (session->internals.priorities->no_exts_shuffle == 1) + goto next; + + ret = shuffle_exts(shuffled_exts, MAX_EXT_TYPES - 2); + if (ret < 0) + return gnutls_assert_val(ret); + + next: /* hello_ext_send() ensures we don't send duplicates, in case * of overridden extensions */ - for (i = 0; i < MAX_EXT_TYPES; i++) { + for (size_t r = 0; r < MAX_EXT_TYPES; r++) { + i = shuffled_exts[r]; if (!extfunc[i]) continue; diff --git a/lib/priority.c b/lib/priority.c index 4b5eb7c77d..966de4d83d 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1081,6 +1081,11 @@ static void disable_tls13_compat_mode(gnutls_priority_t c) c->tls13_compat_mode = false; } +static void enable_no_exts_shuffle(gnutls_priority_t c) +{ + c->no_exts_shuffle = 1; +} + static void dummy_func(gnutls_priority_t c) { } diff --git a/lib/priority_options.gperf b/lib/priority_options.gperf index 11bcc6e88e..d69c3b4b11 100644 --- a/lib/priority_options.gperf +++ b/lib/priority_options.gperf @@ -43,3 +43,4 @@ NEW_PADDING, dummy_func DEBUG_ALLOW_KEY_USAGE_VIOLATIONS, enable_server_key_usage_violations ALLOW_SMALL_RECORDS, enable_allow_small_records DISABLE_TLS13_COMPAT_MODE, disable_tls13_compat_mode +NO_EXTS_SHUFFLE, enable_no_exts_shuffle |