]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
use two separate mutexes for nonce and main rng.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 Jan 2014 11:59:56 +0000 (12:59 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 Jan 2014 11:59:56 +0000 (12:59 +0100)
lib/nettle/rnd.c

index 4951b4ed04cc99c9bf90abd561029c275f07d526..bcdefac347b2e0535c2210ef1da485ea91fcf9a7 100644 (file)
 
 #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;
 }