Example #1
0
/* Reseed Mutex is held */
static void
reseed(uint8_t *junk, u_int length)
{
	struct randomdev_hash context;
	uint8_t hash[KEYSIZE];

	KASSERT(fortuna_state.minpoolsize > 0, ("random: Fortuna threshold = 0"));
#ifdef _KERNEL
	mtx_assert(&random_reseed_mtx, MA_OWNED);
#endif

	/* FS&K - K = Hd(K|s) where Hd(m) is H(H(0^512|m)) */
	randomdev_hash_init(&context);
	randomdev_hash_iterate(&context, zero_region, 512/8);
	randomdev_hash_iterate(&context, &fortuna_state.key, sizeof(fortuna_state.key));
	randomdev_hash_iterate(&context, junk, length);
	randomdev_hash_finish(&context, hash);
	randomdev_hash_init(&context);
	randomdev_hash_iterate(&context, hash, KEYSIZE);
	randomdev_hash_finish(&context, hash);
	randomdev_encrypt_init(&fortuna_state.key, hash);
	memset(hash, 0, sizeof(hash));

	/* Unblock the device if it was blocked due to being unseeded */
	if (uint128_is_zero(fortuna_state.counter.whole))
		random_adaptor_unblock();
	/* FS&K - C = C + 1 */
	uint128_increment(&fortuna_state.counter.whole);
}
Example #2
0
/* Internal function to hand external entropy to the PRNG */
void
random_fortuna_write(uint8_t *buf, u_int count)
{
	uint8_t temp[KEYSIZE];
	int i;
	uintmax_t timestamp;

	timestamp = get_cyclecount();
	randomdev_hash_iterate(&fortuna_start_cache.hash, &timestamp, sizeof(timestamp));
	randomdev_hash_iterate(&fortuna_start_cache.hash, buf, count);
	timestamp = get_cyclecount();
	randomdev_hash_iterate(&fortuna_start_cache.hash, &timestamp, sizeof(timestamp));
	randomdev_hash_finish(&fortuna_start_cache.hash, temp);
	for (i = 0; i < KEYSIZE; i++)
		fortuna_start_cache.junk[(fortuna_start_cache.length + i)%PAGE_SIZE] ^= temp[i];
	fortuna_start_cache.length += KEYSIZE;

#ifdef RANDOM_DEBUG
	printf("random: %s - ", __func__);
	for (i = 0; i < KEYSIZE; i++)
		printf("%02X", temp[i]);
	printf("\n");
#endif

	memset(temp, 0, KEYSIZE);

	/* We must be locked for all this as plenty of state gets messed with */
	mtx_lock(&random_reseed_mtx);

	randomdev_hash_init(&fortuna_start_cache.hash);

	reseed(fortuna_start_cache.junk, MIN(PAGE_SIZE, fortuna_start_cache.length));
	memset(fortuna_start_cache.junk, 0, sizeof(fortuna_start_cache.junk));

	mtx_unlock(&random_reseed_mtx);
}
Example #3
0
static void
reseed(u_int fastslow)
{
	/* Interrupt-context stack is a limited resource; make large
	 * structures static.
	 */
	static uint8_t v[TIMEBIN][KEYSIZE];	/* v[i] */
	static struct randomdev_hash context;
	uint8_t hash[KEYSIZE];			/* h' */
	uint8_t temp[KEYSIZE];
	u_int i;
	enum esource j;

#if 0
	printf("Yarrow: %s reseed\n", fastslow == FAST ? "fast" : "slow");
#endif

	/* The reseed task must not be jumped on */
	mtx_lock(&random_reseed_mtx);

	/* 1. Hash the accumulated entropy into v[0] */

	randomdev_hash_init(&context);
	/* Feed the slow pool hash in if slow */
	if (fastslow == SLOW)
		randomdev_hash_iterate(&context,
			&random_state.pool[SLOW].hash,
			sizeof(struct randomdev_hash));
	randomdev_hash_iterate(&context,
		&random_state.pool[FAST].hash, sizeof(struct randomdev_hash));
	randomdev_hash_finish(&context, v[0]);

	/* 2. Compute hash values for all v. _Supposed_ to be computationally
	 *    intensive.
	 */

	if (random_state.bins > TIMEBIN)
		random_state.bins = TIMEBIN;
	for (i = 1; i < random_state.bins; i++) {
		randomdev_hash_init(&context);
		/* v[i] #= h(v[i - 1]) */
		randomdev_hash_iterate(&context, v[i - 1], KEYSIZE);
		/* v[i] #= h(v[0]) */
		randomdev_hash_iterate(&context, v[0], KEYSIZE);
		/* v[i] #= h(i) */
		randomdev_hash_iterate(&context, &i, sizeof(u_int));
		/* Return the hashval */
		randomdev_hash_finish(&context, v[i]);
	}

	/* 3. Compute a new key; h' is the identity function here;
	 *    it is not being ignored!
	 */

	randomdev_hash_init(&context);
	randomdev_hash_iterate(&context, &random_state.key, KEYSIZE);
	for (i = 1; i < random_state.bins; i++)
		randomdev_hash_iterate(&context, &v[i], KEYSIZE);
	randomdev_hash_finish(&context, temp);
	randomdev_encrypt_init(&random_state.key, temp);

	/* 4. Recompute the counter */

	clear_counter();
	randomdev_encrypt(&random_state.key, random_state.counter.byte, temp, BLOCKSIZE);
	memcpy(random_state.counter.byte, temp, BLOCKSIZE);

	/* 5. Reset entropy estimate accumulators to zero */

	for (i = 0; i <= fastslow; i++)
		for (j = RANDOM_START; j < ENTROPYSOURCE; j++)
			random_state.pool[i].source[j].bits = 0;

	/* 6. Wipe memory of intermediate values */

	memset((void *)v, 0, sizeof(v));
	memset((void *)temp, 0, sizeof(temp));
	memset((void *)hash, 0, sizeof(hash));

	/* 7. Dump to seed file */
	/* XXX Not done here yet */

	/* Unblock the device if it was blocked due to being unseeded */
	randomdev_unblock();

	/* Release the reseed mutex */
	mtx_unlock(&random_reseed_mtx);
}
Example #4
0
/* The argument buf points to a whole number of blocks. */
void
random_fortuna_read(uint8_t *buf, u_int bytecount)
{
#ifdef _KERNEL
	sbintime_t thistime;
#endif
	struct randomdev_hash context;
	uint8_t s[NPOOLS*KEYSIZE], temp[KEYSIZE];
	int i;
	u_int seedlength;

	/* We must be locked for all this as plenty of state gets messed with */
	mtx_lock(&random_reseed_mtx);

	/* if buf == NULL and bytecount == 0 then this is the pre-read. */
	/* if buf == NULL and bytecount != 0 then this is the post-read; ignore. */
	if (buf == NULL) {
		if (bytecount == 0) {
			if (fortuna_state.pool[0].length >= fortuna_state.minpoolsize
#ifdef _KERNEL
			/* F&S - Use 'getsbinuptime()' to prevent reseed-spamming. */
		    	&& ((thistime = getsbinuptime()) - fortuna_state.lasttime > hz/10)
#endif
		    	) {
#ifdef _KERNEL
				fortuna_state.lasttime = thistime;
#endif

				seedlength = 0U;
				/* F&S - ReseedCNT = ReseedCNT + 1 */
				fortuna_state.reseedcount++;
				/* s = \epsilon by default */
				for (i = 0; i < NPOOLS; i++) {
					/* F&S - if Divides(ReseedCnt, 2^i) ... */
					if ((fortuna_state.reseedcount % (1 << i)) == 0U) {
						seedlength += KEYSIZE;
						/* F&S - temp = (P_i) */
						randomdev_hash_finish(&fortuna_state.pool[i].hash, temp);
						/* F&S - P_i = \epsilon */
						randomdev_hash_init(&fortuna_state.pool[i].hash);
						fortuna_state.pool[i].length = 0U;
						/* F&S - s = s|H(temp) */
						randomdev_hash_init(&context);
						randomdev_hash_iterate(&context, temp, KEYSIZE);
						randomdev_hash_finish(&context, s + i*KEYSIZE);
					}
					else
						break;
				}
#ifdef RANDOM_DEBUG
				printf("random: active reseed: reseedcount [%d] ", fortuna_state.reseedcount);
				for (i = 0; i < NPOOLS; i++)
					printf(" %d", fortuna_state.pool[i].length);
				printf("\n");
#endif
				/* F&S */
				reseed(s, seedlength);

				/* Clean up */
				memset(s, 0, seedlength);
				seedlength = 0U;
				memset(temp, 0, sizeof(temp));
				memset(&context, 0, sizeof(context));
			}
		}
	}
	/* if buf != NULL do a regular read. */
	else
		random_fortuna_genrandom(buf, bytecount);

	mtx_unlock(&random_reseed_mtx);
}