]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
extensions: simplified the extension tracking
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 19 Sep 2017 10:58:56 +0000 (12:58 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Feb 2018 14:29:34 +0000 (15:29 +0100)
Instead of keep a list of the received TLS extension IDs, use the bits
in a variable to mark the received extensions. That reduces the
overall memory usage due to extension tracking.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/extensions.c
lib/extensions.h
lib/gnutls_int.h
lib/handshake.c

index 71e34637997aab2c3103213ea80bd065742c76f2..8ebf4ab378786b972d9beecbf403439c7bdfd92d 100644 (file)
@@ -141,56 +141,6 @@ const char *gnutls_ext_get_name(unsigned int ext)
        return NULL;
 }
 
-/* Checks if the extension @id provided has been requested
- * by us (in client side). In that case it returns zero, 
- * otherwise a negative error value.
- */
-int
-_gnutls_extension_list_check(gnutls_session_t session, extensions_t id)
-{
-       unsigned i;
-
-       for (i = 0; i < session->internals.used_exts_size; i++) {
-               if (id == session->internals.used_exts[i]->gid)
-                       return 0;
-       }
-
-       return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
-}
-
-/* Adds the extension we want to send in the extensions list.
- * This list is used in client side to check whether the (later) received
- * extensions are the ones we requested.
- *
- * In server side, this list is used to ensure we don't send
- * extensions that we didn't receive a corresponding value.
- *
- * Returns zero if failed, non-zero on success.
- */
-static unsigned _gnutls_extension_list_add(gnutls_session_t session, const struct extension_entry_st *e, unsigned check_dup)
-{
-       unsigned i;
-
-       if (check_dup) {
-               for (i=0;i<session->internals.used_exts_size;i++) {
-                       if (session->internals.used_exts[i]->gid == e->gid)
-                               return 0;
-               }
-       }
-
-       if (session->internals.used_exts_size < MAX_EXT_TYPES) {
-               session->internals.used_exts[session->
-                                                  internals.used_exts_size]
-                   = e;
-               session->internals.used_exts_size++;
-               return 1;
-       } else {
-               _gnutls_handshake_log
-                   ("extensions: Increase MAX_EXT_TYPES\n");
-               return 0;
-       }
-}
-
 static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
 {
        unsigned i;
@@ -208,13 +158,11 @@ static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
        return 0;
 }
 
-
 void _gnutls_extension_list_add_sr(gnutls_session_t session)
 {
        _gnutls_extension_list_add(session, &ext_mod_sr, 1);
 }
 
-
 int
 _gnutls_parse_extensions(gnutls_session_t session,
                         gnutls_ext_flags_t msg,
@@ -514,21 +462,29 @@ int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed)
        unsigned int i;
        int ret;
        int total_exts_pos;
-       int exts = 0;
+       int n_exts = 0;
+       const struct extension_entry_st *ext;
 
        total_exts_pos = packed->length;
        BUFFER_APPEND_NUM(packed, 0);
 
-       for (i = 0; i < session->internals.used_exts_size; i++) {
-               ret = pack_extension(session, session->internals.used_exts[i], packed);
-               if (ret < 0)
-                       return gnutls_assert_val(ret);
+       for (i = 0; i <= GNUTLS_EXTENSION_MAX_VALUE; i++) {
+               if (session->internals.used_exts & (1<<i)) {
+
+                       ext = _gnutls_ext_ptr(session, i, GNUTLS_EXT_ANY);
+                       if (ext == NULL)
+                               continue;
 
-               if (ret > 0)
-                       exts++;
+                       ret = pack_extension(session, ext, packed);
+                       if (ret < 0)
+                               return gnutls_assert_val(ret);
+
+                       if (ret > 0)
+                               n_exts++;
+               }
        }
 
-       _gnutls_write_uint32(exts, packed->data + total_exts_pos);
+       _gnutls_write_uint32(n_exts, packed->data + total_exts_pos);
 
        return 0;
 }
index 556cdd32d7a43da9155551f2103081f9a1f09ec4..b1a47ecf36ef4e0dff0cfecbe745927ada375fbb 100644 (file)
@@ -36,9 +36,6 @@ int _gnutls_gen_extensions(gnutls_session_t session,
 int _gnutls_ext_init(void);
 void _gnutls_ext_deinit(void);
 
-void _gnutls_extension_list_add_sr(gnutls_session_t session);
-int _gnutls_extension_list_check(gnutls_session_t session, extensions_t type);
-
 void _gnutls_ext_free_session_data(gnutls_session_t session);
 
 /* functions to be used by extensions internally
@@ -120,4 +117,42 @@ typedef struct extension_entry_st {
 
 int _gnutls_ext_register(extension_entry_st *);
 
+void _gnutls_extension_list_add_sr(gnutls_session_t session);
+
+/* Checks if the extension @id provided has been requested
+ * by us (in client side). In that case it returns zero,
+ * otherwise a negative error value.
+ */
+inline static int
+_gnutls_extension_list_check(gnutls_session_t session, extensions_t id)
+{
+       if (id != 0 && ((1 << id) & session->internals.used_exts))
+               return 0;
+
+       return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
+}
+
+/* Adds the extension we want to send in the extensions list.
+ * This list is used in client side to check whether the (later) received
+ * extensions are the ones we requested.
+ *
+ * In server side, this list is used to ensure we don't send
+ * extensions that we didn't receive a corresponding value.
+ *
+ * Returns zero if failed, non-zero on success.
+ */
+inline static
+unsigned _gnutls_extension_list_add(gnutls_session_t session,
+                                   const struct extension_entry_st *e,
+                                   unsigned check_dup)
+{
+       if (check_dup && _gnutls_extension_list_check(session, e->gid) == 0) {
+                       return 0;
+       }
+
+       session->internals.used_exts |= (1 << e->gid);
+
+       return 1;
+}
+
 #endif
index b52e764bda9bbc41e182d4fd1c3b7d237cf91158..1512c4ee86e76012e49e5e5b4840da928e7ff38b 100644 (file)
@@ -291,11 +291,21 @@ typedef enum extensions_t {
        GNUTLS_EXTENSION_MAX = GNUTLS_EXTENSION_SERVER_NAME
 } extensions_t;
 
-#define GNUTLS_EXTENSION_MAX_VALUE 63
+#define GNUTLS_EXTENSION_MAX_VALUE 31
 #if GNUTLS_EXTENSION_MAX >= GNUTLS_EXTENSION_MAX_VALUE
 # error over limit
 #endif
 
+#if GNUTLS_EXTENSION_MAX >= MAX_EXT_TYPES
+# error over limit
+#endif
+
+/* we must provide at least 16 extensions for users to register */
+#if GNUTLS_EXTENSION_MAX_VALUE - GNUTLS_EXTENSION_MAX < 16
+# error not enough extension types; increase GNUTLS_EXTENSION_MAX_VALUE, MAX_EXT_TYPES and used_exts type
+#endif
+
+
 typedef enum { CIPHER_STREAM, CIPHER_BLOCK, CIPHER_AEAD } cipher_type_t;
 
 #define RESUME_TRUE 1
@@ -1138,10 +1148,10 @@ typedef struct {
        } ext_data[MAX_EXT_TYPES];
 
        /* In case of a client holds the extensions we sent to the peer;
-        * otherwise the extensions we received from the client.
+        * otherwise the extensions we received from the client. This is
+        * an OR of (1<<extensions_t values).
         */
-       const struct extension_entry_st *used_exts[MAX_EXT_TYPES];
-       unsigned used_exts_size;
+       uint32_t used_exts;
 
        /* this is not the negotiated max_record_recv_size, but the actual maximum
         * receive size */
index cfaa290505a0fbb49d24fa45ea9a008a157ff54f..9b35ebe228fb3713c0c76cdab490dcf591713bb7 100644 (file)
@@ -79,7 +79,7 @@ handshake_hash_buffer_empty(gnutls_session_t session)
 
        _gnutls_buffers_log("BUF[HSK]: Emptied buffer\n");
 
-       session->internals.used_exts_size = 0;
+       session->internals.used_exts = 0;
        session->internals.handshake_hash_buffer_prev_len = 0;
        session->internals.handshake_hash_buffer.length = 0;
        return;
@@ -2250,7 +2250,7 @@ int gnutls_handshake(gnutls_session_t session)
                if (ret < 0)
                        return gnutls_assert_val(ret);
 
-               session->internals.used_exts_size = 0;
+               session->internals.used_exts = 0;
                session->internals.crt_requested = 0;
                session->internals.handshake_in_progress = 1;
                session->internals.vc_status = -1;