/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */

/*
 *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *    - Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *    - 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.
 *
 *    - Neither the name of Intel Corporation nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
 */

#include <tinycrypt/hmac_prng.h>
#include <tinycrypt/hmac.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>

/*
 * min bytes in the seed string.
 * MIN_SLEN*8 must be at least the expected security level.
 */
static const unsigned int MIN_SLEN = 32;

/*
 * max bytes in the seed string;
 * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
 */
static const unsigned int MAX_SLEN = UINT32_MAX;

/*
 * max bytes in the personalization string;
 * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
 */
static const unsigned int MAX_PLEN = UINT32_MAX;

/*
 * max bytes in the additional_info string;
 * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
 */
static const unsigned int MAX_ALEN = UINT32_MAX;

/*
 * max number of generates between re-seeds;
 * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
 * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
 */
static const unsigned int MAX_GENS = UINT32_MAX;

/*
 * maximum bytes per generate call;
 * SP800-90A specifies a maximum up to 2^19.
 */
static const unsigned int  MAX_OUT = (1 << 19);

/*
 * Assumes: prng != NULL
 */
static void update(TCHmacPrng_t prng, const uint8_t *data, unsigned int datalen, const uint8_t *additional_data, unsigned int additional_datalen)
{
	const uint8_t separator0 = 0x00;
	const uint8_t separator1 = 0x01;

	/* configure the new prng key into the prng's instance of hmac */
	tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));

	/* use current state, e and separator 0 to compute a new prng key: */
	(void)tc_hmac_init(&prng->h);
	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
	(void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));

	if (data && datalen)
		(void)tc_hmac_update(&prng->h, data, datalen);
	if (additional_data && additional_datalen)
		(void)tc_hmac_update(&prng->h, additional_data, additional_datalen);

	(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);

	/* configure the new prng key into the prng's instance of hmac */
	(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));

	/* use the new key to compute a new state variable v */
	(void)tc_hmac_init(&prng->h);
	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
	(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);

	if (data == 0 || datalen == 0)
		return;

	/* configure the new prng key into the prng's instance of hmac */
	tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));

	/* use current state, e and separator 1 to compute a new prng key: */
	(void)tc_hmac_init(&prng->h);
	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
	(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
	(void)tc_hmac_update(&prng->h, data, datalen);
	if (additional_data && additional_datalen)
		(void)tc_hmac_update(&prng->h, additional_data, additional_datalen);
	(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);

	/* configure the new prng key into the prng's instance of hmac */
	(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));

	/* use the new key to compute a new state variable v */
	(void)tc_hmac_init(&prng->h);
	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
	(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
}

int tc_hmac_prng_init(TCHmacPrng_t prng,
		      const uint8_t *personalization,
		      unsigned int plen)
{

	/* input sanity check: */
	if (prng == (TCHmacPrng_t) 0 ||
	    personalization == (uint8_t *) 0 ||
	    plen > MAX_PLEN) {
		return TC_CRYPTO_FAIL;
	}

	/* put the generator into a known state: */
	_set(prng->key, 0x00, sizeof(prng->key));
	_set(prng->v, 0x01, sizeof(prng->v));

	update(prng, personalization, plen, 0, 0);

	/* force a reseed before allowing tc_hmac_prng_generate to succeed: */
	prng->countdown = 0;

	return TC_CRYPTO_SUCCESS;
}

int tc_hmac_prng_reseed(TCHmacPrng_t prng,
			const uint8_t *seed,
			unsigned int seedlen,
			const uint8_t *additional_input,
			unsigned int additionallen)
{

	/* input sanity check: */
	if (prng == (TCHmacPrng_t) 0 ||
	    seed == (const uint8_t *) 0 ||
	    seedlen < MIN_SLEN ||
	    seedlen > MAX_SLEN) {
		return TC_CRYPTO_FAIL;
	}

	if (additional_input != (const uint8_t *) 0) {
		/*
		 * Abort if additional_input is provided but has inappropriate
		 * length
		 */
		if (additionallen == 0 ||
		    additionallen > MAX_ALEN) {
			return TC_CRYPTO_FAIL;
		} else {
			/* call update for the seed and additional_input */
			update(prng, seed, seedlen, additional_input, additionallen);
		}
	} else {
		/* call update only for the seed */
		update(prng, seed, seedlen, 0, 0);
	}

	/* ... and enable hmac_prng_generate */
	prng->countdown = MAX_GENS;

	return TC_CRYPTO_SUCCESS;
}

int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
{
	unsigned int bufferlen;

	/* input sanity check: */
	if (out == (uint8_t *) 0 ||
	    prng == (TCHmacPrng_t) 0 ||
	    outlen == 0 ||
	    outlen > MAX_OUT) {
		return TC_CRYPTO_FAIL;
	} else if (prng->countdown == 0) {
		return TC_HMAC_PRNG_RESEED_REQ;
	}

	prng->countdown--;

	while (outlen != 0) {
		/* configure the new prng key into the prng's instance of hmac */
		tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));

		/* operate HMAC in OFB mode to create "random" outputs */
		(void)tc_hmac_init(&prng->h);
		(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
		(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);

		bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
			outlen : TC_SHA256_DIGEST_SIZE;
		(void)_copy(out, bufferlen, prng->v, bufferlen);

		out += bufferlen;
		outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
			(outlen - TC_SHA256_DIGEST_SIZE) : 0;
	}

	/* block future PRNG compromises from revealing past state */
	update(prng, 0, 0, 0, 0);

	return TC_CRYPTO_SUCCESS;
}
