summaryrefslogtreecommitdiff
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
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
-rw-r--r--Makefile2
-rw-r--r--deps.mk9
-rw-r--r--src/hash.c104
-rw-r--r--src/hash.h8
-rw-r--r--tests/hash.c63
5 files changed, 185 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index ffc06f4..088d839 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ MANDIR = $(SHAREDIR)/man
EXEC = ./
## Where to store the installation. Empty by default.
DESTDIR =
-LDLIBS = -lsiphashbs
+LDLIBS = -lpthread -lsiphashbs
diff --git a/deps.mk b/deps.mk
index ee1bcb4..12678b6 100644
--- a/deps.mk
+++ b/deps.mk
@@ -4,6 +4,7 @@ catalogs.msg = $(catalogs.en.msg)
sources.c = \
src/catalog.c \
+ src/hash.c \
src/i18n.c \
src/lib.c \
src/logerr.c \
@@ -18,6 +19,7 @@ sources.c = \
tests.c = \
tests/catalog.c \
+ tests/hash.c \
tests/i18n.c \
tests/lib.c \
tests/logerr.c \
@@ -31,6 +33,7 @@ tests.c = \
tests/vector.c \
src/catalog.o: src/catalog.h
+src/hash.o: src/hash.h
src/i18n.o: src/i18n.h
src/lib.o: src/lib.h
src/logerr.o: src/logerr.h
@@ -44,6 +47,7 @@ src/util.o: src/util.h
src/vector.o: src/vector.h
tests/catalog.o: src/catalog.c src/catalog.h
+tests/hash.o: src/hash.c src/hash.h
tests/i18n.o: src/i18n.c src/i18n.h
tests/lib.o: src/lib.c src/lib.h
tests/logerr.o: src/logerr.c src/logerr.h
@@ -57,6 +61,7 @@ tests/util.o: src/util.c src/util.h
tests/vector.o: src/vector.c src/vector.h
tests/catalog.a: tests/catalog.o
+tests/hash.a: tests/hash.o
tests/i18n.a: tests/i18n.o
tests/lib.a: tests/lib.o
tests/logerr.a: tests/logerr.o
@@ -70,6 +75,7 @@ tests/util.a: tests/util.o
tests/vector.a: tests/vector.o
tests/catalog.bin-check: tests/catalog.bin
+tests/hash.bin-check: tests/hash.bin
tests/i18n.bin-check: tests/i18n.bin
tests/lib.bin-check: tests/lib.bin
tests/logerr.bin-check: tests/logerr.bin
@@ -84,6 +90,7 @@ tests/vector.bin-check: tests/vector.bin
src/catalog.o: src/logerr.h
+src/hash.o: src/logerr.h src/random.h
src/i18n.o: src/catalog.h
src/lib.o: src/logerr.h
src/logerr.o:
@@ -97,6 +104,7 @@ src/util.o: src/logerr.h
src/vector.o: src/catalog.h src/i18n.h src/logerr.h src/math.h src/util.h
tests/catalog.o: src/logerr.h src/testing.h src/util.h tests/slurp.h
+tests/hash.o: src/logerr.h src/random.h src/testing.h
tests/i18n.o: src/catalog.h src/logerr.h
tests/lib.o: src/logerr.h
tests/logerr.o: src/testing.h src/util.h tests/slurp.h
@@ -110,6 +118,7 @@ tests/util.o: src/logerr.h src/testing.h tests/slurp.h
tests/vector.o: src/catalog.h src/i18n.h src/logerr.h src/math.h src/util.h src/testing.h
tests/catalog.a: src/logerr.o src/testing.o src/util.o tests/slurp.o
+tests/hash.a: src/logerr.o src/random.o src/testing.o src/util.o
tests/i18n.a: src/catalog.o src/logerr.o
tests/lib.a: src/logerr.o
tests/logerr.a: src/testing.o src/util.o tests/slurp.o
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]
+);
diff --git a/tests/hash.c b/tests/hash.c
new file mode 100644
index 0000000..652b4fd
--- /dev/null
+++ b/tests/hash.c
@@ -0,0 +1,63 @@
+#include "../src/hash.c"
+
+#include <stdlib.h>
+
+#include "../src/testing.h"
+
+
+
+static void
+test_HASH_OUTPUT_LENGTH(void) {
+ test_start("HASH_OUTPUT_LENGTH");
+
+ {
+ testing("Enforce we're always consistent with SipHash");
+
+ assert(HASH_OUTPUT_LENGTH == SIPHASH_OUTPUT_LENGTH);
+
+ test_ok();
+ }
+}
+
+static int
+test_hash_init(void) {
+ int rc = -1;
+
+ test_start("hash_init()");
+
+ {
+ testing("INITIALIZED changes after calling hash_init()");
+
+ assert(INITIALIZED == false);
+
+ if (hash_init()) {
+ logerr("hash_init()");
+ goto out;
+ }
+ rc = 0; goto out;
+
+ assert(INITIALIZED == true);
+
+ test_ok();
+ }
+
+ rc = 0;
+out:
+ return rc;
+}
+
+int
+main(void) {
+ int rc = EXIT_FAILURE;
+
+ test_HASH_OUTPUT_LENGTH();
+
+ if (test_hash_init()) {
+ logerr("test_hash_init()");
+ goto out;
+ }
+
+ rc = EXIT_SUCCESS;
+out:
+ return rc;
+}