From 901478a2d04fcae70cf1f99f19b7508256633fa0 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sat, 17 Dec 2022 23:16:55 +0100 Subject: Secure random fallback: thread safety --- source/kit/secure_random.c | 36 +++++++++++++++++++++++++----- source/kit/secure_random.h | 5 +++++ source/kit/time.h | 8 +++---- source/test/unittests/secure_random.test.c | 4 ++++ 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/source/kit/secure_random.c b/source/kit/secure_random.c index 8852524..8f48c9d 100644 --- a/source/kit/secure_random.c +++ b/source/kit/secure_random.c @@ -1,6 +1,7 @@ #include "secure_random.h" #include "mersenne_twister_64.h" +#include "mutex.h" #include "time.h" #include @@ -26,8 +27,16 @@ static uint64_t get_available_memory() { #endif } +#ifndef KIT_DISABLE_SYSTEM_THREADS +static mtx_t kit_secure_random_fallback_mutex; +#endif + static void secure_random_fallback(ptrdiff_t const size, void *const data) { +#ifndef KIT_DISABLE_SYSTEM_THREADS + mtx_lock(&kit_secure_random_fallback_mutex); +#endif + /* Try to get some unpredictable system properties and use them to * seed the pseudo random number generator. */ @@ -42,11 +51,11 @@ static void secure_random_fallback(ptrdiff_t const size, kit_mt64_state_t state; if (time_sec == 0 && time_nsec == 0) { - uint64_t seed[4] = { n++, get_available_memory(), + uint64_t seed[4] = { n, get_available_memory(), (uint64_t) t.tv_sec, (uint64_t) t.tv_nsec }; kit_mt64_init_array(&state, sizeof seed / sizeof *seed, seed); } else { - uint64_t seed[6] = { n++, + uint64_t seed[6] = { n, get_available_memory(), (uint64_t) t.tv_sec, (uint64_t) t.tv_nsec, @@ -55,17 +64,34 @@ static void secure_random_fallback(ptrdiff_t const size, kit_mt64_init_array(&state, sizeof seed / sizeof *seed, seed); } - time_sec = (uint64_t) t.tv_sec; - time_nsec = (uint64_t) t.tv_nsec; - /* Bootstrap the generator. */ for (ptrdiff_t i = 0; i < KIT_MT64_N; i++) kit_mt64_generate(&state); + n = kit_mt64_generate(&state); + time_sec = (uint64_t) t.tv_sec; + time_nsec = (uint64_t) t.tv_nsec; + for (ptrdiff_t i = 0; i < size; i++) ((uint8_t *) data)[i] = (uint8_t) (kit_mt64_generate(&state) >> 56); + +#ifndef KIT_DISABLE_SYSTEM_THREADS + mtx_unlock(&kit_secure_random_fallback_mutex); +#endif +} + +void kit_secure_random_init() { +#ifndef KIT_DISABLE_SYSTEM_THREADS + mtx_init(&kit_secure_random_fallback_mutex, mtx_plain); +#endif +} + +void kit_secure_random_cleanup() { +#ifndef KIT_DISABLE_SYSTEM_THREADS + mtx_destroy(&kit_secure_random_fallback_mutex); +#endif } void kit_secure_random(ptrdiff_t const size, void *const data) { diff --git a/source/kit/secure_random.h b/source/kit/secure_random.h index 758478d..5b461f9 100644 --- a/source/kit/secure_random.h +++ b/source/kit/secure_random.h @@ -9,9 +9,14 @@ extern "C" { #endif +void kit_secure_random_init(); +void kit_secure_random_cleanup(); + void kit_secure_random(ptrdiff_t size, void *data); #ifndef KIT_DISABLE_SHORT_NAMES +# define secure_random_init kit_secure_random_init +# define secure_random_cleanup kit_secure_random_cleanup # define secure_random kit_secure_random #endif diff --git a/source/kit/time.h b/source/kit/time.h index dbf8883..0d995f4 100644 --- a/source/kit/time.h +++ b/source/kit/time.h @@ -38,21 +38,21 @@ struct timespec { /*-------------------------- functions --------------------------*/ #if !defined(KIT_HAVE_TIMESPEC_GET) -# define KIT_HAVE_TIMESPEC_GET_NEED_DECL_ +# define KIT_TIMESPEC_GET_NEED_DECL_ #elif defined(__APPLE__) && defined(__cplusplus) && \ (__cplusplus < 201703L) /* On macOS, the guard for declaration of timespec_get is by * (defined(__cplusplus) && __cplusplus >= 201703L), * fix the declaration for C++14 and lower here */ -# define KIT_HAVE_TIMESPEC_GET_NEED_DECL_ +# define KIT_TIMESPEC_GET_NEED_DECL_ #endif -#ifdef KIT_HAVE_TIMESPEC_GET_NEED_DECL_ +#ifdef KIT_TIMESPEC_GET_NEED_DECL_ /*-------------------- 7.25.7 Time functions --------------------*/ // 7.25.6.1 int timespec_get(struct timespec *ts, int base); -# undef KIT_HAVE_TIMESPEC_GET_NEED_DECL_ +# undef KIT_TIMESPEC_GET_NEED_DECL_ #endif #ifdef __cplusplus diff --git a/source/test/unittests/secure_random.test.c b/source/test/unittests/secure_random.test.c index ec0a7b2..eadae65 100644 --- a/source/test/unittests/secure_random.test.c +++ b/source/test/unittests/secure_random.test.c @@ -8,9 +8,13 @@ TEST("secure random") { int v[20]; memset(v, 0, sizeof v); + secure_random_init(); + secure_random(40, v); secure_random(40, v + 10); + secure_random_cleanup(); + int repeats = 0; for (int i = 1; i < sizeof v / sizeof *v; i++) -- cgit v1.2.3