static int wrap_nettle_rnd_init (void **ctx) { int ret; ret = gnutls_mutex_init (&rnd_mutex); if (ret < 0) { gnutls_assert (); return ret; } yarrow256_init (&yctx, SOURCES, ysources); ret = do_device_source (1); if (ret < 0) { gnutls_assert (); return ret; } ret = do_trivia_source (1); if (ret < 0) { gnutls_assert (); return ret; } yarrow256_slow_reseed (&yctx); return 0; }
static int wrap_nettle_rnd_init(void **ctx) { int ret; struct event_st event; uint8_t nonce_key[NONCE_KEY_SIZE]; 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(&rnd_ctx.yctx, SOURCES, rnd_ctx.ysources); _rnd_get_event(&event); rnd_ctx.forkid = _gnutls_get_forkid(); ret = do_device_source(&rnd_ctx, 1, &event); if (ret < 0) { gnutls_assert(); return ret; } ret = do_trivia_source(&rnd_ctx, 1, &event); if (ret < 0) { gnutls_assert(); return ret; } yarrow256_slow_reseed(&rnd_ctx.yctx); /* initialize the nonce RNG */ ret = _rnd_get_system_entropy(nonce_key, sizeof(nonce_key)); if (ret < 0) return gnutls_assert_val(ret); ret = nonce_rng_init(&nonce_ctx, nonce_key, sizeof(nonce_key), 1); if (ret < 0) return gnutls_assert_val(ret); return 0; }
static int do_device_source (int init) { static pid_t pid; /* detect fork() */ int ret, reseed = 0; static int (*do_source) (int init) = NULL; /* using static var here is ok since we are * always called with mutexes down */ if (init == 1) { pid = getpid(); do_source = do_device_source_urandom; ret = do_source (init); if (ret < 0) { do_source = do_device_source_egd; ret = do_source (init); } if (ret < 0) { gnutls_assert (); return ret; } return ret; } else { if (getpid() != pid) { /* fork() detected */ device_last_read = 0; pid = getpid(); reseed = 1; } ret = do_source (init); if (reseed) yarrow256_slow_reseed (&yctx); return ret; } }
static int wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize) { int ret, reseed = 0; struct event_st event; if (level == GNUTLS_RND_NONCE) return wrap_nettle_rnd_nonce(_ctx, data, datasize); _rnd_get_event(&event); RND_LOCK(&rnd_ctx); if (_gnutls_detect_fork(rnd_ctx.forkid)) { /* fork() detected */ memset(&rnd_ctx.device_last_read, 0, sizeof(rnd_ctx.device_last_read)); reseed = 1; } /* reseed main */ ret = do_trivia_source(&rnd_ctx, 0, &event); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = do_device_source(&rnd_ctx, 0, &event); if (ret < 0) { gnutls_assert(); goto cleanup; } if (reseed != 0) { yarrow256_slow_reseed(&rnd_ctx.yctx); rnd_ctx.forkid = _gnutls_get_forkid(); } yarrow256_random(&rnd_ctx.yctx, datasize, data); ret = 0; cleanup: RND_UNLOCK(&rnd_ctx); return ret; }
int yarrow256_update(struct yarrow256_ctx *ctx, unsigned source_index, unsigned entropy, size_t length, const uint8_t *data) { enum yarrow_pool_id current; struct yarrow_source *source; assert(source_index < ctx->nsources); if (!length) /* Nothing happens */ return 0; source = &ctx->sources[source_index]; if (!ctx->seeded) /* While seeding, use the slow pool */ current = YARROW_SLOW; else { current = source->next; source->next = !source->next; } sha256_update(&ctx->pools[current], length, data); /* NOTE: We should be careful to avoid overflows in the estimates. */ if (source->estimate[current] < YARROW_MAX_ENTROPY) { if (entropy > YARROW_MAX_ENTROPY) entropy = YARROW_MAX_ENTROPY; if ( (length < (YARROW_MAX_ENTROPY / YARROW_MULTIPLIER)) && (entropy > YARROW_MULTIPLIER * length) ) entropy = YARROW_MULTIPLIER * length; entropy += source->estimate[current]; if (entropy > YARROW_MAX_ENTROPY) entropy = YARROW_MAX_ENTROPY; source->estimate[current] = entropy; } /* Check for seed/reseed */ switch(current) { case YARROW_FAST: #if YARROW_DEBUG fprintf(stderr, "yarrow256_update: source_index = %d,\n" " fast pool estimate = %d\n", source_index, source->estimate[YARROW_FAST]); #endif if (source->estimate[YARROW_FAST] >= YARROW_FAST_THRESHOLD) { yarrow256_fast_reseed(ctx); return 1; } else return 0; case YARROW_SLOW: { if (!yarrow256_needed_sources(ctx)) { yarrow256_slow_reseed(ctx); return 1; } else return 0; } default: abort(); } }