/* * fortuna_mutex must be held by callers of this function */ static int fortuna_init(void) { if (!init_done) { init_state(&main_state); init_done = 1; } if (!have_entropy) have_entropy = fortuna_reseed(); return (init_done && have_entropy); }
/* Get some random bytes from the generator. */ int fortuna_get_bytes(uint8_t *buffer, int count) { int remaining_bytes = 0; uint8_t *block_buffer = 0; uint8_t *seed_buffer = 0; int blocks_done = 0; int seed_size = 0; if ((count > 0) && (count < (2 * 1024 * 1024))) { // probably we need to initialize and update fortuna_generator.last_reseed_time? if ((jiffies - fortuna_generator.last_reseed_time >= FORTUNA_MINIMUM_RESEED_MS) && (1 >= FORTUNA_MINIMUM_RESEED_ENTR)) { /* FIXME to check 'size' of pool 0 */ seed_buffer = kalloc(sizeof(uint8_t) * FORTUNA_POOL_COUNT * FORTUNA_HASH_SIZE); /* Assume that we use every pool hash... */ if (NULL == seed_buffer) { return 0; } seed_size = fortuna_extract_seed(seed_buffer, (sizeof(uint8_t) * FORTUNA_POOL_COUNT * FORTUNA_HASH_SIZE)); fortuna_reseed(seed_buffer, seed_size); kfree(seed_buffer); } /* Get random blocks until we have our data. */ for (remaining_bytes = count; remaining_bytes > 0; remaining_bytes -= FORTUNA_ENCRYPT_BLOCK_SIZE) { if (remaining_bytes / FORTUNA_ENCRYPT_BLOCK_SIZE > 0) { /* At least one full block remaining? Can copy directly without overflowing. */ fortuna_generate_block(buffer + (FORTUNA_ENCRYPT_BLOCK_SIZE * blocks_done++), FORTUNA_ENCRYPT_BLOCK_SIZE); /* TODO check! */ } else { /* This'll only be necessary for the last block, and only if requested byte count != multiple of block size */ block_buffer = kalloc(FORTUNA_ENCRYPT_BLOCK_SIZE); if (NULL != block_buffer) { fortuna_generate_block(block_buffer, FORTUNA_ENCRYPT_BLOCK_SIZE); /* Copy required part of block to output */ memcpy(buffer + (blocks_done * FORTUNA_ENCRYPT_BLOCK_SIZE), block_buffer, remaining_bytes); kfree(block_buffer); } else { return 0; } } } return 1; } else { /* Not allowed to produce more than 1MiB of data at once */ return 0; } }
static int fortuna_bytes(unsigned char *outdata, int size) { int ret = 0; HEIMDAL_MUTEX_lock(&fortuna_mutex); if (!fortuna_init()) goto out; resend_bytes += size; if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) { resend_bytes = 0; fortuna_reseed(); } extract_data(&main_state, size, outdata); ret = 1; out: HEIMDAL_MUTEX_unlock(&fortuna_mutex); return ret; }