From a4f0ca8649065101efc628dab8fd6fbe62954b94 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 1 Feb 2021 14:41:32 +0100 Subject: [PATCH] Bluetooth: host: Refactor host ECC handling to own source file Move the host ECC handling under BT_ECC to its own source file. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/CMakeLists.txt | 4 + subsys/bluetooth/host/ecc.c | 202 +++++++++++++++++++++++++++ subsys/bluetooth/host/hci_core.c | 197 +------------------------- subsys/bluetooth/host/hci_core.h | 4 + 4 files changed, 214 insertions(+), 193 deletions(-) create mode 100644 subsys/bluetooth/host/ecc.c diff --git a/subsys/bluetooth/host/CMakeLists.txt b/subsys/bluetooth/host/CMakeLists.txt index 21bc9dd5680..a56ff6b8c53 100644 --- a/subsys/bluetooth/host/CMakeLists.txt +++ b/subsys/bluetooth/host/CMakeLists.txt @@ -39,6 +39,10 @@ if(CONFIG_BT_HCI_HOST) CONFIG_BT_HOST_CRYPTO crypto.c ) + zephyr_library_sources_ifdef( + CONFIG_BT_ECC + ecc.c + ) if(CONFIG_BT_CONN) zephyr_library_sources( diff --git a/subsys/bluetooth/host/ecc.c b/subsys/bluetooth/host/ecc.c new file mode 100644 index 00000000000..bbcc34d880f --- /dev/null +++ b/subsys/bluetooth/host/ecc.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2015 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#include "ecc.h" +#include "hci_core.h" + +#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE) +#define LOG_MODULE_NAME bt_ecc +#include "common/log.h" + +static uint8_t pub_key[64]; +static struct bt_pub_key_cb *pub_key_cb; +static bt_dh_key_cb_t dh_key_cb; + +static const uint8_t debug_public_key[64] = { + /* 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 *pub_key) +{ + return memcmp(pub_key, debug_public_key, 64) == 0; +} + +int bt_pub_key_gen(struct bt_pub_key_cb *new_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)) { + BT_WARN("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)) { + BT_WARN("ECC Debug keys HCI command not available"); + } else { + atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY); + new_cb->func(debug_public_key); + return 0; + } + } + + new_cb->_next = pub_key_cb; + pub_key_cb = new_cb; + + 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) { + BT_ERR("Sending LE P256 Public Key command failed"); + atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY); + pub_key_cb = NULL; + return err; + } + + return 0; +} + +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[64], 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; + BT_WARN("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; + + BT_DBG("status: 0x%02x", evt->status); + + atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY); + + if (!evt->status) { + memcpy(pub_key, evt->key, 64); + atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY); + } + + for (cb = pub_key_cb; cb; cb = cb->_next) { + cb->func(evt->status ? NULL : pub_key); + } + + pub_key_cb = NULL; +} + +void bt_hci_evt_le_dhkey_complete(struct net_buf *buf) +{ + struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data; + + BT_DBG("status: 0x%02x", 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); + } +} diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 69151061357..78c44709b8a 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -111,12 +111,6 @@ static sys_slist_t pa_sync_cbs = SYS_SLIST_STATIC_INIT(&pa_sync_cbs); static bt_hci_vnd_evt_cb_t *hci_vnd_evt_cb; #endif /* CONFIG_BT_HCI_VS_EVT_USER */ -#if defined(CONFIG_BT_ECC) -static uint8_t pub_key[64]; -static struct bt_pub_key_cb *pub_key_cb; -static bt_dh_key_cb_t dh_key_cb; -#endif /* CONFIG_BT_ECC */ - #if defined(CONFIG_BT_BREDR) static bt_br_discovery_cb_t *discovery_cb; struct bt_br_discovery_result *discovery_results; @@ -3841,43 +3835,6 @@ static void le_ltk_request(struct net_buf *buf) } #endif /* CONFIG_BT_SMP */ -#if defined(CONFIG_BT_ECC) -static void 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; - - BT_DBG("status: 0x%02x", evt->status); - - atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY); - - if (!evt->status) { - memcpy(pub_key, evt->key, 64); - atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY); - } - - for (cb = pub_key_cb; cb; cb = cb->_next) { - cb->func(evt->status ? NULL : pub_key); - } - - pub_key_cb = NULL; -} - -static void le_dhkey_complete(struct net_buf *buf) -{ - struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data; - - BT_DBG("status: 0x%02x", 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); - } -} -#endif /* CONFIG_BT_ECC */ - static void hci_reset_complete(struct net_buf *buf) { uint8_t status = buf->data[0]; @@ -4994,9 +4951,11 @@ static const struct event_handler meta_events[] = { sizeof(struct bt_hci_evt_le_ltk_request)), #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_ECC) - EVENT_HANDLER(BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE, le_pkey_complete, + EVENT_HANDLER(BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE, + bt_hci_evt_le_pkey_complete, sizeof(struct bt_hci_evt_le_p256_public_key_complete)), - EVENT_HANDLER(BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE, le_dhkey_complete, + EVENT_HANDLER(BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE, + bt_hci_evt_le_dhkey_complete, sizeof(struct bt_hci_evt_le_generate_dhkey_complete)), #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_EXT_ADV) @@ -9311,154 +9270,6 @@ int bt_br_set_discoverable(bool enable) } #endif /* CONFIG_BT_BREDR */ -#if defined(CONFIG_BT_ECC) -static const uint8_t debug_public_key[64] = { - /* 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 *pub_key) -{ - return memcmp(pub_key, debug_public_key, 64) == 0; -} - -int bt_pub_key_gen(struct bt_pub_key_cb *new_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)) { - BT_WARN("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)) { - BT_WARN("ECC Debug keys HCI command not available"); - } else { - atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY); - new_cb->func(debug_public_key); - return 0; - } - } - - new_cb->_next = pub_key_cb; - pub_key_cb = new_cb; - - 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) { - BT_ERR("Sending LE P256 Public Key command failed"); - atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY); - pub_key_cb = NULL; - return err; - } - - return 0; -} - -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[64], 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; - BT_WARN("Failed to generate DHKey (err %d)", err); - return err; - } - - return 0; -} -#endif /* CONFIG_BT_ECC */ - #if defined(CONFIG_BT_BREDR) int bt_br_oob_get_local(struct bt_br_oob *oob) { diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index a7c581395cd..29fc0246874 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -387,3 +387,7 @@ void hci_evt_user_confirm_req(struct net_buf *buf); void hci_evt_user_passkey_notify(struct net_buf *buf); void hci_evt_user_passkey_req(struct net_buf *buf); void hci_evt_auth_complete(struct net_buf *buf); + +/* ECC HCI event handlers */ +void bt_hci_evt_le_pkey_complete(struct net_buf *buf); +void bt_hci_evt_le_dhkey_complete(struct net_buf *buf);