summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-12-12 12:11:53 +0100
committerThomas Haller <thaller@redhat.com>2018-12-12 12:51:47 +0100
commitdb791db4e1ff7a850b4ac49d24d159e2ccbe005c (patch)
tree15f465d377872b97e53588eb1edf068c6cf3ecc5
parent3e0177f7d5450e955c7f812895a5de43822ea6d2 (diff)
downloadNetworkManager-db791db4e1ff7a850b4ac49d24d159e2ccbe005c.tar.gz
shared: expose siphash24() related functionality in nm-hash-utils.h
CSiphash is a first class citizen, it's fine to use everwhere where we need it. NMHash wraps CSiphash and provides three things: 1) Convenience macros that make hashing nicer to use. 2) it uses a randomly generated, per-run hash seed, that can be combined with a guint static seed. 3) it's a general API for hashing data. It nowhere promises that it actually uses siphash24, although currently it does everywhere. NMHash is not (officially) siphash24. Add API nm_hash_siphash42_init() and nm_hash_siphash42() to "nm-hash-utils.h", that exposes (2) for use with regular CSiphash. You of course no longer get the convenice macros (1) but you get plain siphash24 (which NMHash does not give (3)). While at it, also add a nm_hash_complete_u64(). Usually, for hasing we want guint types. But we don't need to hide the fact, that the underlying value is first uint64. Expose it.
-rw-r--r--shared/nm-utils/nm-hash-utils.c6
-rw-r--r--shared/nm-utils/nm-hash-utils.h62
2 files changed, 59 insertions, 9 deletions
diff --git a/shared/nm-utils/nm-hash-utils.c b/shared/nm-utils/nm-hash-utils.c
index 9f164a119e..80387c7143 100644
--- a/shared/nm-utils/nm-hash-utils.c
+++ b/shared/nm-utils/nm-hash-utils.c
@@ -122,17 +122,17 @@ nm_hash_static (guint static_seed)
}
void
-nm_hash_init (NMHashState *state, guint static_seed)
+nm_hash_siphash42_init (CSipHash *h, guint static_seed)
{
const guint8 *g;
guint seed[HASH_KEY_SIZE_GUINT];
- nm_assert (state);
+ nm_assert (h);
g = _get_hash_key ();
memcpy (seed, g, HASH_KEY_SIZE);
seed[0] ^= static_seed;
- c_siphash_init (&state->_state, (const guint8 *) seed);
+ c_siphash_init (h, (const guint8 *) seed);
}
guint
diff --git a/shared/nm-utils/nm-hash-utils.h b/shared/nm-utils/nm-hash-utils.h
index b797fb75af..cf71a7e9f2 100644
--- a/shared/nm-utils/nm-hash-utils.h
+++ b/shared/nm-utils/nm-hash-utils.h
@@ -25,6 +25,39 @@
#include "c-siphash/src/c-siphash.h"
#include "nm-macros-internal.h"
+/*****************************************************************************/
+
+void nm_hash_siphash42_init (CSipHash *h, guint static_seed);
+
+/* Siphash24 of binary buffer @arr and @len, using the randomized seed from
+ * other NMHash functions.
+ *
+ * Note, that this is guaranteed to use siphash42 under the hood (contrary to
+ * all other NMHash API, which leave this undefined). That matters at the point,
+ * where the caller needs to be sure that a reasonably strong hasing algorithm
+ * is used. (Yes, NMHash is all about siphash24, but otherwise that is not promised
+ * anywhere).
+ *
+ * Another difference is, that this returns guint64 (not guint like other NMHash functions).
+ *
+ * Another difference is, that this may also return zero (not like nm_hash_complete()).
+ *
+ * Then, why not use c_siphash_hash() directly? Because this also uses the randomized,
+ * per-run hash-seed like nm_hash_init(). So, you get siphash24 with a random
+ * seed (which is cached for the current run of the program).
+ */
+static inline guint64
+nm_hash_siphash42 (guint static_seed, const void *ptr, gsize n)
+{
+ CSipHash h;
+
+ nm_hash_siphash42_init (&h, static_seed);
+ c_siphash_append (&h, ptr, n);
+ return c_siphash_finalize (&h);
+}
+
+/*****************************************************************************/
+
struct _NMHashState {
CSipHash _state;
};
@@ -33,16 +66,33 @@ typedef struct _NMHashState NMHashState;
guint nm_hash_static (guint static_seed);
-void nm_hash_init (NMHashState *state, guint static_seed);
+static inline void
+nm_hash_init (NMHashState *state, guint static_seed)
+{
+ nm_assert (state);
+
+ nm_hash_siphash42_init (&state->_state, static_seed);
+}
+
+static inline guint64
+nm_hash_complete_u64 (NMHashState *state)
+{
+ nm_assert (state);
+
+ /* this returns the native u64 hash value. Note that this differs
+ * from nm_hash_complete() in two ways:
+ *
+ * - the type, guint64 vs. guint.
+ * - nm_hash_complete() never returns zero. */
+ return c_siphash_finalize (&state->_state);
+}
static inline guint
nm_hash_complete (NMHashState *state)
{
guint64 h;
- nm_assert (state);
-
- h = c_siphash_finalize (&state->_state);
+ h = nm_hash_complete_u64 (state);
/* we don't ever want to return a zero hash.
*
@@ -218,8 +268,8 @@ guint nm_str_hash (gconstpointer str);
({ \
NMHashState _h; \
\
- nm_hash_init (&_h, static_seed); \
- nm_hash_update_val (&_h, val); \
+ nm_hash_init (&_h, (static_seed)); \
+ nm_hash_update_val (&_h, (val)); \
nm_hash_complete (&_h); \
})