]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
util/hash: use randomized hash algorithm
authorPhilippe Antoine <pantoine@oisf.net>
Sun, 22 Sep 2024 19:38:50 +0000 (21:38 +0200)
committerVictor Julien <vjulien@oisf.net>
Wed, 25 Sep 2024 08:46:12 +0000 (10:46 +0200)
For datasets and http ranges

Ticket: 7209

Prevents abusive hash collisions from known djb2 algorithm

14 files changed:
src/app-layer-htp-range.c
src/datasets-ipv4.c
src/datasets-ipv4.h
src/datasets-ipv6.c
src/datasets-ipv6.h
src/datasets-md5.c
src/datasets-md5.h
src/datasets-sha256.c
src/datasets-sha256.h
src/datasets-string.c
src/datasets-string.h
src/detect-engine-threshold.c
src/util-thash.c
src/util-thash.h

index 55587487f57334a29beda6a12534d46dccafdf01..b1f2b62423fcbf57e128b3bfff6eadbd9ab44ff0 100644 (file)
@@ -26,7 +26,7 @@
 #include "util-misc.h"        //ParseSizeStringU64
 #include "util-thash.h"       //HashTable
 #include "util-memcmp.h"      //SCBufferCmp
-#include "util-hash-string.h" //StringHashDjb2
+#include "util-hash-lookup3.h" //hashlittle_safe
 #include "util-validate.h"    //DEBUG_VALIDATE_BUG_ON
 #include "util-byte.h"        //StringParseUint32
 
@@ -102,10 +102,10 @@ static bool ContainerUrlRangeCompare(void *a, void *b)
     return false;
 }
 
-static uint32_t ContainerUrlRangeHash(void *s)
+static uint32_t ContainerUrlRangeHash(uint32_t hash_seed, void *s)
 {
     HttpRangeContainerFile *cur = s;
-    uint32_t h = StringHashDjb2(cur->key, cur->len);
+    uint32_t h = hashlittle_safe(cur->key, cur->len, hash_seed);
     return h;
 }
 
index f1192a0db5d1ff02c7efa0234730784cc707e4a0..67f8778fd2d613fd89e4652fbed151092e8786c5 100644 (file)
@@ -25,6 +25,7 @@
 #include "conf.h"
 #include "datasets.h"
 #include "datasets-ipv4.h"
+#include "util-hash-lookup3.h"
 #include "util-thash.h"
 #include "util-print.h"
 
@@ -45,15 +46,10 @@ bool IPv4Compare(void *a, void *b)
     return (memcmp(as->ipv4, bs->ipv4, sizeof(as->ipv4)) == 0);
 }
 
-uint32_t IPv4Hash(void *s)
+uint32_t IPv4Hash(uint32_t hash_seed, void *s)
 {
     const IPv4Type *str = s;
-    uint32_t hash = 5381;
-
-    for (int i = 0; i < (int)sizeof(str->ipv4); i++) {
-        hash = ((hash << 5) + hash) + str->ipv4[i]; /* hash * 33 + c */
-    }
-    return hash;
+    return hashword((uint32_t *)str->ipv4, 1, hash_seed);
 }
 
 // data stays in hash
index db7abd685140a0b7c06c378bf7d767356125c4ff..4a840e9aa63150b18d0efacf878ebe17139db9cb 100644 (file)
@@ -33,7 +33,7 @@ typedef struct IPv4Type {
 
 int IPv4Set(void *dst, void *src);
 bool IPv4Compare(void *a, void *b);
-uint32_t IPv4Hash(void *s);
+uint32_t IPv4Hash(uint32_t hash_seed, void *s);
 void IPv4Free(void *s);
 
 #endif /* SURICATA_DATASETS_IPV4_H */
index f907320f007d0b3645205191fa81a817da743114..ac96374da7c79a9f7e9daed71188bf30891624d8 100644 (file)
@@ -25,6 +25,7 @@
 #include "conf.h"
 #include "datasets.h"
 #include "datasets-ipv6.h"
+#include "util-hash-lookup3.h"
 #include "util-thash.h"
 #include "util-print.h"
 
@@ -45,15 +46,10 @@ bool IPv6Compare(void *a, void *b)
     return (memcmp(as->ipv6, bs->ipv6, sizeof(as->ipv6)) == 0);
 }
 
-uint32_t IPv6Hash(void *s)
+uint32_t IPv6Hash(uint32_t hash_seed, void *s)
 {
     const IPv6Type *str = s;
-    uint32_t hash = 5381;
-
-    for (int i = 0; i < (int)sizeof(str->ipv6); i++) {
-        hash = ((hash << 5) + hash) + str->ipv6[i]; /* hash * 33 + c */
-    }
-    return hash;
+    return hashword((uint32_t *)str->ipv6, 4, hash_seed);
 }
 
 // data stays in hash
index f3f59a0a9676a2a8aa388778446a9ef9b67b6659..c75ad194d68592b9471d2466f36c9aef11fa5a5f 100644 (file)
@@ -33,7 +33,7 @@ typedef struct IPv6Type {
 
 int IPv6Set(void *dst, void *src);
 bool IPv6Compare(void *a, void *b);
-uint32_t IPv6Hash(void *s);
+uint32_t IPv6Hash(uint32_t hash_seed, void *s);
 void IPv6Free(void *s);
 
 #endif /* __DATASETS_IPV4_H__ */
index 53d828d178b646621d59d3a0e1778bbbb2f6a68c..28fd37d8304a1ab61c6213ba6e7405d363532a05 100644 (file)
@@ -25,6 +25,8 @@
 #include "conf.h"
 #include "datasets.h"
 #include "datasets-md5.h"
+#include "util-hash-lookup3.h"
+
 #include "util-thash.h"
 #include "util-print.h"
 
@@ -45,15 +47,10 @@ bool Md5StrCompare(void *a, void *b)
     return (memcmp(as->md5, bs->md5, sizeof(as->md5)) == 0);
 }
 
-uint32_t Md5StrHash(void *s)
+uint32_t Md5StrHash(uint32_t hash_seed, void *s)
 {
     const Md5Type *str = s;
-    uint32_t hash = 5381;
-
-    for (int i = 0; i < (int)sizeof(str->md5); i++) {
-        hash = ((hash << 5) + hash) + str->md5[i]; /* hash * 33 + c */
-    }
-    return hash;
+    return hashword((uint32_t *)str->md5, sizeof(str->md5) / 4, hash_seed);
 }
 
 // data stays in hash
index e6030540df35be9c45044c97d72f701312c38039..88c1ff1dfd3be344b7773250d498492b06b614af 100644 (file)
@@ -33,7 +33,7 @@ typedef struct Md5Type {
 
 int Md5StrSet(void *dst, void *src);
 bool Md5StrCompare(void *a, void *b);
-uint32_t Md5StrHash(void *s);
+uint32_t Md5StrHash(uint32_t hash_seed, void *s);
 void Md5StrFree(void *s);
 
 #endif /* SURICATA_DATASETS_MD5_H */
index 02f97ae8776ba3db8af775bbef363549c8b6303c..240939c08454796a9e29a0ce07a44f4673fd65dd 100644 (file)
@@ -25,8 +25,8 @@
 #include "conf.h"
 #include "datasets.h"
 #include "datasets-sha256.h"
+#include "util-hash-lookup3.h"
 #include "util-thash.h"
-#include "util-print.h"
 
 int Sha256StrSet(void *dst, void *src)
 {
@@ -45,15 +45,10 @@ bool Sha256StrCompare(void *a, void *b)
     return (memcmp(as->sha256, bs->sha256, sizeof(as->sha256)) == 0);
 }
 
-uint32_t Sha256StrHash(void *s)
+uint32_t Sha256StrHash(uint32_t hash_seed, void *s)
 {
     Sha256Type *str = s;
-    uint32_t hash = 5381;
-
-    for (int i = 0; i < (int)sizeof(str->sha256); i++) {
-        hash = ((hash << 5) + hash) + str->sha256[i]; /* hash * 33 + c */
-    }
-    return hash;
+    return hashword((uint32_t *)str->sha256, sizeof(str->sha256) / 4, hash_seed);
 }
 
 // data stays in hash
index 716fa93dcf223930430fda44ad80a427947d82be..4f99b85a96e67f5bebc930baf005db773acc4fc4 100644 (file)
@@ -33,7 +33,7 @@ typedef struct Sha256Type {
 
 int Sha256StrSet(void *dst, void *src);
 bool Sha256StrCompare(void *a, void *b);
-uint32_t Sha256StrHash(void *s);
+uint32_t Sha256StrHash(uint32_t hash_seed, void *s);
 void Sha256StrFree(void *s);
 
 #endif /* SURICATA_DATASETS_SHA256_H */
index 2e60a3ca85fba7e9ab5982efe7834bb68d28235c..85fe864f52dbd359217e8c4c34a10315360634bc 100644 (file)
@@ -27,6 +27,7 @@
 #include "datasets-string.h"
 #include "util-thash.h"
 #include "util-print.h"
+#include "util-hash-lookup3.h"
 #include "rust.h"
 
 #if 0
@@ -84,17 +85,10 @@ bool StringCompare(void *a, void *b)
     return (memcmp(as->ptr, bs->ptr, as->len) == 0);
 }
 
-uint32_t StringHash(void *s)
+uint32_t StringHash(uint32_t hash_seed, void *s)
 {
-    uint32_t hash = 5381;
     StringType *str = s;
-
-    for (uint32_t i = 0; i < str->len; i++) {
-        int c = str->ptr[i];
-        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
-    }
-
-    return hash;
+    return hashlittle_safe(str->ptr, str->len, hash_seed);
 }
 
 uint32_t StringGetLength(void *s)
index 1d5463cd9c0aa0d717399879a2bdeb53fb5fc7f6..745754fc49ac5f240bdffe27a2018c3f1ffee7df 100644 (file)
@@ -34,7 +34,7 @@ typedef struct StringType {
 
 int StringSet(void *dst, void *src);
 bool StringCompare(void *a, void *b);
-uint32_t StringHash(void *s);
+uint32_t StringHash(uint32_t hash_seed, void *s);
 uint32_t StringGetLength(void *s);
 void StringFree(void *s);
 int StringAsBase64(const void *s, char *out, size_t out_size);
index 0f1e0e9ed533738559fdea972050f0bcc5afa583..c9ca8fa4a45e0dcb817133876b660da3e9bd69b4 100644 (file)
@@ -141,10 +141,10 @@ static inline int CompareAddress(const Address *a, const Address *b)
     return 0;
 }
 
-static uint32_t ThresholdEntryHash(void *ptr)
+static uint32_t ThresholdEntryHash(uint32_t seed, void *ptr)
 {
     const ThresholdEntry *e = ptr;
-    uint32_t hash = hashword(e->key, sizeof(e->key) / sizeof(uint32_t), 0);
+    uint32_t hash = hashword(e->key, sizeof(e->key) / sizeof(uint32_t), seed);
     switch (e->key[TRACK]) {
         case TRACK_BOTH:
             hash += HashAddress(&e->addr2);
index 74c74e245a6980603a17336c96f1b80060b1248e..3787454a37f4442f5c944aa5ffb8c81c4676f56c 100644 (file)
@@ -300,9 +300,10 @@ static int THashInitConfig(THashTableContext *ctx, const char *cnf_prefix)
 }
 
 THashTableContext *THashInit(const char *cnf_prefix, size_t data_size,
-        int (*DataSet)(void *, void *), void (*DataFree)(void *), uint32_t (*DataHash)(void *),
-        bool (*DataCompare)(void *, void *), bool (*DataExpired)(void *, SCTime_t),
-        uint32_t (*DataSize)(void *), bool reset_memcap, uint64_t memcap, uint32_t hashsize)
+        int (*DataSet)(void *, void *), void (*DataFree)(void *),
+        uint32_t (*DataHash)(uint32_t, void *), bool (*DataCompare)(void *, void *),
+        bool (*DataExpired)(void *, SCTime_t), uint32_t (*DataSize)(void *), bool reset_memcap,
+        uint64_t memcap, uint32_t hashsize)
 {
     THashTableContext *ctx = SCCalloc(1, sizeof(*ctx));
     BUG_ON(!ctx);
@@ -531,7 +532,7 @@ static uint32_t THashGetKey(const THashConfig *cnf, void *data)
 {
     uint32_t key;
 
-    key = cnf->DataHash(data);
+    key = cnf->DataHash(cnf->hash_rand, data);
     key %= cnf->hash_size;
 
     return key;
index 346c528a292a868b941f5b4ea6876a49129c6720..803a5f477c3c490be33ae937628f0826925afdbe 100644 (file)
@@ -130,7 +130,7 @@ typedef struct THashDataConfig_ {
     uint32_t data_size;
     int (*DataSet)(void *dst, void *src);
     void (*DataFree)(void *);
-    uint32_t (*DataHash)(void *);
+    uint32_t (*DataHash)(uint32_t, void *);
     bool (*DataCompare)(void *, void *);
     bool (*DataExpired)(void *, SCTime_t ts);
     uint32_t (*DataSize)(void *);
@@ -171,7 +171,7 @@ typedef struct THashTableContext_ {
 
 THashTableContext *THashInit(const char *cnf_prefix, size_t data_size,
         int (*DataSet)(void *dst, void *src), void (*DataFree)(void *),
-        uint32_t (*DataHash)(void *), bool (*DataCompare)(void *, void *),
+        uint32_t (*DataHash)(uint32_t, void *), bool (*DataCompare)(void *, void *),
         bool (*DataExpired)(void *, SCTime_t), uint32_t (*DataSize)(void *), bool reset_memcap,
         uint64_t memcap, uint32_t hashsize);