예제 #1
0
/*
 * 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);
}
예제 #2
0
/* 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;
	}
}
예제 #3
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;
}