Beispiel #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);
}
Beispiel #2
0
/* Reseed Mutex is held, and buf points to a whole number of blocks. */
static __inline void
random_fortuna_genblocks(uint8_t *buf, u_int blockcount)
{
	u_int i;

	for (i = 0u; i < blockcount; i++) {
		/* F&S - r = r|E(K,C) */
		randomdev_encrypt(&fortuna_state.key, fortuna_state.counter.byte, buf, BLOCKSIZE);
		buf += BLOCKSIZE;

		/* F&S - C = C + 1 */
		uint128_increment(&fortuna_state.counter.whole);
	}
}
Beispiel #3
0
/*
 * Create a psuedorandom output stream of 'blockcount' blocks using a CTR-mode
 * cipher or similar.  The 128-bit counter is supplied in the in-out parmeter
 * 'ctr.'  The output stream goes to 'd_out.'  'blockcount' RANDOM_BLOCKSIZE
 * bytes are generated.
 */
void
randomdev_keystream(union randomdev_key *context, uint128_t *ctr,
    void *d_out, u_int blockcount)
{
	u_int i;

	if (random_chachamode) {
		uint128_t lectr;

		/*
		 * Chacha always encodes and increments the counter little
		 * endian.  So on BE machines, we must provide a swapped
		 * counter to chacha, and swap the output too.
		 */
		le128enc(&lectr, *ctr);

		chacha_ivsetup(&context->chacha, NULL, (const void *)&lectr);
		chacha_encrypt_bytes(&context->chacha, NULL, d_out,
		    RANDOM_BLOCKSIZE * blockcount);

		/*
		 * Decode Chacha-updated LE counter to native endian and store
		 * it back in the caller's in-out parameter.
		 */
		chacha_ctrsave(&context->chacha, (void *)&lectr);
		*ctr = le128dec(&lectr);
	} else {
		for (i = 0; i < blockcount; i++) {
			/*-
			 * FS&K - r = r|E(K,C)
			 *      - C = C + 1
			 */
			rijndael_blockEncrypt(&context->cipher, &context->key,
			    (void *)ctr, RANDOM_BLOCKSIZE * 8, d_out);
			d_out = (char *)d_out + RANDOM_BLOCKSIZE;
			uint128_increment(ctr);
		}
	}
}