]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
tls13/key_update: increase handling limit from 1 to 8
authorDaiki Ueno <dueno@redhat.com>
Wed, 22 May 2019 08:39:27 +0000 (10:39 +0200)
committerDaiki Ueno <dueno@redhat.com>
Wed, 22 May 2019 15:32:35 +0000 (17:32 +0200)
The limit was too small when testing the capability of handling
multiple KeyUpdate messages with tlsfuzzer.

This requires a change in the rate limit logic, as previously it
doesn't count the KeyUpdate messages despite the name of
KEY_UPDATES_PER_SEC.

Signed-off-by: Daiki Ueno <dueno@redhat.com>
lib/gnutls_int.h
lib/tls13/key_update.c

index 50251a356aff93ec582e727e7019bc91a80c79c9..867e4d2d76f3e46dafb637988668703fc2299730 100644 (file)
@@ -1368,7 +1368,8 @@ typedef struct {
        /* The hsk_flags are for use within the ongoing handshake;
         * they are reset to zero prior to handshake start by gnutls_handshake. */
        unsigned hsk_flags;
-       time_t last_key_update;
+       struct timespec last_key_update;
+       unsigned key_update_count;
        /* Read-only pointer to the full ClientHello message */
        gnutls_buffer_st full_client_hello;
        /* The offset at which extensions start in the ClientHello buffer */
index abd7c93ec60518de9dac4292b25ee9cd6bb3bd54..d542a214b7990c7dfbf7f7f5f66cb54633831d52 100644 (file)
@@ -28,7 +28,8 @@
 #include "mbuffers.h"
 #include "secrets.h"
 
-#define KEY_UPDATES_PER_SEC 1
+#define KEY_UPDATES_WINDOW 1000
+#define KEY_UPDATES_PER_WINDOW 8
 
 static int update_keys(gnutls_session_t session, hs_stage_t stage)
 {
@@ -60,18 +61,28 @@ static int update_keys(gnutls_session_t session, hs_stage_t stage)
 int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
 {
        int ret;
-       time_t now = gnutls_time(0);
+       struct timespec now;
 
        if (buf->length != 1)
                return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
-       if (unlikely(now - session->internals.last_key_update < KEY_UPDATES_PER_SEC)) {
-               _gnutls_debug_log("reached maximum number of key updates per second (%d)\n",
-                                 KEY_UPDATES_PER_SEC);
-               return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
+       gnutls_gettime(&now);
+
+       /* Roll over the counter if the time window has elapsed */
+       if (session->internals.key_update_count == 0 ||
+           timespec_sub_ms(&now, &session->internals.last_key_update) >
+           KEY_UPDATES_WINDOW) {
+               session->internals.last_key_update = now;
+               session->internals.key_update_count = 0;
        }
 
-       session->internals.last_key_update = now;
+       if (unlikely(++session->internals.key_update_count >
+                    KEY_UPDATES_PER_WINDOW)) {
+               _gnutls_debug_log("reached maximum number of key updates per %d milliseconds (%d)\n",
+                                 KEY_UPDATES_WINDOW,
+                                 KEY_UPDATES_PER_WINDOW);
+               return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
+       }
 
        _gnutls_epoch_gc(session);