#include "config.h" #include #include #include #include #include #include #include #include #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); }