diff options
Diffstat (limited to 'shared/nm-glib-aux/nm-hash-utils.c')
-rw-r--r-- | shared/nm-glib-aux/nm-hash-utils.c | 286 |
1 files changed, 0 insertions, 286 deletions
diff --git a/shared/nm-glib-aux/nm-hash-utils.c b/shared/nm-glib-aux/nm-hash-utils.c deleted file mode 100644 index 29349b1d0d..0000000000 --- a/shared/nm-glib-aux/nm-hash-utils.c +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "nm-glib-aux/nm-default-glib-i18n-lib.h" - -#include "nm-hash-utils.h" - -#include <stdint.h> - -#include "nm-shared-utils.h" -#include "nm-random-utils.h" - -/*****************************************************************************/ - -#define HASH_KEY_SIZE 16u -#define HASH_KEY_SIZE_GUINT ((HASH_KEY_SIZE + sizeof(guint) - 1) / sizeof(guint)) - -G_STATIC_ASSERT(sizeof(guint) * HASH_KEY_SIZE_GUINT >= HASH_KEY_SIZE); - -static const guint8 *volatile global_seed = NULL; - -static const guint8 * -_get_hash_key_init(void) -{ - /* the returned hash is aligned to guin64, hence, it is safe - * to use it as guint* or guint64* pointer. */ - static union { - guint8 v8[HASH_KEY_SIZE]; - guint _align_as_uint; - guint32 _align_as_uint32; - guint64 _align_as_uint64; - } g_arr; - const guint8 *g; - -again: - g = g_atomic_pointer_get(&global_seed); - if (!G_UNLIKELY(g)) { - static gsize g_lock; - uint64_t h; - union { - guint vuint; - guint8 v8[HASH_KEY_SIZE]; - guint8 _extra_entropy[3 * HASH_KEY_SIZE]; - } t_arr; - - nm_utils_random_bytes(&t_arr, sizeof(t_arr)); - - /* We only initialize one random hash key. So we can spend some effort - * of getting this right. For one, we collect more random bytes than - * necessary. - * - * Then, the first guint of the seed should have all the entropy that we could - * obtain in sizeof(t_arr). For that, siphash(t_arr) and xor the first guint - * with hash. - * The first guint is especially interesting for nm_hash_static() below that - * doesn't use siphash itself. */ - h = c_siphash_hash(t_arr.v8, (const guint8 *) &t_arr, sizeof(t_arr)); - if (sizeof(h) > sizeof(guint)) - t_arr.vuint = t_arr.vuint ^ ((guint)(h & G_MAXUINT)) ^ ((guint)(h >> 32)); - else - t_arr.vuint = t_arr.vuint ^ ((guint)(h & G_MAXUINT)); - - if (!g_once_init_enter(&g_lock)) { - /* lost a race. The random key is already initialized. */ - goto again; - } - - memcpy(g_arr.v8, t_arr.v8, HASH_KEY_SIZE); - g = g_arr.v8; - g_atomic_pointer_set(&global_seed, g); - g_once_init_leave(&g_lock, 1); - } - - nm_assert(g == g_arr.v8); - return g; -} - -#define _get_hash_key() \ - ({ \ - const guint8 *_g; \ - \ - _g = g_atomic_pointer_get(&global_seed); \ - if (G_UNLIKELY(!_g)) \ - _g = _get_hash_key_init(); \ - _g; \ - }) - -guint -nm_hash_static(guint static_seed) -{ - /* Note that we only xor the static_seed with the first guint of the key. - * - * We don't use siphash, which would mix the bits better with _get_hash_key(). - * Note that nm_hash_static() isn't used to hash the static_seed. Instead, it - * is used to get a unique hash value in a static context. That means, every - * caller is responsible to choose a static_seed that is sufficiently - * distinct from all other callers. In other words, static_seed should be a - * unique constant with good entropy. - * - * Note that _get_hash_key_init() already xored the first guint of the - * key with the siphash of the entire static key. That means, even if - * we got bad randomness for the first guint, the first guint is also - * mixed with the randomness of the entire random key. - * - * Also, ensure that we don't return zero (like for nm_hash_complete()). - */ - return ((*((const guint *) _get_hash_key())) ^ static_seed) ?: 3679500967u; -} - -void -nm_hash_siphash42_init(CSipHash *h, guint static_seed) -{ - const guint8 *g; - union { - guint64 _align_as_uint64; - guint arr[HASH_KEY_SIZE_GUINT]; - } seed; - - nm_assert(h); - - g = _get_hash_key(); - memcpy(&seed, g, HASH_KEY_SIZE); - seed.arr[0] ^= static_seed; - c_siphash_init(h, (const guint8 *) &seed); -} - -guint -nm_hash_str(const char *str) -{ - NMHashState h; - - if (!str) - return nm_hash_static(1867854211u); - nm_hash_init(&h, 1867854211u); - nm_hash_update_str(&h, str); - return nm_hash_complete(&h); -} - -guint -nm_str_hash(gconstpointer str) -{ - return nm_hash_str(str); -} - -guint -nm_hash_ptr(gconstpointer ptr) -{ - NMHashState h; - - if (!ptr) - return nm_hash_static(2907677551u); - nm_hash_init(&h, 2907677551u); - nm_hash_update(&h, &ptr, sizeof(ptr)); - return nm_hash_complete(&h); -} - -guint -nm_direct_hash(gconstpointer ptr) -{ - return nm_hash_ptr(ptr); -} - -/*****************************************************************************/ - -guint -nm_pstr_hash(gconstpointer p) -{ - const char *const *s = p; - - if (!s) - return nm_hash_static(101061439u); - return nm_hash_str(*s); -} - -gboolean -nm_pstr_equal(gconstpointer a, gconstpointer b) -{ - const char *const *s1 = a; - const char *const *s2 = b; - - return (s1 == s2) || (s1 && s2 && nm_streq0(*s1, *s2)); -} - -guint -nm_pint_hash(gconstpointer p) -{ - const int *s = p; - - if (!s) - return nm_hash_static(298377461u); - return nm_hash_val(1208815757u, *s); -} - -gboolean -nm_pint_equals(gconstpointer a, gconstpointer b) -{ - const int *s1 = a; - const int *s2 = a; - - return s1 == s2 || (s1 && s2 && *s1 == *s2); -} - -guint -nm_pdirect_hash(gconstpointer p) -{ - const void *const *s = p; - - if (!s) - return nm_hash_static(1852748873u); - return nm_direct_hash(*s); -} - -gboolean -nm_pdirect_equal(gconstpointer a, gconstpointer b) -{ - const void *const *s1 = a; - const void *const *s2 = b; - - return (s1 == s2) || (s1 && s2 && *s1 == *s2); -} - -guint -nm_ppdirect_hash(gconstpointer p) -{ - const void *const *const *s = p; - - if (!s) - return nm_hash_static(396534869u); - if (!*s) - return nm_hash_static(1476102263u); - return nm_direct_hash(**s); -} - -gboolean -nm_ppdirect_equal(gconstpointer a, gconstpointer b) -{ - const void *const *const *s1 = a; - const void *const *const *s2 = b; - - if (s1 == s2) - return TRUE; - if (!s1 || !s2) - return FALSE; - - if (*s1 == *s2) - return TRUE; - if (!*s1 || !*s2) - return FALSE; - - return **s1 == **s2; -} - -/*****************************************************************************/ - -guint -nm_gbytes_hash(gconstpointer p) -{ - GBytes * ptr = (GBytes *) p; - gconstpointer arr; - gsize len; - - arr = g_bytes_get_data(ptr, &len); - return nm_hash_mem(792701303u, arr, len); -} - -guint -nm_pgbytes_hash(gconstpointer p) -{ - GBytes *const *ptr = p; - gconstpointer arr; - gsize len; - - arr = g_bytes_get_data(*ptr, &len); - return nm_hash_mem(1470631313u, arr, len); -} - -gboolean -nm_pgbytes_equal(gconstpointer a, gconstpointer b) -{ - GBytes *const *ptr_a = a; - GBytes *const *ptr_b = b; - - return g_bytes_equal(*ptr_a, *ptr_b); -} |