diff options
Diffstat (limited to 'src/hash.c')
-rw-r--r-- | src/hash.c | 104 |
1 files changed, 104 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); +} |