/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <string.h>

#include <zephyr/zephyr.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/bluetooth/crypto.h>

#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
#define LOG_MODULE_NAME bt_aes_ccm
#include "common/log.h"

static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
{
	dst[0] = a[0] ^ b[0];
	dst[1] = a[1] ^ b[1];
	dst[2] = a[2] ^ b[2];
	dst[3] = a[3] ^ b[3];
	dst[4] = a[4] ^ b[4];
	dst[5] = a[5] ^ b[5];
	dst[6] = a[6] ^ b[6];
	dst[7] = a[7] ^ b[7];
	dst[8] = a[8] ^ b[8];
	dst[9] = a[9] ^ b[9];
	dst[10] = a[10] ^ b[10];
	dst[11] = a[11] ^ b[11];
	dst[12] = a[12] ^ b[12];
	dst[13] = a[13] ^ b[13];
	dst[14] = a[14] ^ b[14];
	dst[15] = a[15] ^ b[15];
}

/* b field is assumed to have the nonce already present in bytes 1-13 */
static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
			    size_t mic_size, uint16_t msg_len, uint8_t b[16],
			    uint8_t X0[16])
{
	int i, j, err;

	/* X_0 = e(AppKey, flags || nonce || length) */
	b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;

	sys_put_be16(msg_len, b + 14);

	err = bt_encrypt_be(key, b, X0);
	if (err) {
		return err;
	}

	/* If AAD is being used to authenticate, include it here */
	if (aad_len) {
		sys_put_be16(aad_len, b);

		for (i = 0; i < sizeof(uint16_t); i++) {
			b[i] = X0[i] ^ b[i];
		}

		j = 0;
		aad_len += sizeof(uint16_t);
		while (aad_len > 16) {
			do {
				b[i] = X0[i] ^ aad[j];
				i++, j++;
			} while (i < 16);

			aad_len -= 16;
			i = 0;

			err = bt_encrypt_be(key, b, X0);
			if (err) {
				return err;
			}
		}

		for (; i < aad_len; i++, j++) {
			b[i] = X0[i] ^ aad[j];
		}

		for (i = aad_len; i < 16; i++) {
			b[i] = X0[i];
		}

		err = bt_encrypt_be(key, b, X0);
		if (err) {
			return err;
		}
	}

	return 0;
}

static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
		    const uint8_t *cleartext_msg, uint16_t msg_len, const uint8_t *aad,
		    size_t aad_len, uint8_t *mic, size_t mic_size)
{
	uint8_t b[16], Xn[16], s0[16];
	uint16_t blk_cnt, last_blk;
	int err, j, i;

	last_blk = msg_len % 16;
	blk_cnt = (msg_len + 15) / 16;
	if (!last_blk) {
		last_blk = 16U;
	}

	b[0] = 0x01;
	memcpy(b + 1, nonce, 13);

	/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
	sys_put_be16(0x0000, &b[14]);

	err = bt_encrypt_be(key, b, s0);
	if (err) {
		return err;
	}

	ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);

	for (j = 0; j < blk_cnt; j++) {
		/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
		if (j + 1 == blk_cnt) {
			for (i = 0; i < last_blk; i++) {
				b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
			}

			memcpy(&b[i], &Xn[i], 16 - i);
		} else {
			xor16(b, Xn, &cleartext_msg[j * 16]);
		}

		err = bt_encrypt_be(key, b, Xn);
		if (err) {
			return err;
		}
	}

	/* MIC = C_mic ^ X_1 */
	for (i = 0; i < mic_size; i++) {
		mic[i] = s0[i] ^ Xn[i];
	}

	return 0;
}

static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
		     const uint8_t *in_msg, uint8_t *out_msg, uint16_t msg_len)
{
	uint8_t a_i[16], s_i[16];
	uint16_t last_blk, blk_cnt;
	size_t i, j;
	int err;

	last_blk = msg_len % 16;
	blk_cnt = (msg_len + 15) / 16;
	if (!last_blk) {
		last_blk = 16U;
	}

	a_i[0] = 0x01;
	memcpy(&a_i[1], nonce, 13);

	for (j = 0; j < blk_cnt; j++) {
		/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
		sys_put_be16(j + 1, &a_i[14]);

		err = bt_encrypt_be(key, a_i, s_i);
		if (err) {
			return err;
		}

		/* Encrypted = Payload[0-15] ^ C_1 */
		if (j < blk_cnt - 1) {
			xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
		} else {
			for (i = 0; i < last_blk; i++) {
				out_msg[(j * 16) + i] =
					in_msg[(j * 16) + i] ^ s_i[i];
			}
		}
	}
	return 0;
}

int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13],
		   const uint8_t *enc_data, size_t len, const uint8_t *aad,
		   size_t aad_len, uint8_t *plaintext, size_t mic_size)
{
	uint8_t mic[16];

	if (aad_len >= 0xff00 || mic_size > sizeof(mic) || len > UINT16_MAX) {
		return -EINVAL;
	}

	ccm_crypt(key, nonce, enc_data, plaintext, len);

	ccm_auth(key, nonce, plaintext, len, aad, aad_len, mic, mic_size);

	if (memcmp(mic, enc_data + len, mic_size)) {
		return -EBADMSG;
	}

	return 0;
}

int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13],
		   const uint8_t *plaintext, size_t len, const uint8_t *aad,
		   size_t aad_len, uint8_t *enc_data, size_t mic_size)
{
	uint8_t *mic = enc_data + len;

	BT_DBG("key %s", bt_hex(key, 16));
	BT_DBG("nonce %s", bt_hex(nonce, 13));
	BT_DBG("msg (len %zu) %s", len, bt_hex(plaintext, len));
	BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);

	/* Unsupported AAD size */
	if (aad_len >= 0xff00 || mic_size > 16 || len > UINT16_MAX) {
		return -EINVAL;
	}

	ccm_auth(key, nonce, plaintext, len, aad, aad_len, mic, mic_size);

	ccm_crypt(key, nonce, plaintext, enc_data, len);

	return 0;
}
