]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
hello_ext: add ClientHello extension permutation
author@Ajit <ajeetsinghchahar2@gmail.com>
Sat, 1 Apr 2023 23:05:00 +0000 (23:05 +0000)
committerDaiki Ueno <ueno@gnu.org>
Sat, 1 Apr 2023 23:05:00 +0000 (23:05 +0000)
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>
lib/gnutls_int.h
lib/hello_ext.c
lib/priority.c
lib/priority_options.gperf
tests/tls13-early-data.c
tests/tls13/prf-early.c
tests/tls13/prf.c

index d4b2e280e0660fe36d2c064cb67aaddb4f5bd9a0..a3ee5e6f204f138ac4ef2037656b5c51f0ef91d4 100644 (file)
@@ -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;
index 6870db8a81c71f659ca284a782e713842e67257c..a15e91876a6bac7b6312f9181020c14f8184acbb 100644 (file)
@@ -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;
 
index 4b5eb7c77d94a441a5a7adfb0bb5e7886e0adaf2..966de4d83dc3ea9e9bb286fe02182309651c96ff 100644 (file)
@@ -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)
 {
 }
index 11bcc6e88e15cdb5023a09aeffec4f3c09d87d90..d69c3b4b1169529bfdcf223e652b29b5af7e1015 100644 (file)
@@ -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
index b89fe75367b1c8bd00f5035699b9c01892dd8395..d7ed79b3bfb7cff31c4facf4267afcbcf9ccf6e8 100644 (file)
@@ -91,8 +91,8 @@ extern unsigned int _gnutls_global_version;
  * selected during the initial handshake, not the resuming handshakes.
  */
 # define SESSIONS 3
-# define TLS13_AES_128_GCM "NONE:+VERS-TLS1.3:+AES-128-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1"
-# define TLS13_CHACHA20_POLY1305 "NONE:+VERS-TLS1.3:+CHACHA20-POLY1305:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1"
+# define TLS13_AES_128_GCM "NONE:+VERS-TLS1.3:+AES-128-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1:%NO_EXTS_SHUFFLE"
+# define TLS13_CHACHA20_POLY1305 "NONE:+VERS-TLS1.3:+CHACHA20-POLY1305:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1:%NO_EXTS_SHUFFLE"
 
 static const
 gnutls_datum_t hrnd = { (void *)
index a21bc1c7a459140ba6e6b5893a8b3c33bdbd585f..0df9a18abd786c111be442c88457db2b08f13e3b 100644 (file)
@@ -183,9 +183,9 @@ static void client(int sds[])
                 */
                gnutls_init(&session, GNUTLS_CLIENT);
 
-               /* Use default priorities */
+               /* Use default priorities, sets %NO_EXTS_SHUFFLE */
                ret = gnutls_priority_set_direct(session,
-                                                "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1",
+                                                "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1:%NO_EXTS_SHUFFLE",
                                                 &err);
                if (ret < 0) {
                        fail("client: priority set failed (%s): %s\n",
index 1cd3f9e5ecd9325dc86b754389f4885dab800481..003ed69b01ac7e1e4b0eaeec793667a97d97c7ea 100644 (file)
@@ -196,10 +196,11 @@ static void client(int fd)
         */
        gnutls_init(&session, GNUTLS_CLIENT);
 
-       /* Use default priorities */
+       /* Use default priorities, sets %NO_EXTS_SHUFFLE */
        ret = gnutls_priority_set_direct(session,
-                                        "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1",
+                                        "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1:%NO_EXTS_SHUFFLE",
                                         &err);
+
        if (ret < 0) {
                fail("client: priority set failed (%s): %s\n",
                     gnutls_strerror(ret), err);