/*
 * fortuna.c
 *		Fortuna-like PRNG.
 *
 * Copyright (c) 2005 Marko Kreen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *	  notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *	  notice, this list of conditions and the following disclaimer in the
 *	  documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * contrib/pgcrypto/fortuna.c
 */

#include <arch/arch.h>
#include <time.h>

#include <random/fortuna.h>
#include <random/rijndael.h>
#include <random/sha2.h>

/*
 * Why Fortuna-like: There does not seem to be any definitive reference
 * on Fortuna in the net.  Instead this implementation is based on
 * following references:
 *
 * http://en.wikipedia.org/wiki/Fortuna_(PRNG)
 *	 - Wikipedia article
 * http://jlcooke.ca/random/
 *	 - Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
 */

/*
 * There is some confusion about whether and how to carry forward
 * the state of the pools.	Seems like original Fortuna does not
 * do it, resetting hash after each request.  I guess expecting
 * feeding to happen more often that requesting.   This is absolutely
 * unsuitable for pgcrypto, as nothing asynchronous happens here.
 *
 * J.L. Cooke fixed this by feeding previous hash to new re-initialized
 * hash context.
 *
 * Fortuna predecessor Yarrow requires ability to query intermediate
 * 'final result' from hash, without affecting it.
 *
 * This implementation uses the Yarrow method - asking intermediate
 * results, but continuing with old state.
 */

/*
 * Algorithm parameters
 */

/*
 * How many pools.
 *
 * Original Fortuna uses 32 pools, that means 32'th pool is
 * used not earlier than in 13th year.	This is a waste in
 * pgcrypto, as we have very low-frequancy seeding.  Here
 * is preferable to have all entropy usable in reasonable time.
 *
 * With 23 pools, 23th pool is used after 9 days which seems
 * more sane.
 *
 * In our case the minimal cycle time would be bit longer
 * than the system-randomness feeding frequency.
 */
enum { numPools = 23,

       /* in microseconds */
       reseedInterval = 100000, /* 0.1 sec */

       /* for one big request, reseed after this many bytes */
       reseedBytes = (1024 * 1024),

       /*
	* Skip reseed if pool 0 has less than this many
	* bytes added since last reseed.
	*/
       pool0Fill = (256 / 8),

       /*
	* Algorithm constants
	*/

       /* Both cipher key size and hash result size */
       block = 32,

       /* cipher block size */
       ciphBlock = 16 };

/* for internal wrappers */
typedef SHA256Ctx mdCtx;
typedef rijndaelCtx ciphCtx;

struct FState {
	uint8_t counter[ciphBlock];
	uint8_t result[ciphBlock];
	uint8_t key[block];
	mdCtx pool[numPools];
	ciphCtx ciph;
	unsigned reseedCount;
	int32_t lastReseedTime;
	unsigned pool0Bytes;
	unsigned rndPos;
	int tricksDone;
};
typedef struct FState FState;

/*
 * Use our own wrappers here.
 * - Need to get intermediate result from digest, without affecting it.
 * - Need re-set key on a cipher context.
 * - Algorithms are guaranteed to exist.
 * - No memory allocations.
 */

static void ciph_init(ciphCtx *ctx, const uint8_t *key, int klen)
{
	rijndael_set_key(ctx, (const uint32_t *)key, klen, 1);
}

static void ciph_encrypt(ciphCtx *ctx, const uint8_t *in, uint8_t *out)
{
	rijndael_encrypt(ctx, (const uint32_t *)in, (uint32_t *)out);
}

static void md_init(mdCtx *ctx)
{
	SHA256_Init(ctx);
}

static void md_update(mdCtx *ctx, const uint8_t *data, int len)
{
	SHA256_Update(ctx, data, len);
}

static void md_result(mdCtx *ctx, uint8_t *dst)
{
	SHA256Ctx tmp;

	memmove(&tmp, ctx, sizeof(*ctx));
	SHA256_Final(dst, &tmp);
	memset(&tmp, 0, sizeof(tmp));
}

/*
 * initialize state
 */
static void init_state(FState *st)
{
	int i;

	memset(st, 0, sizeof(*st));
	for (i = 0; i < numPools; i++)
		md_init(&st->pool[i]);
}

/*
 * Endianess does not matter.
 * It just needs to change without repeating.
 */
static void inc_counter(FState *st)
{
	uint32_t *val = (uint32_t *)st->counter;

	if (++val[0])
		return;
	if (++val[1])
		return;
	if (++val[2])
		return;
	++val[3];
}

/*
 * This is called 'cipher in counter mode'.
 */
static void encrypt_counter(FState *st, uint8_t *dst)
{
	ciph_encrypt(&st->ciph, st->counter, dst);
	inc_counter(st);
}

/*
 * The time between reseed must be at least reseedInterval
 * microseconds.
 */
static int enough_time_passed(FState *st)
{
	int ok;
	int32_t now;
	int32_t last = st->lastReseedTime;

	now = tsc2sec(read_tsc());

	/* check how much time has passed */
	ok = 0;
	if (now - last >= reseedInterval)
		ok = 1;

	/* reseed will happen, update lastReseedTime */
	if (ok)
		st->lastReseedTime = now;

	return ok;
}

/*
 * generate new key from all the pools
 */
static void reseed(FState *st)
{
	unsigned k;
	unsigned n;
	mdCtx key_md;
	uint8_t buf[block];

	/* set pool as empty */
	st->pool0Bytes = 0;

	/*
	 * Both #0 and #1 reseed would use only pool 0. Just skip #0 then.
	 */
	n = ++st->reseedCount;

	/*
	 * The goal: use k-th pool only 1/(2^k) of the time.
	 */
	md_init(&key_md);
	for (k = 0; k < numPools; k++) {
		md_result(&st->pool[k], buf);
		md_update(&key_md, buf, block);

		if (n & 1 || !n)
			break;
		n >>= 1;
	}

	/* add old key into mix too */
	md_update(&key_md, st->key, block);

	/* now we have new key */
	md_result(&key_md, st->key);

	/* use new key */
	ciph_init(&st->ciph, st->key, block);

	memset(&key_md, 0, sizeof(key_md));
	memset(buf, 0, block);
}

/*
 * Pick a random pool.	This uses key bytes as random source.
 */
static unsigned get_rand_pool(FState *st)
{
	unsigned rnd;

	/*
	 * This slightly prefers lower pools - thats OK.
	 */
	rnd = st->key[st->rndPos] % numPools;

	st->rndPos++;
	if (st->rndPos >= block)
		st->rndPos = 0;

	return rnd;
}

/*
 * update pools
 */
static void add_entropy(FState *st, const uint8_t *data, unsigned len)
{
	unsigned pos;
	uint8_t hash[block];
	mdCtx md;

	/* hash given data */
	md_init(&md);
	md_update(&md, data, len);
	md_result(&md, hash);

	/*
	 * Make sure the pool 0 is initialized, then update randomly.
	 */
	if (st->reseedCount == 0)
		pos = 0;
	else
		pos = get_rand_pool(st);
	md_update(&st->pool[pos], hash, block);

	if (pos == 0)
		st->pool0Bytes += len;

	memset(hash, 0, block);
	memset(&md, 0, sizeof(md));
}

/*
 * Just take 2 next blocks as new key
 */
static void rekey(FState *st)
{
	encrypt_counter(st, st->key);
	encrypt_counter(st, st->key + ciphBlock);
	ciph_init(&st->ciph, st->key, block);
}

/*
 * Hide public constants. (counter, pools > 0)
 *
 * This can also be viewed as spreading the startup
 * entropy over all of the components.
 */
static void startup_tricks(FState *st)
{
	int i;
	uint8_t buf[block];

	/* Use next block as counter. */
	encrypt_counter(st, st->counter);

	/* Now shuffle pools, excluding #0 */
	for (i = 1; i < numPools; i++) {
		encrypt_counter(st, buf);
		encrypt_counter(st, buf + ciphBlock);
		md_update(&st->pool[i], buf, block);
	}
	memset(buf, 0, block);

	/* Hide the key. */
	rekey(st);

	/* This can be done only once. */
	st->tricksDone = 1;
}

static void extract_data(FState *st, unsigned count, uint8_t *dst)
{
	unsigned n;
	unsigned block_nr = 0;

	/* Should we reseed? */
	if (st->pool0Bytes >= pool0Fill || st->reseedCount == 0)
		if (enough_time_passed(st))
			reseed(st);

	/* Do some randomization on first call */
	if (!st->tricksDone)
		startup_tricks(st);

	while (count > 0) {
		/* produce bytes */
		encrypt_counter(st, st->result);

		/* copy result */
		if (count > ciphBlock)
			n = ciphBlock;
		else
			n = count;
		memmove(dst, st->result, n);
		dst += n;
		count -= n;

		/* must not give out too many bytes with one key */
		block_nr++;
		if (block_nr > (reseedBytes / ciphBlock)) {
			rekey(st);
			block_nr = 0;
		}
	}
	/* Set new key for next request. */
	rekey(st);
}

static FState mainState;
static int initDone;

static void init()
{
	init_state(&mainState);
	initDone = 1;
}

/*
 * public interface
 */

void fortuna_add_entropy(const uint8_t *data, unsigned len)
{
	if (!initDone)
		init();

	if (!data || !len)
		return;
	add_entropy(&mainState, data, len);
}

void fortuna_get_bytes(unsigned len, uint8_t *dst)
{
	if (!initDone)
		init();

	if (!dst || !len)
		return;
	extract_data(&mainState, len, dst);
}
