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

#include <stdint.h>

#include <zephyr/sys/check.h>
#include <zephyr/bluetooth/hci.h>

#include "ecc.h"
#include "hci_core.h"

#define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_ecc);

static uint8_t pub_key[BT_PUB_KEY_LEN];
static sys_slist_t pub_key_cb_slist;
static bt_dh_key_cb_t dh_key_cb;

static const uint8_t debug_public_key[BT_PUB_KEY_LEN] = {
	/* X */
	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
	0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
	0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
	/* Y */
	0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
	0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
	0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
};

bool bt_pub_key_is_debug(uint8_t *cmp_pub_key)
{
	return memcmp(cmp_pub_key, debug_public_key, BT_PUB_KEY_LEN) == 0;
}

int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
{
	struct bt_pub_key_cb *cb;
	int err;

	/*
	 * We check for both "LE Read Local P-256 Public Key" and
	 * "LE Generate DH Key" support here since both commands are needed for
	 * ECC support. If "LE Generate DH Key" is not supported then there
	 * is no point in reading local public key.
	 */
	if (!BT_CMD_TEST(bt_dev.supported_commands, 34, 1) ||
	    !BT_CMD_TEST(bt_dev.supported_commands, 34, 2)) {
		LOG_WRN("ECC HCI commands not available");
		return -ENOTSUP;
	}

	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS)) {
		if (!BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
			LOG_WRN("ECC Debug keys HCI command not available");
		} else {
			atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
			__ASSERT_NO_MSG(new_cb->func != NULL);
			new_cb->func(debug_public_key);
			return 0;
		}
	}

	if (!new_cb) {
		return -EINVAL;
	}

	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
		if (cb == new_cb) {
			LOG_WRN("Callback already registered");
			return -EALREADY;
		}
	}

	sys_slist_prepend(&pub_key_cb_slist, &new_cb->node);

	if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
		return 0;
	}

	atomic_clear_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);

	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_P256_PUBLIC_KEY, NULL, NULL);
	if (err) {

		LOG_ERR("Sending LE P256 Public Key command failed");
		atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);

		SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
			if (cb->func) {
				cb->func(NULL);
			}
		}

		sys_slist_init(&pub_key_cb_slist);
		return err;
	}

	return 0;
}

void bt_pub_key_hci_disrupted(void)
{
	struct bt_pub_key_cb *cb;

	atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);

	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
		if (cb->func) {
			cb->func(NULL);
		}
	}

	sys_slist_init(&pub_key_cb_slist);
}

const uint8_t *bt_pub_key_get(void)
{
	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) &&
	    BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
		return debug_public_key;
	}

	if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
		return pub_key;
	}

	return NULL;
}

static int hci_generate_dhkey_v1(const uint8_t *remote_pk)
{
	struct bt_hci_cp_le_generate_dhkey *cp;
	struct net_buf *buf;

	buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY, sizeof(*cp));
	if (!buf) {
		return -ENOBUFS;
	}

	cp = net_buf_add(buf, sizeof(*cp));
	memcpy(cp->key, remote_pk, sizeof(cp->key));

	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY, buf, NULL);
}

static int hci_generate_dhkey_v2(const uint8_t *remote_pk, uint8_t key_type)
{
	struct bt_hci_cp_le_generate_dhkey_v2 *cp;
	struct net_buf *buf;

	buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY_V2, sizeof(*cp));
	if (!buf) {
		return -ENOBUFS;
	}

	cp = net_buf_add(buf, sizeof(*cp));
	memcpy(cp->key, remote_pk, sizeof(cp->key));
	cp->key_type = key_type;

	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY_V2, buf, NULL);
}

int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb)
{
	int err;

	if (dh_key_cb == cb) {
		return -EALREADY;
	}

	if (dh_key_cb || atomic_test_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
		return -EBUSY;
	}

	if (!atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
		return -EADDRNOTAVAIL;
	}

	dh_key_cb = cb;

	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) &&
	    BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
		err = hci_generate_dhkey_v2(remote_pk,
					    BT_HCI_LE_KEY_TYPE_DEBUG);
	} else {
		err = hci_generate_dhkey_v1(remote_pk);
	}

	if (err) {
		dh_key_cb = NULL;
		LOG_WRN("Failed to generate DHKey (err %d)", err);
		return err;
	}

	return 0;
}

void bt_hci_evt_le_pkey_complete(struct net_buf *buf)
{
	struct bt_hci_evt_le_p256_public_key_complete *evt = (void *)buf->data;
	struct bt_pub_key_cb *cb;

	LOG_DBG("status: 0x%02x %s", evt->status, bt_hci_err_to_str(evt->status));

	atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);

	if (!evt->status) {
		memcpy(pub_key, evt->key, BT_PUB_KEY_LEN);
		atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
	}

	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
		if (cb->func) {
			cb->func(evt->status ? NULL : pub_key);
		}
	}

	sys_slist_init(&pub_key_cb_slist);
}

void bt_hci_evt_le_dhkey_complete(struct net_buf *buf)
{
	struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data;

	LOG_DBG("status: 0x%02x %s", evt->status, bt_hci_err_to_str(evt->status));

	if (dh_key_cb) {
		bt_dh_key_cb_t cb = dh_key_cb;

		dh_key_cb = NULL;
		cb(evt->status ? NULL : evt->dhkey);
	}
}

#ifdef ZTEST_UNITTEST
uint8_t const *bt_ecc_get_public_key(void)
{
	return pub_key;
}

uint8_t const *bt_ecc_get_internal_debug_public_key(void)
{
	return debug_public_key;
}

sys_slist_t *bt_ecc_get_pub_key_cb_slist(void)
{
	return &pub_key_cb_slist;
}

bt_dh_key_cb_t *bt_ecc_get_dh_key_cb(void)
{
	return &dh_key_cb;
}
#endif /* ZTEST_UNITTEST */
