summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-06-02 09:52:32 -0300
committerEuAndreh <eu@euandre.org>2024-06-02 20:27:30 -0300
commit0cbfbd63d86b63cef88f349119d1a4b551c0a862 (patch)
treea388138afaf1fe909ba701d5914c3c75834179c4 /src
parenttests/*.c: Use EXIT_FAILURE and EXIT_SUCCESS in main() functions (diff)
downloadpindaiba-0cbfbd63d86b63cef88f349119d1a4b551c0a862.tar.gz
pindaiba-0cbfbd63d86b63cef88f349119d1a4b551c0a862.tar.xz
src/hash.c: Add thread safe initialization of SipHash seed
Diffstat (limited to 'src')
-rw-r--r--src/hash.c104
-rw-r--r--src/hash.h8
2 files changed, 112 insertions, 0 deletions
diff --git a/src/hash.c b/src/hash.c
new file mode 100644
index 0000000..4b397bd
--- /dev/null
+++ b/src/hash.c
@@ -0,0 +1,104 @@
+#include "config.h"
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <siphashbs.h>
+
+#include "hash.h"
+#include "logerr.h"
+#include "random.h"
+
+
+
+static volatile bool
+INITIALIZED = false;
+
+static uint8_t
+SIPHASH_KEY[SIPHASH_KEY_LENGTH];
+
+static pthread_mutex_t
+SEED_MUTEX = PTHREAD_MUTEX_INITIALIZER;
+
+
+
+static int
+unsafe_init(void) {
+ int rc = -1;
+
+ if (urandom_bytes(SIPHASH_KEY_LENGTH, &SIPHASH_KEY)) {
+ logerr("urandom_bytes()");
+ goto out;
+ }
+
+ rc = 0;
+out:
+ return rc;
+}
+
+static int
+safe_init(void) {
+ int rc = -1;
+
+ bool lock_acquired = false;
+
+ if (INITIALIZED == true) {
+ rc = 0;
+ goto out;
+ }
+
+ const int ret1 = pthread_mutex_lock(&SEED_MUTEX);
+ if (ret1) {
+ logerr("pthread_mutex_lock(): %s", strerror(ret1));
+ goto out;
+ }
+ lock_acquired = true;
+
+ if (INITIALIZED == true) {
+ rc = 0;
+ goto out;
+ }
+
+ if (unsafe_init()) {
+ logerr("unsafe_init()");
+ goto out;
+ }
+
+ INITIALIZED = true;
+
+ rc = 0;
+out:
+ if (lock_acquired) {
+ const int ret2 = pthread_mutex_unlock(&SEED_MUTEX);
+ if (ret2) {
+ logerr("pthread_mutex_unlock(): %s", strerror(ret2));
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+static void
+ensure_initialized(void) {
+ assert((safe_init() == 0) && "Failed to initialized the hash seed");
+}
+
+int
+hash_init(void) {
+ return safe_init();
+}
+
+void
+hash(
+ const size_t inlen,
+ const void *const restrict in,
+ uint8_t out[HASH_OUTPUT_LENGTH]
+) {
+ ensure_initialized();
+ siphashbs(SIPHASH_KEY, inlen, in, out);
+}
diff --git a/src/hash.h b/src/hash.h
new file mode 100644
index 0000000..4831c4b
--- /dev/null
+++ b/src/hash.h
@@ -0,0 +1,8 @@
+#define HASH_OUTPUT_LENGTH 16U
+
+void
+hash(
+ const size_t inlen,
+ const void *const restrict in,
+ uint8_t out[HASH_OUTPUT_LENGTH]
+);