/* 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_CRYPTO_FAIL;
	} else if (nlen != 13) {
		return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
	} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
		return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
	}

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

	return TC_CRYPTO_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_CRYPTO_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_CRYPTO_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_CRYPTO_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_CRYPTO_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_CRYPTO_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 ((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_CRYPTO_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_CRYPTO_FAIL;
	}

	return TC_CRYPTO_SUCCESS;
}
