/* 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); }
static void generator_gate(void) { u_int i; uint8_t temp[KEYSIZE]; for (i = 0; i < KEYSIZE; i += BLOCKSIZE) { increment_counter(); randomdev_encrypt(&random_state.key, random_state.counter.byte, temp + i, BLOCKSIZE); } randomdev_encrypt_init(&random_state.key, temp); memset((void *)temp, 0, KEYSIZE); }
/* Reseed Mutex is held, and buf points to a whole number of blocks. */ static __inline void random_fortuna_genrandom(uint8_t *buf, u_int bytecount) { static uint8_t temp[BLOCKSIZE*(KEYSIZE/BLOCKSIZE)]; u_int blockcount; /* F&S - assert(n < 2^20) */ KASSERT((bytecount <= (1 << 20)), ("invalid single read request to fortuna of %d bytes", bytecount)); /* F&S - r = first-n-bytes(GenerateBlocks(ceil(n/16))) */ blockcount = bytecount / BLOCKSIZE; random_fortuna_genblocks(buf, blockcount); /* TODO: FIX! remove memcpy()! */ if (bytecount % BLOCKSIZE > 0) { random_fortuna_genblocks(temp, 1); memcpy(buf + (blockcount * BLOCKSIZE), temp, bytecount % BLOCKSIZE); } /* F&S - K = GenerateBlocks(2) */ random_fortuna_genblocks(temp, KEYSIZE/BLOCKSIZE); randomdev_encrypt_init(&fortuna_state.key, temp); memset(temp, 0, sizeof(temp)); }
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); }