#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)
#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();
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];
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);
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;
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;
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;
}
/* 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);
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 */
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;
}
_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;
}
_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;
}