/* ccm_mode.c - TinyCrypt implementation of CCM mode */

/*
 *  Copyright (C) 2015 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/ccm_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>

#include <stdio.h>

int32_t tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
		      uint32_t nlen, uint32_t mlen)
{

	/* input sanity check: */
	if (c == (TCCcmMode_t) 0 ||
	    sched == (TCAesKeySched_t) 0 ||
	    nonce == (uint8_t *) 0) {
		return TC_FAIL;
	} else if (nlen != 13) {
		return TC_FAIL; /* The allowed nonce size is: 13. See documentation.*/
	} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
		return TC_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
	}

	c->mlen = mlen;
	c->sched = sched;
	c->nonce = nonce;

	return TC_SUCCESS;
}

/**
 * Variation of CBC-MAC mode used in CCM.
 */
static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, uint32_t dlen,
			 uint32_t flag, TCAesKeySched_t sched)
{

	uint32_t i;

	if (flag > 0) {
		T[0] ^= (uint8_t)(dlen >> 8);
		T[1] ^= (uint8_t)(dlen);
		dlen += 2; i = 2;
	} else {
		i = 0;
	}

	while (i < dlen) {
		T[i++ % (Nb * Nk)] ^= *data++;
		if (((i % (Nb * Nk)) == 0) || dlen == i) {
			(void) tc_aes_encrypt(T, T, sched);
		}
	}
}

/**
 * Variation of CTR mode used in CCM.
 * The CTR mode used by CCM is slightly different than the conventional CTR
 * mode (the counter is increased before encryption, instead of after
 * encryption). Besides, it is assumed that the counter is stored in the last
 * 2 bytes of the nonce.
 */
static int32_t ccm_ctr_mode(uint8_t *out, uint32_t outlen, const uint8_t *in,
			     uint32_t inlen, uint8_t *ctr, const TCAesKeySched_t sched)
{

	uint8_t buffer[TC_AES_BLOCK_SIZE];
	uint8_t nonce[TC_AES_BLOCK_SIZE];
	uint16_t block_num;
	uint32_t i;

	/* input sanity check: */
	if (out == (uint8_t *) 0 ||
	    in == (uint8_t *) 0 ||
	    ctr == (uint8_t *) 0 ||
	    sched == (TCAesKeySched_t) 0 ||
	    inlen == 0 ||
	    outlen == 0 ||
	    outlen != inlen) {
		return TC_FAIL;
	}

	/* copy the counter to the nonce */
	(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));

	/* select the last 2 bytes of the nonce to be incremented */
	block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
	for (i = 0; i < inlen; ++i) {
		if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
			block_num++;
			nonce[14] = (uint8_t)(block_num >> 8);
			nonce[15] = (uint8_t)(block_num);
			if (!tc_aes_encrypt(buffer, nonce, sched)) {
				return TC_FAIL;
			}
		}
		/* update the output */
		*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
	}

	/* update the counter */
	ctr[14] = nonce[14]; ctr[15] = nonce[15];

	return TC_SUCCESS;
}

int32_t tc_ccm_generation_encryption(uint8_t *out, const uint8_t *associated_data,
				     uint32_t alen, const uint8_t *payload,
				     uint32_t plen, TCCcmMode_t c)
{
	/* input sanity check: */
	if ((out == (uint8_t *) 0) ||
	    (c == (TCCcmMode_t) 0) ||
	    ((plen > 0) && (payload == (uint8_t *) 0)) ||
	    ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
	    (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
	    (plen >= TC_CCM_PAYLOAD_MAX_BYTES)) { /* payload size unsupported */
		return TC_FAIL;
	}

	uint8_t b[Nb * Nk];
	uint8_t tag[Nb * Nk];
	uint32_t i;

	/* GENERATING THE AUTHENTICATION TAG: */

	/* formatting the sequence b for authentication: */
	b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
	for (i = 1; i <= 13; ++i) {
		b[i] = c->nonce[i - 1];
	}
	b[14] = (uint8_t)(plen >> 8);
	b[15] = (uint8_t)(plen);

	/* computing the authentication tag using cbc-mac: */
	(void) tc_aes_encrypt(tag, b, c->sched);
	if (alen > 0) {
		ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
	}
	if (plen > 0) {
		ccm_cbc_mac(tag, payload, plen, 0, c->sched);
	}

	/* ENCRYPTION: */

	/* formatting the sequence b for encryption: */
	b[0] = 1; /* q - 1 = 2 - 1 = 1 */
	b[14] = b[15] = TC_ZERO_BYTE;

	/* encrypting payload using ctr mode: */
	ccm_ctr_mode(out, plen, payload, plen, b, c->sched);

	b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/

	/* encrypting b and adding the tag to the output: */
	(void) tc_aes_encrypt(b, b, c->sched);
	out += plen;
	for (i = 0; i < c->mlen; ++i) {
		*out++ = tag[i] ^ b[i];
	}

	return TC_SUCCESS;
}

int32_t tc_ccm_decryption_verification(uint8_t *out, const uint8_t *associated_data,
				       uint32_t alen, const uint8_t *payload,
				       uint32_t plen, TCCcmMode_t c)
{

	/* input sanity check: */
	if ((plen <= alen) ||
	    (out == (uint8_t *) 0) ||
	    (c == (TCCcmMode_t) 0) ||
	    ((plen > 0) && (payload == (uint8_t *) 0)) ||
	    ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
	    (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
	    (plen >= TC_CCM_PAYLOAD_MAX_BYTES)) { /* payload size unsupported */
		return TC_FAIL;
	}

	uint8_t b[Nb * Nk];
	uint8_t tag[Nb * Nk];
	uint32_t i;

	/* DECRYPTION: */

	/* formatting the sequence b for decryption: */
	b[0] = 1; /* q - 1 = 2 - 1 = 1 */
	for (i = 1; i < 14; ++i) {
		b[i] = c->nonce[i - 1];
	}
	b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */

	/* decrypting payload using ctr mode: */
	ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);

	b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */

	/* encrypting b and restoring the tag from input: */
	(void) tc_aes_encrypt(b, b, c->sched);
	for (i = 0; i < c->mlen; ++i) {
		tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
	}

	/* VERIFYING THE AUTHENTICATION TAG: */

	/* formatting the sequence b for authentication: */
	b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
	for (i = 1; i < 14; ++i) {
		b[i] = c->nonce[i - 1];
	}
	b[14] = (uint8_t)((plen - c->mlen) >> 8);
	b[15] = (uint8_t)(plen - c->mlen);

	/* computing the authentication tag using cbc-mac: */
	(void) tc_aes_encrypt(b, b, c->sched);
	if (alen > 0) {
		ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
	}
	if (plen > 0) {
		ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
	}

	/* comparing the received tag and the computed one: */
	if (_compare(b, tag, c->mlen) != 0) {
		/* erase the decrypted buffer in case of mac validation failure: */
		_set(out, 0, sizeof(*out));
		return TC_FAIL;
	}

	return TC_SUCCESS;
}
