Пример #1
0
static void wrap_nettle_rnd_refresh(void *_ctx)
{
	struct generators_ctx_st *ctx = _ctx;
	char tmp;

	/* force reseed */
	ctx->nonce.counter = prng_reseed_limits[GNUTLS_RND_NONCE]+1;
	ctx->normal.counter = prng_reseed_limits[GNUTLS_RND_RANDOM]+1;

	wrap_nettle_rnd(_ctx, GNUTLS_RND_NONCE, &tmp, 1);
	wrap_nettle_rnd(_ctx, GNUTLS_RND_RANDOM, &tmp, 1);

	return;
}
Пример #2
0
static void wrap_nettle_rnd_refresh(void *_ctx)
{
	uint8_t nonce_key[NONCE_KEY_SIZE];

	/* this call refreshes the random context */
	wrap_nettle_rnd(&rnd_ctx, GNUTLS_RND_RANDOM, nonce_key, sizeof(nonce_key));

	RND_LOCK(&nonce_ctx);
	nonce_rng_init(&nonce_ctx, nonce_key, sizeof(nonce_key), 0);
	RND_UNLOCK(&nonce_ctx);

	return;
}
Пример #3
0
static int
wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
{
	struct generators_ctx_st *ctx = _ctx;
	struct prng_ctx_st *prng_ctx;
	int ret, reseed = 0;
	uint8_t new_key[PRNG_KEY_SIZE];
	time_t now;

	if (level == GNUTLS_RND_RANDOM || level == GNUTLS_RND_KEY)
		prng_ctx = &ctx->normal;
	else if (level == GNUTLS_RND_NONCE)
		prng_ctx = &ctx->nonce;
	else
		return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);

	/* Two reasons for this memset():
	 *  1. avoid getting filled with valgrind warnings
	 *  2. avoid a cipher/PRNG failure to expose stack data
	 */
	memset(data, 0, datasize);

	now = gnutls_time(0);

	/* We re-seed based on time in addition to output data. That is,
	 * to prevent a temporal state compromise to become permanent for low
	 * traffic sites */
	if (unlikely(_gnutls_detect_fork(prng_ctx->forkid))) {
		reseed = 1;
	} else {
		if (now > prng_ctx->last_reseed + prng_reseed_time[level])
			reseed = 1;
	}

	if (reseed != 0 || prng_ctx->counter > prng_reseed_limits[level]) {
		if (level == GNUTLS_RND_NONCE) {
			ret = wrap_nettle_rnd(_ctx, GNUTLS_RND_RANDOM, new_key, sizeof(new_key));
		} else {

			/* we also use the system entropy to reduce the impact
			 * of a temporal state compromise for these two levels. */
			ret = _rnd_get_system_entropy(new_key, sizeof(new_key));
		}

		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = single_prng_init(prng_ctx, new_key, sizeof(new_key), 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		prng_ctx->last_reseed = now;
		prng_ctx->forkid = _gnutls_get_forkid();
	}

	chacha_crypt(&prng_ctx->ctx, datasize, data, data);
	prng_ctx->counter += datasize;

	if (level == GNUTLS_RND_KEY) { /* prevent backtracking */
		ret = wrap_nettle_rnd(_ctx, GNUTLS_RND_RANDOM, new_key, sizeof(new_key));
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = single_prng_init(prng_ctx, new_key, sizeof(new_key), 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret = 0;

cleanup:
	return ret;
}