/*
 * Copyright (c) 2016-2017 Nordic Semiconductor ASA
 * Copyright (c) 2016 Vinayak Kariappa Chettimada
 * Copyright 2019-2020 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <string.h>

#include <zephyr/bluetooth/hci.h>

#include <zephyr/sys/dlist.h>
#include <zephyr/sys/byteorder.h>

#include "hal/ecb.h"

#include <zephyr/logging/log.h>

#include "hal/debug.h"
#include "fsl_cau3_ble.h"

LOG_MODULE_REGISTER(bt_ctlr_rv32m1_ecb, LOG_LEVEL_DBG);

void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
		    uint8_t *const cipher_text_be)
{
	uint8_t keyAes[16] __aligned(4);
	status_t status;

	cau3_handle_t handle;

	memcpy(&keyAes, key_be, sizeof(keyAes));

	/* CAU3 driver supports 4 key slots. */
	handle.keySlot = kCAU3_KeySlot1;

	/* After encrypt/decrypt req is sent to CAU3, the Host CPU will
	 * execute WFE() until CAU3 signals task done by setting the event.
	 */
	handle.taskDone = kCAU3_TaskDonePoll;

	/* Loads the key into CAU3's DMEM and expands the AES key schedule */
	status = CAU3_AES_SetKey(CAU3, &handle, keyAes, sizeof(keyAes));
	if (status != kStatus_Success) {
		LOG_ERR("CAUv3 AES key set failed %d", status);
		return;
	}

	status = CAU3_AES_Encrypt(CAU3, &handle, clear_text_be, cipher_text_be);
	if (status != kStatus_Success) {
		LOG_ERR("CAUv3 AES encrypt failed %d", status);
		return;
	}
}

void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
		 uint8_t *const cipher_text_le, uint8_t *const cipher_text_be)
{
	uint8_t keyAes[16] __aligned(4);
	uint8_t clear[16];
	uint8_t cipher[16];
	status_t status;

	cau3_handle_t handle;

	/* The security function e of the cryptographic toolbox in CAU as in STD
	 * The most significant octet of key corresponds to key[0], the most
	 * significant octet of plaintextData corresponds to in[0] and the most
	 * significant octet of encryptedData corresponds to out[0] using the
	 * notation specified in FIPS-197
	 * Thus, reverse the input parameters that are LSB to MSB format (le)
	 */
	sys_memcpy_swap(&keyAes, key_le, sizeof(keyAes));
	sys_memcpy_swap(&clear, clear_text_le, sizeof(clear));

	/* CAU3 driver supports 4 key slots. */
	handle.keySlot = kCAU3_KeySlot1;

	/* After encrypt/decrypt req is sent to CAU3, the Host CPU will
	 * execute WFE() until CAU3 signals task done by setting the event.
	 */
	handle.taskDone = kCAU3_TaskDonePoll;

	/* Loads the key into CAU3's DMEM and expands the AES key schedule */
	status = CAU3_AES_SetKey(CAU3, &handle, keyAes, sizeof(keyAes));
	if (status != kStatus_Success) {
		LOG_ERR("CAUv3 AES key set failed %d", status);
		return;
	}

	status = CAU3_AES_Encrypt(CAU3, &handle, clear, cipher);
	if (status != kStatus_Success) {
		LOG_ERR("CAUv3 AES encrypt failed %d", status);
		return;
	}

	if (cipher_text_le) {
		/* STD e function outputs in MSB thus reverse for the (le) */
		sys_memcpy_swap(cipher_text_le, &cipher[0], sizeof(cipher));
	}

	if (cipher_text_be) {
		memcpy(cipher_text_be, &cipher, sizeof(cipher));
	}
}

uint32_t ecb_encrypt_nonblocking(struct ecb *ecb)
{
	return 0;
}

void isr_ecb(void *param)
{
}

/*
 * Used by ULL as in this example:
 * ltk[16] is copied from the HCI packet, preserving the LSO to MSO format
 * skd[16] is copied from the PDU, preserving the LSO to MSO format
 * calc the Session Key and retrieve the MSO to LSO format because that is how
 * the PDU payload uses the encrypted data; MIC is also MSO to LSO.
	ecb_encrypt(&conn->llcp_enc.ltk[0],
		    &conn->llcp.encryption.skd[0], NULL,
		    &lll->ccm_rx.key[0]);
 */
uint32_t ecb_ut(void)
{
	/*
	 * LTK = 0x4C68384139F574D836BCF34E9DFB01BF (MSO to LSO)
	 * SKD = SKDm || SKDs
	 * SKD (LSO to MSO)
	 * :0x13:0x02:0xF1:0xE0:0xDF:0xCE:0xBD:0xAC
	 * :0x79:0x68:0x57:0x46:0x35:0x24:0x13:0x02
	 * SK = Encrypt(LTK, SKD)
	 * SK (LSO to MSO)
	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
	 */
	static const uint8_t ltk_le[16] = {
		0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
		0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c
	};
	static const uint8_t skd_le[16] = {
		0x13, 0x02, 0xF1, 0xE0, 0xDF, 0xCE, 0xBD, 0xAC,
		0x79, 0x68, 0x57, 0x46, 0x35, 0x24, 0x13, 0x02
	};
	uint8_t key_le[16] = {};
	uint8_t key_ref_le[16] = {
		0x66, 0xC6, 0xC2, 0x27, 0x8E, 0x3B, 0x8E, 0x05,
		0x3E, 0x7E, 0xA3, 0x26, 0x52, 0x1B, 0xAD, 0x99
	};
	uint32_t status = kStatus_Success;
	uint8_t *key;

	/* calc the Session Key and compare vs the ref_le in LSO format */
	ecb_encrypt(ltk_le, skd_le, key = key_le, NULL);

	if (memcmp(key_ref_le, key, 16)) {
		printk("Failed session key unit test\n");
		status = kStatus_Fail;
	}

	printk("Session key: %02x %02x %02x %02x %02x %02x %02x %02x "
			"%02x %02x %02x %02x %02x %02x %02x %02x\n",
			key[0], key[1], key[2], key[3],
			key[4], key[5], key[6], key[7],
			key[8], key[9], key[10], key[11],
			key[12], key[13], key[14], key[15]);

	return status;
}
