From: Nikos Mavrogiannopoulos Date: Sun, 26 Jan 2014 11:59:56 +0000 (+0100) Subject: use two separate mutexes for nonce and main rng. X-Git-Tag: gnutls_3_3_0pre0~265 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b0ca115eade6ccd9c0a52d93dfd1bd217cf27b91;p=thirdparty%2Fgnutls.git use two separate mutexes for nonce and main rng. --- diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c index 4951b4ed04..bcdefac347 100644 --- a/lib/nettle/rnd.c +++ b/lib/nettle/rnd.c @@ -41,38 +41,41 @@ #define SOURCES 2 -#define RND_LOCK if (gnutls_mutex_lock(&rnd_mutex)!=0) abort() -#define RND_UNLOCK if (gnutls_mutex_unlock(&rnd_mutex)!=0) abort() +#define RND_LOCK(ctx) if (gnutls_mutex_lock(&((ctx)->mutex))!=0) abort() +#define RND_UNLOCK(ctx) if (gnutls_mutex_unlock(&((ctx)->mutex))!=0) abort() enum { RANDOM_SOURCE_TRIVIA = 0, RANDOM_SOURCE_DEVICE, }; -static struct yarrow256_ctx yctx; -static struct yarrow_source ysources[SOURCES]; struct nonce_ctx_st { struct salsa20_ctx ctx; unsigned int counter; + void *mutex; #ifdef HAVE_GETPID pid_t pid; /* detect fork() */ #endif }; -/* after this number of bytes salsa20 will reseed */ -#define NONCE_RESEED_BYTES (1048576) -static struct nonce_ctx_st nonce_ctx; - -static struct timespec device_last_read = { 0, 0 }; - -static time_t trivia_previous_time = 0; -static time_t trivia_time_count = 0; +struct rnd_ctx_st { + struct yarrow256_ctx yctx; + struct yarrow_source ysources[SOURCES]; + struct timespec device_last_read; + time_t trivia_previous_time; + time_t trivia_time_count; + void *mutex; #ifdef HAVE_GETPID -static pid_t pid; /* detect fork() */ + pid_t pid; /* detect fork() */ #endif +}; -static void *rnd_mutex; +static struct rnd_ctx_st rnd_ctx; + +/* after this number of bytes salsa20 will reseed */ +#define NONCE_RESEED_BYTES (1048576) +static struct nonce_ctx_st nonce_ctx; inline static unsigned int timespec_sub_sec(struct timespec *a, struct timespec *b) @@ -83,43 +86,43 @@ timespec_sub_sec(struct timespec *a, struct timespec *b) #define DEVICE_READ_INTERVAL (1200) /* universal functions */ -static int do_trivia_source(int init, struct event_st *event) +static int do_trivia_source(struct rnd_ctx_st *ctx, int init, struct event_st *event) { unsigned entropy = 0; if (init) { - trivia_time_count = 0; + ctx->trivia_time_count = 0; } else { - trivia_time_count++; + ctx->trivia_time_count++; - if (event->now.tv_sec != trivia_previous_time) { + if (event->now.tv_sec != ctx->trivia_previous_time) { /* Count one bit of entropy if we either have more than two * invocations in one second, or more than two seconds * between invocations. */ - if ((trivia_time_count > 2) - || ((event->now.tv_sec - trivia_previous_time) > 2)) + if ((ctx->trivia_time_count > 2) + || ((event->now.tv_sec - ctx->trivia_previous_time) > 2)) entropy++; - trivia_time_count = 0; + ctx->trivia_time_count = 0; } } - trivia_previous_time = event->now.tv_sec; + ctx->trivia_previous_time = event->now.tv_sec; - return yarrow256_update(&yctx, RANDOM_SOURCE_TRIVIA, entropy, + return yarrow256_update(&ctx->yctx, RANDOM_SOURCE_TRIVIA, entropy, sizeof(*event), (void *) event); } #define DEVICE_READ_SIZE 16 #define DEVICE_READ_SIZE_MAX 32 -static int do_device_source(int init, struct event_st *event) +static int do_device_source(struct rnd_ctx_st *ctx, int init, struct event_st *event) { unsigned int read_size = DEVICE_READ_SIZE; int ret; if (init) { #ifdef HAVE_GETPID - pid = event->pid; + ctx->pid = event->pid; #endif ret = _rnd_system_entropy_init(); @@ -128,14 +131,14 @@ static int do_device_source(int init, struct event_st *event) return gnutls_assert_val(ret); } - memcpy(&device_last_read, &event->now, - sizeof(device_last_read)); + memcpy(&ctx->device_last_read, &event->now, + sizeof(ctx->device_last_read)); read_size = DEVICE_READ_SIZE_MAX; /* initially read more data */ } if ((init - || (timespec_sub_sec(&event->now, &device_last_read) > + || (timespec_sub_sec(&event->now, &ctx->device_last_read) > DEVICE_READ_INTERVAL))) { /* More than 20 minutes since we last read the device */ uint8_t buf[DEVICE_READ_SIZE_MAX]; @@ -144,10 +147,10 @@ static int do_device_source(int init, struct event_st *event) if (ret < 0) return gnutls_assert_val(ret); - memcpy(&device_last_read, &event->now, - sizeof(device_last_read)); + memcpy(&ctx->device_last_read, &event->now, + sizeof(ctx->device_last_read)); - return yarrow256_update(&yctx, RANDOM_SOURCE_DEVICE, + return yarrow256_update(&ctx->yctx, RANDOM_SOURCE_DEVICE, read_size * 8 / 2 /* we trust the RNG */ , read_size, buf); @@ -157,15 +160,15 @@ static int do_device_source(int init, struct event_st *event) static void wrap_nettle_rnd_deinit(void *ctx) { - RND_LOCK; _rnd_system_entropy_deinit(); - RND_UNLOCK; - gnutls_mutex_deinit(&rnd_mutex); - rnd_mutex = NULL; + gnutls_mutex_deinit(&nonce_ctx.mutex); + nonce_ctx.mutex = NULL; + gnutls_mutex_deinit(&rnd_ctx.mutex); + rnd_ctx.mutex = NULL; } -static int nonce_rng_init(struct nonce_ctx_st *ctx) +static int nonce_rng_init(struct nonce_ctx_st *ctx, struct event_st *event) { uint8_t buffer[SALSA20_KEY_SIZE]; int ret; @@ -175,8 +178,16 @@ static int nonce_rng_init(struct nonce_ctx_st *ctx) if (ret < 0) return gnutls_assert_val(ret); + salsa20_set_key(&ctx->ctx, sizeof(buffer), buffer); + if (sizeof(struct event_st) < 8) { + abort(); + } + + if (event != NULL) + salsa20_set_iv(&ctx->ctx, (void*)event); + zeroize_key(buffer, sizeof(buffer)); ctx->counter = 0; @@ -194,7 +205,15 @@ static int wrap_nettle_rnd_init(void **ctx) int ret; struct event_st event; - ret = gnutls_mutex_init(&rnd_mutex); + memset(&rnd_ctx, 0, sizeof(rnd_ctx)); + + ret = gnutls_mutex_init(&nonce_ctx.mutex); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = gnutls_mutex_init(&rnd_ctx.mutex); if (ret < 0) { gnutls_assert(); return ret; @@ -207,26 +226,26 @@ static int wrap_nettle_rnd_init(void **ctx) } /* initialize the main RNG */ - yarrow256_init(&yctx, SOURCES, ysources); + yarrow256_init(&rnd_ctx.yctx, SOURCES, rnd_ctx.ysources); _rnd_get_event(&event); - ret = do_device_source(1, &event); + ret = do_device_source(&rnd_ctx, 1, &event); if (ret < 0) { gnutls_assert(); return ret; } - ret = do_trivia_source(1, &event); + ret = do_trivia_source(&rnd_ctx, 1, &event); if (ret < 0) { gnutls_assert(); return ret; } - yarrow256_slow_reseed(&yctx); + yarrow256_slow_reseed(&rnd_ctx.yctx); /* initialize the nonce RNG */ - ret = nonce_rng_init(&nonce_ctx); + ret = nonce_rng_init(&nonce_ctx, &event); if (ret < 0) return gnutls_assert_val(ret); @@ -241,7 +260,11 @@ wrap_nettle_rnd_nonce(void *_ctx, void *data, size_t datasize) pid_t tpid = getpid(); #endif - RND_LOCK; + /* we don't really need memset here, but otherwise we + * get filled with valgrind warnings */ + memset(data, 0, datasize); + + RND_LOCK(&nonce_ctx); #ifdef HAVE_GETPID if (tpid != nonce_ctx.pid) { /* fork() detected */ @@ -251,23 +274,20 @@ wrap_nettle_rnd_nonce(void *_ctx, void *data, size_t datasize) if (reseed != 0 || nonce_ctx.counter > NONCE_RESEED_BYTES) { /* reseed nonce */ - ret = nonce_rng_init(&nonce_ctx); + ret = nonce_rng_init(&nonce_ctx, NULL); if (ret < 0) { gnutls_assert(); goto cleanup; } } - /* we don't really need memset here, but otherwise we - * get filled with valgrind warnings */ - memset(data, 0, datasize); salsa20r12_crypt(&nonce_ctx.ctx, datasize, data, data); nonce_ctx.counter += datasize; ret = 0; cleanup: - RND_UNLOCK; + RND_UNLOCK(&nonce_ctx); return ret; } @@ -284,37 +304,37 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize) _rnd_get_event(&event); - RND_LOCK; + RND_LOCK(&rnd_ctx); #ifdef HAVE_GETPID - if (event.pid != pid) { /* fork() detected */ - memset(&device_last_read, 0, sizeof(device_last_read)); - pid = event.pid; + if (event.pid != rnd_ctx.pid) { /* fork() detected */ + memset(&rnd_ctx.device_last_read, 0, sizeof(rnd_ctx.device_last_read)); + rnd_ctx.pid = event.pid; reseed = 1; } #endif /* reseed main */ - ret = do_trivia_source(0, &event); + ret = do_trivia_source(&rnd_ctx, 0, &event); if (ret < 0) { gnutls_assert(); goto cleanup; } - ret = do_device_source(0, &event); + ret = do_device_source(&rnd_ctx, 0, &event); if (ret < 0) { gnutls_assert(); goto cleanup; } if (reseed != 0) - yarrow256_slow_reseed(&yctx); + yarrow256_slow_reseed(&rnd_ctx.yctx); - yarrow256_random(&yctx, datasize, data); + yarrow256_random(&rnd_ctx.yctx, datasize, data); ret = 0; cleanup: - RND_UNLOCK; + RND_UNLOCK(&rnd_ctx); return ret; } @@ -324,11 +344,15 @@ static void wrap_nettle_rnd_refresh(void *_ctx) _rnd_get_event(&event); - RND_LOCK; - do_trivia_source(0, &event); - do_device_source(0, &event); + RND_LOCK(&rnd_ctx); + do_trivia_source(&rnd_ctx, 0, &event); + do_device_source(&rnd_ctx, 0, &event); + RND_UNLOCK(&rnd_ctx); + + RND_LOCK(&nonce_ctx); + nonce_rng_init(&nonce_ctx, &event); + RND_UNLOCK(&nonce_ctx); - RND_UNLOCK; return; }