/* cmac_mode.c - TinyCrypt CMAC mode implementation */

/*
 *  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/aes.h>
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>

/* max number of calls until change the key (2^48).*/
const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);

/*
 *  gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
 *  array with byte 0 the most significant and byte 15 the least significant.
 *  High bit carry reduction is based on the primitive polynomial
 *
 *                     X^128 + X^7 + X^2 + X + 1,
 *
 *  which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
 *  since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
 *  addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
 *  add X^128 to both sides to get
 *
 *       X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
 *
 *  and the coefficients of the polynomial on the right hand side form the
 *  string 1000 0111 = 0x87, which is the value of gf_wrap.
 *
 *  This gets used in the following way. Doubling in GF(2^128) is just a left
 *  shift by 1 bit, except when the most significant bit is 1. In the latter
 *  case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
 *  that overflows beyond 128 bits can be replaced by addition of
 *  X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
 *  in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
 *  into the low order byte after a left shift when the starting high order
 *  bit is 1.
 */
const unsigned char gf_wrap = 0x87;

/*
 *  assumes: out != NULL and points to a GF(2^n) value to receive the
 *            doubled value;
 *           in != NULL and points to a 16 byte GF(2^n) value
 *            to double;
 *           the in and out buffers do not overlap.
 *  effects: doubles the GF(2^n) value pointed to by "in" and places
 *           the result in the GF(2^n) value pointed to by "out."
 */
void gf_double(uint8_t *out, uint8_t *in)
{

	/* start with low order byte */
	uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);

	/* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
	uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;

	out += (TC_AES_BLOCK_SIZE - 1);
	for (;;) {
		*out-- = (*x << 1) ^ carry;
		if (x == in) {
			break;
		}
		carry = *x-- >> 7;
	}
}

int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
{

	/* input sanity check: */
	if (s == (TCCmacState_t) 0 ||
	    key == (const uint8_t *) 0) {
		return TC_CRYPTO_FAIL;
	}

	/* put s into a known state */
	_set(s, 0, sizeof(*s));
	s->sched = sched;

	/* configure the encryption key used by the underlying block cipher */
	tc_aes128_set_encrypt_key(s->sched, key);

	/* compute s->K1 and s->K2 from s->iv using s->keyid */
	_set(s->iv, 0, TC_AES_BLOCK_SIZE);
	tc_aes_encrypt(s->iv, s->iv, s->sched);
	gf_double (s->K1, s->iv);
	gf_double (s->K2, s->K1);

	/* reset s->iv to 0 in case someone wants to compute now */
	tc_cmac_init(s);

	return TC_CRYPTO_SUCCESS;
}

int tc_cmac_erase(TCCmacState_t s)
{
	if (s == (TCCmacState_t) 0) {
		return TC_CRYPTO_FAIL;
	}

	/* destroy the current state */
	_set(s, 0, sizeof(*s));

	return TC_CRYPTO_SUCCESS;
}

int tc_cmac_init(TCCmacState_t s)
{
	/* input sanity check: */
	if (s == (TCCmacState_t) 0) {
		return TC_CRYPTO_FAIL;
	}

	/* CMAC starts with an all zero initialization vector */
	_set(s->iv, 0, TC_AES_BLOCK_SIZE);

	/* and the leftover buffer is empty */
	_set(s->leftover, 0, TC_AES_BLOCK_SIZE);
	s->leftover_offset = 0;

	/* Set countdown to max number of calls allowed before re-keying: */
	s->countdown = MAX_CALLS;

	return TC_CRYPTO_SUCCESS;
}

int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
{
	unsigned int i;

	/* input sanity check: */
	if (s == (TCCmacState_t) 0) {
		return TC_CRYPTO_FAIL;
	}
	if (data_length == 0) {
		return  TC_CRYPTO_SUCCESS;
	}
	if (data == (const uint8_t *) 0) {
		return TC_CRYPTO_FAIL;
	}

	if (s->countdown == 0) {
		return TC_CRYPTO_FAIL;
	}

	s->countdown--;

	if (s->leftover_offset > 0) {
		/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
		size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;

		if (data_length < remaining_space) {
			/* still not enough data to encrypt this time either */
			_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
			s->leftover_offset += data_length;
			return TC_CRYPTO_SUCCESS;
		}
		/* leftover block is now full; encrypt it first */
		_copy(&s->leftover[s->leftover_offset],
		      remaining_space,
		      data,
		      remaining_space);
		data_length -= remaining_space;
		data += remaining_space;
		s->leftover_offset = 0;

		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
			s->iv[i] ^= s->leftover[i];
		}
		tc_aes_encrypt(s->iv, s->iv, s->sched);
	}

	/* CBC encrypt each (except the last) of the data blocks */
	while (data_length > TC_AES_BLOCK_SIZE) {
		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
			s->iv[i] ^= data[i];
		}
		tc_aes_encrypt(s->iv, s->iv, s->sched);
		data += TC_AES_BLOCK_SIZE;
		data_length  -= TC_AES_BLOCK_SIZE;
	}

	if (data_length > 0) {
		/* save leftover data for next time */
		_copy(s->leftover, data_length, data, data_length);
		s->leftover_offset = data_length;
	}

	return TC_CRYPTO_SUCCESS;
}

int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
{
	uint8_t *k;
	unsigned int i;

	/* input sanity check: */
	if (tag == (uint8_t *) 0 ||
	    s == (TCCmacState_t) 0) {
		return TC_CRYPTO_FAIL;
	}

	if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
		/* the last message block is a full-sized block */
		k = (uint8_t *) s->K1;
	} else {
		/* the final message block is not a full-sized  block */
		size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;

		_set(&s->leftover[s->leftover_offset], 0, remaining);
		s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
		k = (uint8_t *) s->K2;
	}
	for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
		s->iv[i] ^= s->leftover[i] ^ k[i];
	}

	tc_aes_encrypt(tag, s->iv, s->sched);

	/* erasing state: */
	tc_cmac_erase(s);

	return TC_CRYPTO_SUCCESS;
}
