]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Change hash iv to a be a fixed sized array master
authorArne Schwabe <arne@rfc2549.org>
Thu, 6 Aug 2026 10:29:21 +0000 (12:29 +0200)
committerGert Doering <gert@greenie.muc.de>
Thu, 6 Aug 2026 10:44:36 +0000 (12:44 +0200)
While for our own hash function, always using an uint32_t works well, it does
not work very well if we move to another hash function like siphash that
requires a larger key.

To avoid allocating a specific context, change the API to be a fixed size
array of size 4. This define allows use to easily change it to a larger
value if we use hash functions that require larger keys.

Change-Id: If47c7d920b2fa4047b7db03fcde821899839324d
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Frank Lichtenheld <frank@lichtenheld.com>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1571
Message-Id: <20260806102926.28206-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg38162.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/list.c
src/openvpn/list.h
src/openvpn/mroute.c
src/openvpn/mroute.h
src/openvpn/multi.c
tests/unit_tests/openvpn/test_misc.c

index c07e764f2b2c1eaee76c940fa1a112f628a45a42..e52c778619f30bc3553e465f7d8275a553932f89 100644 (file)
 
 #include "integer.h"
 #include "list.h"
 
 #include "integer.h"
 #include "list.h"
+
+#include "crypto.h"
 #include "misc.h"
 
 #include "memdbg.h"
 
 struct hash *
 #include "misc.h"
 
 #include "memdbg.h"
 
 struct hash *
-hash_init(const uint32_t n_buckets, const uint32_t iv,
-          uint64_t (*hash_function)(const void *key, uint32_t iv),
+hash_init(const uint32_t n_buckets,
+          uint64_t (*hash_function)(const void *key, const uint8_t hash_key[HASH_KEY_LEN]),
           bool (*compare_function)(const void *key1, const void *key2))
 {
     struct hash *h;
           bool (*compare_function)(const void *key1, const void *key2))
 {
     struct hash *h;
@@ -46,7 +48,10 @@ hash_init(const uint32_t n_buckets, const uint32_t iv,
     h->mask = h->n_buckets - 1;
     h->hash_function = hash_function;
     h->compare_function = compare_function;
     h->mask = h->n_buckets - 1;
     h->hash_function = hash_function;
     h->compare_function = compare_function;
-    h->iv = iv;
+
+    /* create random hash key */
+    prng_bytes(h->hash_key, sizeof(h->hash_key));
+
     ALLOC_ARRAY(h->buckets, struct hash_bucket, h->n_buckets);
     for (uint32_t i = 0; i < h->n_buckets; ++i)
     {
     ALLOC_ARRAY(h->buckets, struct hash_bucket, h->n_buckets);
     for (uint32_t i = 0; i < h->n_buckets; ++i)
     {
index 06377c6ce2307fccb24381ca1049fb0347c3988a..cbf1abf363c38ea257c363f700b7e5b6f380f5d6 100644 (file)
@@ -49,19 +49,24 @@ struct hash_bucket
     struct hash_element *list;
 };
 
     struct hash_element *list;
 };
 
+
+#define HASH_KEY_LEN 4
+
 struct hash
 {
     uint32_t n_buckets;
     uint32_t n_elements;
     uint32_t mask;
 struct hash
 {
     uint32_t n_buckets;
     uint32_t n_elements;
     uint32_t mask;
-    uint32_t iv;
-    uint64_t (*hash_function)(const void *key, uint32_t iv);
+    /** key/iv used for the hash function. No to be confused with the (key, value)
+     * keys for the actual hash map entries */
+    uint8_t hash_key[HASH_KEY_LEN];
+    uint64_t (*hash_function)(const void *key, const uint8_t hash_key[HASH_KEY_LEN]);
     bool (*compare_function)(const void *key1, const void *key2); /* return true if equal */
     struct hash_bucket *buckets;
 };
 
     bool (*compare_function)(const void *key1, const void *key2); /* return true if equal */
     struct hash_bucket *buckets;
 };
 
-struct hash *hash_init(const uint32_t n_buckets, const uint32_t iv,
-                       uint64_t (*hash_function)(const void *key, uint32_t iv),
+struct hash *hash_init(const uint32_t n_buckets,
+                       uint64_t (*hash_function)(const void *key, const uint8_t hash_key[HASH_KEY_LEN]),
                        bool (*compare_function)(const void *key1, const void *key2));
 
 void hash_free(struct hash *hash);
                        bool (*compare_function)(const void *key1, const void *key2));
 
 void hash_free(struct hash *hash);
@@ -103,7 +108,7 @@ uint64_t hash_func(const uint8_t *k, uint32_t length, uint32_t initval);
 static inline uint64_t
 hash_value(const struct hash *hash, const void *key)
 {
 static inline uint64_t
 hash_value(const struct hash *hash, const void *key)
 {
-    return (*hash->hash_function)(key, hash->iv);
+    return (*hash->hash_function)(key, hash->hash_key);
 }
 
 static inline uint32_t
 }
 
 static inline uint32_t
index 78c689e3d4f39a6a2d5a22ae4539c9828326e7a7..a5179d00f92b1e356e86541331ef14aa1457a0f7 100644 (file)
@@ -355,10 +355,10 @@ mroute_addr_mask_host_bits(struct mroute_addr *ma)
  * and the actual address.
  */
 uint64_t
  * and the actual address.
  */
 uint64_t
-mroute_addr_hash_function(const void *key, uint32_t iv)
+mroute_addr_hash_function(const void *key, const uint8_t hash_key[HASH_KEY_LEN])
 {
     return hash_func(mroute_addr_hash_ptr((const struct mroute_addr *)key),
 {
     return hash_func(mroute_addr_hash_ptr((const struct mroute_addr *)key),
-                     mroute_addr_hash_len((const struct mroute_addr *)key), iv);
+                     mroute_addr_hash_len((const struct mroute_addr *)key), *(uint32_t *)hash_key);
 }
 
 bool
 }
 
 bool
index 2f5d01931bdf49e9b1ac5154f51fd700ca977db8..639281bef9d21fe1d440955f1ae37b72eef84655 100644 (file)
@@ -144,7 +144,7 @@ bool mroute_extract_openvpn_sockaddr(struct mroute_addr *addr,
 
 bool mroute_learnable_address(const struct mroute_addr *addr, struct gc_arena *gc);
 
 
 bool mroute_learnable_address(const struct mroute_addr *addr, struct gc_arena *gc);
 
-uint64_t mroute_addr_hash_function(const void *key, uint32_t iv);
+uint64_t mroute_addr_hash_function(const void *key, const uint8_t hash_key[HASH_KEY_LEN]);
 
 bool mroute_addr_compare_function(const void *key1, const void *key2);
 
 
 bool mroute_addr_compare_function(const void *key1, const void *key2);
 
index fe2badbfdf14d81bf84dbf36adae5b64999655f4..a4e9c1c8041b57e060ff105a3f4c1dd007d25106 100644 (file)
@@ -229,7 +229,7 @@ reap_buckets_per_pass(uint32_t n_buckets)
 #ifdef ENABLE_MANAGEMENT
 
 static uint64_t
 #ifdef ENABLE_MANAGEMENT
 
 static uint64_t
-cid_hash_function(const void *key, uint32_t iv)
+cid_hash_function(const void *key, const uint8_t hash_key[HASH_KEY_LEN])
 {
     const unsigned long *k = (const unsigned long *)key;
     return (uint64_t)*k;
 {
     const unsigned long *k = (const unsigned long *)key;
     return (uint64_t)*k;
@@ -250,7 +250,7 @@ static uint64_t
 /*
  * inotify watcher descriptors are used as hash value
  */
 /*
  * inotify watcher descriptors are used as hash value
  */
-int_hash_function(const void *key, uint32_t iv)
+int_hash_function(const void *key, const uint8_t hash_key[HASH_KEY_LEN])
 {
     return (uintptr_t)key;
 }
 {
     return (uintptr_t)key;
 }
@@ -290,18 +290,18 @@ multi_init(struct context *t)
      * to determine which client sent an incoming packet
      * which is seen on the TCP/UDP socket.
      */
      * to determine which client sent an incoming packet
      * which is seen on the TCP/UDP socket.
      */
-    m->hash = hash_init(t->options.real_hash_size, (uint32_t)get_random(),
+    m->hash = hash_init(t->options.real_hash_size,
                         mroute_addr_hash_function, mroute_addr_compare_function);
 
     /*
      * Virtual address hash table.  Used to determine
      * which client to route a packet to.
      */
                         mroute_addr_hash_function, mroute_addr_compare_function);
 
     /*
      * Virtual address hash table.  Used to determine
      * which client to route a packet to.
      */
-    m->vhash = hash_init(t->options.virtual_hash_size, (uint32_t)get_random(),
+    m->vhash = hash_init(t->options.virtual_hash_size,
                          mroute_addr_hash_function, mroute_addr_compare_function);
 
 #ifdef ENABLE_MANAGEMENT
                          mroute_addr_hash_function, mroute_addr_compare_function);
 
 #ifdef ENABLE_MANAGEMENT
-    m->cid_hash = hash_init(t->options.real_hash_size, 0, cid_hash_function, cid_compare_function);
+    m->cid_hash = hash_init(t->options.real_hash_size, cid_hash_function, cid_compare_function);
 #endif
 
 #ifdef ENABLE_ASYNC_PUSH
 #endif
 
 #ifdef ENABLE_ASYNC_PUSH
@@ -309,8 +309,8 @@ multi_init(struct context *t)
      * Mapping between inotify watch descriptors and
      * multi_instances.
      */
      * Mapping between inotify watch descriptors and
      * multi_instances.
      */
-    m->inotify_watchers = hash_init(t->options.real_hash_size, (uint32_t)get_random(),
-                                    int_hash_function, int_compare_function);
+    m->inotify_watchers =
+        hash_init(t->options.real_hash_size, int_hash_function, int_compare_function);
 #endif
 
     /*
 #endif
 
     /*
index 4d046ceb4e56b6b052fbd4f2008bb5eaddadca66..3ebbfc159637bcbc06de51e7a71638667c3df58b 100644 (file)
@@ -131,11 +131,11 @@ struct word
 
 
 static uint64_t
 
 
 static uint64_t
-word_hash_function(const void *key, uint32_t iv)
+word_hash_function(const void *key, const uint8_t hash_key[HASH_KEY_LEN])
 {
     const char *str = (const char *)key;
     const uint32_t len = (uint32_t)strlen(str);
 {
     const char *str = (const char *)key;
     const uint32_t len = (uint32_t)strlen(str);
-    return hash_func((const uint8_t *)str, len, iv);
+    return hash_func((const uint8_t *)str, len, *(uint32_t *)(hash_key));
 }
 
 static bool
 }
 
 static bool
@@ -170,10 +170,9 @@ test_list(void **state)
      * Test the hash code by implementing a simple
      * word frequency algorithm.
      */
      * Test the hash code by implementing a simple
      * word frequency algorithm.
      */
-
     struct gc_arena gc = gc_new();
     struct gc_arena gc = gc_new();
-    struct hash *hash = hash_init(10000, get_random(), word_hash_function, word_compare_function);
-    struct hash *nhash = hash_init(256, get_random(), word_hash_function, word_compare_function);
+    struct hash *hash = hash_init(10000, word_hash_function, word_compare_function);
+    struct hash *nhash = hash_init(256, word_hash_function, word_compare_function);
 
     printf("hash_init n_buckets=%u mask=0x%08x\n", hash->n_buckets, hash->mask);
 
 
     printf("hash_init n_buckets=%u mask=0x%08x\n", hash->n_buckets, hash->mask);