diff options
author | EuAndreh <eu@euandre.org> | 2024-06-02 09:52:32 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-06-02 20:27:30 -0300 |
commit | 0cbfbd63d86b63cef88f349119d1a4b551c0a862 (patch) | |
tree | a388138afaf1fe909ba701d5914c3c75834179c4 /src | |
parent | tests/*.c: Use EXIT_FAILURE and EXIT_SUCCESS in main() functions (diff) | |
download | pindaiba-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.c | 104 | ||||
-rw-r--r-- | src/hash.h | 8 |
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] +); |