From 54fe1cd1b3df832fd42372ed78d285d8faf61ce0 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 8 Mar 2021 14:24:34 +0100 Subject: [PATCH] Bluetooth: host: Refactor out identity handling from hci_core to id Refactor out the identity handling from hci_core to its own source file in id.c Identity consistes of managing the identities of the device, the privacy feature which hides the identities. And handling of the identity resolving list in the controller, needed to support privacy-enabled remote devices. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/CMakeLists.txt | 1 + subsys/bluetooth/host/conn.c | 7 +- subsys/bluetooth/host/hci_core.c | 1842 +------------------------- subsys/bluetooth/host/hci_core.h | 16 +- subsys/bluetooth/host/id.c | 1748 ++++++++++++++++++++++++ subsys/bluetooth/host/id.h | 45 + 6 files changed, 1872 insertions(+), 1787 deletions(-) create mode 100644 subsys/bluetooth/host/id.c create mode 100644 subsys/bluetooth/host/id.h diff --git a/subsys/bluetooth/host/CMakeLists.txt b/subsys/bluetooth/host/CMakeLists.txt index 404011e7c69..047129e913e 100644 --- a/subsys/bluetooth/host/CMakeLists.txt +++ b/subsys/bluetooth/host/CMakeLists.txt @@ -34,6 +34,7 @@ if(CONFIG_BT_HCI_HOST) buf.c hci_core.c hci_common.c + id.c ) zephyr_library_sources_ifdef( CONFIG_BT_HOST_CRYPTO diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 12ce2e2ef7d..2117e2025cd 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -28,6 +28,7 @@ #include "common/log.h" #include "hci_core.h" +#include "id.h" #include "conn_internal.h" #include "l2cap_internal.h" #include "keys.h" @@ -2258,7 +2259,7 @@ int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param, return -EINVAL; } - if (!bt_le_scan_random_addr_check()) { + if (!bt_id_scan_random_addr_check()) { return -EINVAL; } @@ -2350,7 +2351,7 @@ int bt_conn_le_create(const bt_addr_le_t *peer, return -EALREADY; } - if (!bt_le_scan_random_addr_check()) { + if (!bt_id_scan_random_addr_check()) { return -EINVAL; } @@ -2422,7 +2423,7 @@ int bt_le_set_auto_conn(const bt_addr_le_t *addr, return -EINVAL; } - if (!bt_le_scan_random_addr_check()) { + if (!bt_id_scan_random_addr_check()) { return -EINVAL; } diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 7a6d5438a83..35c30afd3ef 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -38,6 +38,7 @@ #include "hci_core.h" #include "hci_ecc.h" #include "ecc.h" +#include "id.h" #include "conn_internal.h" #include "iso_internal.h" @@ -56,9 +57,6 @@ #define BT_FEAT_LE_EXT_ADV(feat) 1 #endif -#define RPA_TIMEOUT_MS (CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC) -#define RPA_TIMEOUT K_MSEC(RPA_TIMEOUT_MS) - #define HCI_CMD_TIMEOUT K_SECONDS(10) /* Stacks for the threads */ @@ -93,7 +91,6 @@ static bt_ready_cb_t ready_cb; static bt_le_scan_cb_t *scan_dev_found_cb; #if defined(CONFIG_BT_OBSERVER) -static int set_le_scan_enable(uint8_t enable); static sys_slist_t scan_cbs = SYS_SLIST_STATIC_INIT(&scan_cbs); #endif /* defined(CONFIG_BT_OBSERVER) */ @@ -354,25 +351,6 @@ int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf, return 0; } -#if defined(CONFIG_BT_OBSERVER) || defined(CONFIG_BT_BROADCASTER) -const bt_addr_le_t *bt_lookup_id_addr(uint8_t id, const bt_addr_le_t *addr) -{ - if (IS_ENABLED(CONFIG_BT_SMP)) { - struct bt_keys *keys; - - keys = bt_keys_find_irk(id, addr); - if (keys) { - BT_DBG("Identity %s matched RPA %s", - bt_addr_le_str(&keys->addr), - bt_addr_le_str(addr)); - return &keys->addr; - } - } - - return addr; -} -#endif /* CONFIG_BT_OBSERVER || CONFIG_BT_CONN */ - #if defined(CONFIG_BT_EXT_ADV) uint8_t bt_le_ext_adv_get_index(struct bt_le_ext_adv *adv) { @@ -424,7 +402,7 @@ static struct bt_le_ext_adv *bt_adv_lookup_handle(uint8_t handle) #endif /* CONFIG_BT_BROADCASTER */ #endif /* defined(CONFIG_BT_EXT_ADV) */ -static void bt_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), +void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), void *data) { #if defined(CONFIG_BT_EXT_ADV) @@ -462,7 +440,7 @@ static void adv_delete_legacy(void) #endif } -struct bt_le_ext_adv *bt_adv_lookup_legacy(void) +struct bt_le_ext_adv *bt_le_adv_lookup_legacy(void) { #if defined(CONFIG_BT_EXT_ADV) return bt_dev.adv; @@ -471,7 +449,7 @@ struct bt_le_ext_adv *bt_adv_lookup_legacy(void) #endif } -static int set_le_adv_enable_legacy(struct bt_le_ext_adv *adv, bool enable) +int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable) { struct net_buf *buf; struct bt_hci_cmd_state_set state; @@ -498,38 +476,9 @@ static int set_le_adv_enable_legacy(struct bt_le_ext_adv *adv, bool enable) return 0; } -static int set_random_address(const bt_addr_t *addr) -{ - struct net_buf *buf; - int err; - - BT_DBG("%s", bt_addr_str(addr)); - - /* Do nothing if we already have the right address */ - if (!bt_addr_cmp(addr, &bt_dev.random_addr.a)) { - return 0; - } - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(*addr)); - if (!buf) { - return -ENOBUFS; - } - - net_buf_add_mem(buf, addr, sizeof(*addr)); - - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf, NULL); - if (err) { - return err; - } - - bt_addr_copy(&bt_dev.random_addr.a, addr); - bt_dev.random_addr.type = BT_ADDR_LE_RANDOM; - return 0; -} - -static int set_le_adv_enable_ext(struct bt_le_ext_adv *adv, - bool enable, - const struct bt_le_ext_adv_start_param *param) +int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv, + bool enable, + const struct bt_le_ext_adv_start_param *param) { struct net_buf *buf; struct bt_hci_cmd_state_set state; @@ -562,338 +511,19 @@ static int set_le_adv_enable_ext(struct bt_le_ext_adv *adv, return 0; } -static int set_le_adv_enable(struct bt_le_ext_adv *adv, bool enable) +int bt_le_adv_set_enable(struct bt_le_ext_adv *adv, bool enable) { if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - return set_le_adv_enable_ext(adv, enable, NULL); + return bt_le_adv_set_enable_ext(adv, enable, NULL); } - return set_le_adv_enable_legacy(adv, enable); -} - -static int set_adv_random_address(struct bt_le_ext_adv *adv, - const bt_addr_t *addr) -{ - struct bt_hci_cp_le_set_adv_set_random_addr *cp; - struct net_buf *buf; - int err; - - if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - return set_random_address(addr); - } - - BT_DBG("%s", bt_addr_str(addr)); - - if (!atomic_test_bit(adv->flags, BT_ADV_PARAMS_SET)) { - bt_addr_copy(&adv->random_addr.a, addr); - adv->random_addr.type = BT_ADDR_LE_RANDOM; - atomic_set_bit(adv->flags, BT_ADV_RANDOM_ADDR_PENDING); - return 0; - } - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, - sizeof(*cp)); - if (!buf) { - return -ENOBUFS; - } - - cp = net_buf_add(buf, sizeof(*cp)); - - cp->handle = adv->handle; - bt_addr_copy(&cp->bdaddr, addr); - - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, buf, - NULL); - if (err) { - return err; - } - - bt_addr_copy(&adv->random_addr.a, addr); - adv->random_addr.type = BT_ADDR_LE_RANDOM; - return 0; -} -static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data) -{ - if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { - atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); - } -} - -static void le_rpa_invalidate(void) -{ - /* RPA must be submitted */ - atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_SET); - - /* Invalidate RPA */ - if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && - atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED))) { - atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); - } - - bt_adv_foreach(adv_rpa_invalidate, NULL); -} - -#if defined(CONFIG_BT_PRIVACY) -static void le_rpa_timeout_submit(void) -{ - /* Check if RPA timer is running. */ - if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_SET)) { - return; - } - - k_delayed_work_submit(&bt_dev.rpa_update, RPA_TIMEOUT); -} - -/* this function sets new RPA only if current one is no longer valid */ -static int le_set_private_addr(uint8_t id) -{ - bt_addr_t rpa; - int err; - - /* check if RPA is valid */ - if (atomic_test_bit(bt_dev.flags, BT_DEV_RPA_VALID)) { - return 0; - } - - err = bt_rpa_create(bt_dev.irk[id], &rpa); - if (!err) { - err = set_random_address(&rpa); - if (!err) { - atomic_set_bit(bt_dev.flags, BT_DEV_RPA_VALID); - } - } - - le_rpa_timeout_submit(); - - if (err) { - return err; - } - - if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { - BT_INFO("RPA: %s", bt_addr_str(&rpa)); - } - - return 0; -} - -static int le_adv_set_private_addr(struct bt_le_ext_adv *adv) -{ - bt_addr_t rpa; - int err; - - if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - return le_set_private_addr(adv->id); - } - - /* check if RPA is valid */ - if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID)) { - return 0; - } - - if (adv == bt_adv_lookup_legacy() && adv->id == BT_ID_DEFAULT) { - /* Make sure that a Legacy advertiser using default ID has same - * RPA address as scanner roles. - */ - err = le_set_private_addr(BT_ID_DEFAULT); - if (err) { - return err; - } - - err = set_adv_random_address(adv, &bt_dev.random_addr.a); - if (!err) { - atomic_set_bit(adv->flags, BT_ADV_RPA_VALID); - } - - return 0; - } - - err = bt_rpa_create(bt_dev.irk[adv->id], &rpa); - if (!err) { - err = set_adv_random_address(adv, &rpa); - if (!err) { - atomic_set_bit(adv->flags, BT_ADV_RPA_VALID); - } - } - - if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { - le_rpa_timeout_submit(); - } - - if (err) { - return err; - } - - if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { - BT_INFO("RPA: %s", bt_addr_str(&rpa)); - } - - return 0; -} -#else -static int le_set_private_addr(uint8_t id) -{ - bt_addr_t nrpa; - int err; - - err = bt_rand(nrpa.val, sizeof(nrpa.val)); - if (err) { - return err; - } - - BT_ADDR_SET_NRPA(&nrpa); - - err = set_random_address(&nrpa); - if (err) { - return err; - } - - if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { - BT_INFO("NRPA: %s", bt_addr_str(&nrpa)); - } - - return 0; -} - -static int le_adv_set_private_addr(struct bt_le_ext_adv *adv) -{ - bt_addr_t nrpa; - int err; - - err = bt_rand(nrpa.val, sizeof(nrpa.val)); - if (err) { - return err; - } - - BT_ADDR_SET_NRPA(&nrpa); - - err = set_adv_random_address(adv, &nrpa); - if (err) { - return err; - } - - if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { - BT_INFO("NRPA: %s", bt_addr_str(&nrpa)); - } - - return 0; -} -#endif /* defined(CONFIG_BT_PRIVACY) */ - -static void adv_update_rpa(struct bt_le_ext_adv *adv, void *data) -{ - if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && - !atomic_test_bit(adv->flags, BT_ADV_LIMITED) && - !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - int err; - - set_le_adv_enable_ext(adv, false, NULL); - - err = le_adv_set_private_addr(adv); - if (err) { - BT_WARN("Failed to update advertiser RPA address (%d)", - err); - } - - set_le_adv_enable_ext(adv, true, NULL); - } -} - -static void le_update_private_addr(void) -{ - struct bt_le_ext_adv *adv = NULL; - bool adv_enabled = false; - uint8_t id = BT_ID_DEFAULT; - int err; - - if (IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - bt_adv_foreach(adv_update_rpa, NULL); - } - -#if defined(CONFIG_BT_OBSERVER) - bool scan_enabled = false; - - if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && - atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN) && - !(IS_ENABLED(CONFIG_BT_EXT_ADV) && - atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED))) { - set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); - scan_enabled = true; - } -#endif - if (IS_ENABLED(CONFIG_BT_CENTRAL) && - IS_ENABLED(CONFIG_BT_WHITELIST) && - atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { - /* Canceled initiating procedure will be restarted by - * connection complete event. - */ - bt_le_create_conn_cancel(); - } - - if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - adv = bt_adv_lookup_legacy(); - - if (adv && - atomic_test_bit(adv->flags, BT_ADV_ENABLED) && - !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - adv_enabled = true; - id = adv->id; - set_le_adv_enable_legacy(adv, false); - } - } - - /* If both advertiser and scanner is running then the advertiser - * ID must be BT_ID_DEFAULT, this will update the RPA address - * for both roles. - */ - err = le_set_private_addr(id); - if (err) { - BT_WARN("Failed to update RPA address (%d)", err); - return; - } - - if (adv && adv_enabled) { - set_le_adv_enable_legacy(adv, true); - } - -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { - set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); - } -#endif -} - -struct adv_id_check_data { - uint8_t id; - bool adv_enabled; -}; - -static void adv_id_check_func(struct bt_le_ext_adv *adv, void *data) -{ - struct adv_id_check_data *check_data = data; - - if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { - /* Only check if the ID is in use, as the advertiser can be - * started and stopped without reconfiguring parameters. - */ - if (check_data->id == adv->id) { - check_data->adv_enabled = true; - } - } else { - if (check_data->id == adv->id && - atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { - check_data->adv_enabled = true; - } - } + return bt_le_adv_set_enable_legacy(adv, enable); } static void adv_id_check_connectable_func(struct bt_le_ext_adv *adv, void *data) { - struct adv_id_check_data *check_data = data; + struct bt_adv_id_check_data *check_data = data; if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE) && @@ -902,188 +532,6 @@ static void adv_id_check_connectable_func(struct bt_le_ext_adv *adv, void *data) } } -#if defined(CONFIG_BT_SMP) -static void adv_is_limited_enabled(struct bt_le_ext_adv *adv, void *data) -{ - bool *adv_enabled = data; - - if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && - atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { - *adv_enabled = true; - } -} - -static void adv_pause_enabled(struct bt_le_ext_adv *adv, void *data) -{ - if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { - atomic_set_bit(adv->flags, BT_ADV_PAUSED); - set_le_adv_enable(adv, false); - } -} - -static void adv_unpause_enabled(struct bt_le_ext_adv *adv, void *data) -{ - if (atomic_test_and_clear_bit(adv->flags, BT_ADV_PAUSED)) { - set_le_adv_enable(adv, true); - } -} -#endif /* defined(CONFIG_BT_SMP) */ - -#if defined(CONFIG_BT_PRIVACY) -static void adv_is_private_enabled(struct bt_le_ext_adv *adv, void *data) -{ - bool *adv_enabled = data; - - if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && - !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - *adv_enabled = true; - } -} - -static void rpa_timeout(struct k_work *work) -{ - bool adv_enabled = false; - - BT_DBG(""); - - if (IS_ENABLED(CONFIG_BT_CENTRAL)) { - struct bt_conn *conn = - bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, - BT_CONN_CONNECT_SCAN); - - if (conn) { - bt_conn_unref(conn); - bt_le_create_conn_cancel(); - } - } - - le_rpa_invalidate(); - - bt_adv_foreach(adv_is_private_enabled, &adv_enabled); - - /* IF no roles using the RPA is running we can stop the RPA timer */ - if (!(adv_enabled || - atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || - (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && - atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) { - return; - } - - le_update_private_addr(); -} -#endif /* CONFIG_BT_PRIVACY */ - -bool bt_le_scan_random_addr_check(void) -{ - struct bt_le_ext_adv *adv; - - if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || - (IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - /* Advertiser is not enabled or advertiser and scanner are using - * a different random address. - */ - return true; - } - - adv = bt_adv_lookup_legacy(); - if (!adv) { - return true; - } - - /* If the advertiser is not active there is no issue */ - if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { - return true; - } - - /* When privacy is enabled the random address will not be set - * immediately before starting the role, because the RPA might still be - * valid and only updated on RPA timeout. - */ - if (IS_ENABLED(CONFIG_BT_PRIVACY)) { - /* Cannot start scannor or initiator if the random address is - * used by the advertiser for an RPA with a different identity - * or for a random static identity address. - */ - if ((atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && - bt_dev.id_addr[adv->id].type == BT_ADDR_LE_RANDOM) || - adv->id != BT_ID_DEFAULT) { - return false; - } - } - - /* If privacy is not enabled then the random address will be attempted - * to be set before enabling the role. If another role is already using - * the random address then this command will fail, and should return - * the error code to the application. - */ - return true; -} - -static bool bt_le_adv_random_addr_check(const struct bt_le_adv_param *param) -{ - if (!IS_ENABLED(CONFIG_BT_OBSERVER) || - (IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - /* Scanner is not enabled or advertiser and scanner are using a - * different random address. - */ - return true; - } - - /* If scanner roles are not active there is no issue. */ - if (!(atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || - atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING))) { - return true; - } - - /* When privacy is enabled the random address will not be set - * immediately before starting the role, because the RPA might still be - * valid and only updated on RPA timeout. - */ - if (IS_ENABLED(CONFIG_BT_PRIVACY)) { - /* Cannot start an advertiser with random static identity or - * using an RPA generated for a different identity than scanner - * roles. - */ - if (((param->options & BT_LE_ADV_OPT_USE_IDENTITY) && - bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM) || - param->id != BT_ID_DEFAULT) { - return false; - } - } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && - bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_RANDOM) { - /* Scanning with random static identity. Stop the advertiser - * from overwriting the passive scanner identity address. - * In this case the LE Set Random Address command does not - * protect us in the case of a passive scanner. - * Explicitly stop it here. - */ - - if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE) && - (param->options & BT_LE_ADV_OPT_USE_IDENTITY)) { - /* Attempt to set non-connectable NRPA */ - return false; - } else if (bt_dev.id_addr[param->id].type == - BT_ADDR_LE_RANDOM && - param->id != BT_ID_DEFAULT) { - /* Attempt to set connectable, or non-connectable with - * identity different than scanner. - */ - return false; - } - } - - /* If privacy is not enabled then the random address will be attempted - * to be set before enabling the role. If another role is already using - * the random address then this command will fail, and should return - * the error code to the application. - */ - return true; -} - - #if defined(CONFIG_BT_OBSERVER) static int set_le_ext_scan_enable(uint8_t enable, uint16_t duration) { @@ -1121,7 +569,7 @@ static int set_le_ext_scan_enable(uint8_t enable, uint16_t duration) return 0; } -static int set_le_scan_enable_legacy(uint8_t enable) +static int bt_le_scan_set_enable_legacy(uint8_t enable) { struct bt_hci_cp_le_set_scan_enable *cp; struct bt_hci_cmd_state_set state; @@ -1155,30 +603,17 @@ static int set_le_scan_enable_legacy(uint8_t enable) return 0; } -static int set_le_scan_enable(uint8_t enable) +int bt_le_scan_set_enable(uint8_t enable) { if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { return set_le_ext_scan_enable(enable, 0); } - return set_le_scan_enable_legacy(enable); + return bt_le_scan_set_enable_legacy(enable); } #endif /* CONFIG_BT_OBSERVER */ -static inline bool rpa_is_new(void) -{ -#if defined(CONFIG_BT_PRIVACY) - /* RPA is considered new if there is less than half a second since the - * timeout was started. - */ - return k_delayed_work_remaining_get(&bt_dev.rpa_update) > - (RPA_TIMEOUT_MS - 500); -#else - return false; -#endif -} - static int hci_le_read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) { struct bt_hci_rp_le_read_max_data_len *rp; @@ -1324,61 +759,7 @@ static void hci_num_completed_packets(struct net_buf *buf) } } -static inline bool rpa_timeout_valid_check(void) -{ -#if defined(CONFIG_BT_PRIVACY) - /* Check if create conn timeout will happen before RPA timeout. */ - return k_delayed_work_remaining_get(&bt_dev.rpa_update) > - (10 * bt_dev.create_param.timeout); -#else - return true; -#endif -} - #if defined(CONFIG_BT_CENTRAL) -static int le_create_conn_set_random_addr(bool use_filter, uint8_t *own_addr_type) -{ - int err; - - if (IS_ENABLED(CONFIG_BT_PRIVACY)) { - if (use_filter || rpa_timeout_valid_check()) { - err = le_set_private_addr(BT_ID_DEFAULT); - if (err) { - return err; - } - } else { - /* Force new RPA timeout so that RPA timeout is not - * triggered while direct initiator is active. - */ - le_rpa_invalidate(); - le_update_private_addr(); - } - - if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { - *own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; - } else { - *own_addr_type = BT_ADDR_LE_RANDOM; - } - } else { - const bt_addr_le_t *addr = &bt_dev.id_addr[BT_ID_DEFAULT]; - - /* If Static Random address is used as Identity address we - * need to restore it before creating connection. Otherwise - * NRPA used for active scan could be used for connection. - */ - if (addr->type == BT_ADDR_LE_RANDOM) { - err = set_random_address(&addr->a); - if (err) { - return err; - } - } - - *own_addr_type = addr->type; - } - - return 0; -} - static void set_phy_conn_param(const struct bt_conn *conn, struct bt_hci_ext_conn_phy *phy) { @@ -1406,7 +787,7 @@ int bt_le_create_conn_ext(const struct bt_conn *conn) use_filter = atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT); } - err = le_create_conn_set_random_addr(use_filter, &own_addr_type); + err = bt_id_set_create_conn_own_addr(use_filter, &own_addr_type); if (err) { return err; } @@ -1485,7 +866,7 @@ int bt_le_create_conn_legacy(const struct bt_conn *conn) use_filter = atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT); } - err = le_create_conn_set_random_addr(use_filter, &own_addr_type); + err = bt_id_set_create_conn_own_addr(use_filter, &own_addr_type); if (err) { return err; } @@ -1765,41 +1146,6 @@ int bt_le_set_phy(struct bt_conn *conn, uint8_t all_phys, return bt_hci_cmd_send(BT_HCI_OP_LE_SET_PHY, buf); } -#if defined(CONFIG_BT_SMP) -static void pending_id_update(struct bt_keys *keys, void *data) -{ - if (keys->state & BT_KEYS_ID_PENDING_ADD) { - keys->state &= ~BT_KEYS_ID_PENDING_ADD; - bt_id_add(keys); - return; - } - - if (keys->state & BT_KEYS_ID_PENDING_DEL) { - keys->state &= ~BT_KEYS_ID_PENDING_DEL; - bt_id_del(keys); - return; - } -} - -static void pending_id_keys_update_set(struct bt_keys *keys, uint8_t flag) -{ - atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING); - keys->state |= flag; -} - -static void pending_id_keys_update(void) -{ - if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ID_PENDING)) { - if (IS_ENABLED(CONFIG_BT_CENTRAL) && - IS_ENABLED(CONFIG_BT_PRIVACY)) { - bt_keys_foreach(BT_KEYS_ALL, pending_id_update, NULL); - } else { - bt_keys_foreach(BT_KEYS_IRK, pending_id_update, NULL); - } - } -} -#endif /* defined(CONFIG_BT_SMP) */ - static struct bt_conn *find_pending_connect(uint8_t role, bt_addr_le_t *peer_addr) { struct bt_conn *conn; @@ -1945,7 +1291,7 @@ static void le_conn_complete_adv_timeout(void) { if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); struct bt_conn *conn; /* Handle advertising timeout after high duty cycle directed @@ -1990,7 +1336,7 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) BT_DBG("local RPA %s", bt_addr_str(&evt->local_rpa)); #if defined(CONFIG_BT_SMP) - pending_id_keys_update(); + bt_id_pending_keys_update(); #endif if (evt->status) { @@ -2035,7 +1381,7 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) evt->role == BT_HCI_ROLE_SLAVE && !(IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); /* Clear advertising even if we are not able to add connection * object to keep host in sync with controller state. */ @@ -2087,7 +1433,7 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); if (IS_ENABLED(CONFIG_BT_PRIVACY) && !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { @@ -2122,7 +1468,7 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) if (IS_ENABLED(CONFIG_BT_EXT_ADV) && !BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); /* No advertising set terminated event, must be a * legacy advertiser set. */ @@ -2473,7 +1819,7 @@ static void check_pending_conn(const bt_addr_le_t *id_addr, } if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && - set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE)) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE)) { goto failed; } @@ -3309,309 +2655,6 @@ static void role_change(struct net_buf *buf) #endif /* CONFIG_BT_BREDR */ #if defined(CONFIG_BT_SMP) -static int le_set_privacy_mode(const bt_addr_le_t *addr, uint8_t mode) -{ - struct bt_hci_cp_le_set_privacy_mode cp; - struct net_buf *buf; - int err; - - /* Check if set privacy mode command is supported */ - if (!BT_CMD_TEST(bt_dev.supported_commands, 39, 2)) { - BT_WARN("Set privacy mode command is not supported"); - return 0; - } - - BT_DBG("addr %s mode 0x%02x", bt_addr_le_str(addr), mode); - - bt_addr_le_copy(&cp.id_addr, addr); - cp.mode = mode; - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PRIVACY_MODE, sizeof(cp)); - if (!buf) { - return -ENOBUFS; - } - - net_buf_add_mem(buf, &cp, sizeof(cp)); - - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PRIVACY_MODE, buf, NULL); - if (err) { - return err; - } - - return 0; -} - -static int addr_res_enable(uint8_t enable) -{ - struct net_buf *buf; - - BT_DBG("%s", enable ? "enabled" : "disabled"); - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, 1); - if (!buf) { - return -ENOBUFS; - } - - net_buf_add_u8(buf, enable); - - return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, - buf, NULL); -} - -static int hci_id_add(uint8_t id, const bt_addr_le_t *addr, uint8_t peer_irk[16]) -{ - struct bt_hci_cp_le_add_dev_to_rl *cp; - struct net_buf *buf; - - BT_DBG("addr %s", bt_addr_le_str(addr)); - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_RL, sizeof(*cp)); - if (!buf) { - return -ENOBUFS; - } - - cp = net_buf_add(buf, sizeof(*cp)); - bt_addr_le_copy(&cp->peer_id_addr, addr); - memcpy(cp->peer_irk, peer_irk, 16); - -#if defined(CONFIG_BT_PRIVACY) - memcpy(cp->local_irk, bt_dev.irk[id], 16); -#else - (void)memset(cp->local_irk, 0, 16); -#endif - - return bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_RL, buf, NULL); -} - -void bt_id_add(struct bt_keys *keys) -{ - struct bt_conn *conn; - int err; - - BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); - - /* Nothing to be done if host-side resolving is used */ - if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { - bt_dev.le.rl_entries++; - keys->state |= BT_KEYS_ID_ADDED; - return; - } - - conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); - if (conn) { - pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); - bt_conn_unref(conn); - return; - } - - if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { - bool adv_enabled = false; - - bt_adv_foreach(adv_is_limited_enabled, &adv_enabled); - if (adv_enabled) { - pending_id_keys_update_set(keys, - BT_KEYS_ID_PENDING_ADD); - return; - } - } - -#if defined(CONFIG_BT_OBSERVER) - bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); - - if (IS_ENABLED(CONFIG_BT_EXT_ADV) && scan_enabled && - atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) { - pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); - } -#endif - - bt_adv_foreach(adv_pause_enabled, NULL); - -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { - set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); - } -#endif /* CONFIG_BT_OBSERVER */ - - /* If there are any existing entries address resolution will be on */ - if (bt_dev.le.rl_entries) { - err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE); - if (err) { - BT_WARN("Failed to disable address resolution"); - goto done; - } - } - - if (bt_dev.le.rl_entries == bt_dev.le.rl_size) { - BT_WARN("Resolving list size exceeded. Switching to host."); - - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_RL, NULL, NULL); - if (err) { - BT_ERR("Failed to clear resolution list"); - goto done; - } - - bt_dev.le.rl_entries++; - keys->state |= BT_KEYS_ID_ADDED; - - goto done; - } - - err = hci_id_add(keys->id, &keys->addr, keys->irk.val); - if (err) { - BT_ERR("Failed to add IRK to controller"); - goto done; - } - - bt_dev.le.rl_entries++; - keys->state |= BT_KEYS_ID_ADDED; - - /* - * According to Core Spec. 5.0 Vol 1, Part A 5.4.5 Privacy Feature - * - * By default, network privacy mode is used when private addresses are - * resolved and generated by the Controller, so advertising packets from - * peer devices that contain private addresses will only be accepted. - * By changing to the device privacy mode device is only concerned about - * its privacy and will accept advertising packets from peer devices - * that contain their identity address as well as ones that contain - * a private address, even if the peer device has distributed its IRK in - * the past. - */ - err = le_set_privacy_mode(&keys->addr, BT_HCI_LE_PRIVACY_MODE_DEVICE); - if (err) { - BT_ERR("Failed to set privacy mode"); - goto done; - } - -done: - addr_res_enable(BT_HCI_ADDR_RES_ENABLE); - -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { - set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); - } -#endif /* CONFIG_BT_OBSERVER */ - - bt_adv_foreach(adv_unpause_enabled, NULL); -} - -static void keys_add_id(struct bt_keys *keys, void *data) -{ - if (keys->state & BT_KEYS_ID_ADDED) { - hci_id_add(keys->id, &keys->addr, keys->irk.val); - } -} - -static int hci_id_del(const bt_addr_le_t *addr) -{ - struct bt_hci_cp_le_rem_dev_from_rl *cp; - struct net_buf *buf; - - BT_DBG("addr %s", bt_addr_le_str(addr)); - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_RL, sizeof(*cp)); - if (!buf) { - return -ENOBUFS; - } - - cp = net_buf_add(buf, sizeof(*cp)); - bt_addr_le_copy(&cp->peer_id_addr, addr); - - return bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_RL, buf, NULL); -} - -void bt_id_del(struct bt_keys *keys) -{ - struct bt_conn *conn; - int err; - - BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); - - if (!bt_dev.le.rl_size || - bt_dev.le.rl_entries > bt_dev.le.rl_size + 1) { - bt_dev.le.rl_entries--; - keys->state &= ~BT_KEYS_ID_ADDED; - return; - } - - conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); - if (conn) { - pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL); - bt_conn_unref(conn); - return; - } - - if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { - bool adv_enabled = false; - - bt_adv_foreach(adv_is_limited_enabled, &adv_enabled); - if (adv_enabled) { - pending_id_keys_update_set(keys, - BT_KEYS_ID_PENDING_ADD); - return; - } - } - -#if defined(CONFIG_BT_OBSERVER) - bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); - - if (IS_ENABLED(CONFIG_BT_EXT_ADV) && scan_enabled && - atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) { - pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL); - } -#endif /* CONFIG_BT_OBSERVER */ - - bt_adv_foreach(adv_pause_enabled, NULL); - -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { - set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); - } -#endif /* CONFIG_BT_OBSERVER */ - - err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE); - if (err) { - BT_ERR("Disabling address resolution failed (err %d)", err); - goto done; - } - - /* We checked size + 1 earlier, so here we know we can fit again */ - if (bt_dev.le.rl_entries > bt_dev.le.rl_size) { - bt_dev.le.rl_entries--; - keys->state &= ~BT_KEYS_ID_ADDED; - if (IS_ENABLED(CONFIG_BT_CENTRAL) && - IS_ENABLED(CONFIG_BT_PRIVACY)) { - bt_keys_foreach(BT_KEYS_ALL, keys_add_id, NULL); - } else { - bt_keys_foreach(BT_KEYS_IRK, keys_add_id, NULL); - } - goto done; - } - - err = hci_id_del(&keys->addr); - if (err) { - BT_ERR("Failed to remove IRK from controller"); - goto done; - } - - bt_dev.le.rl_entries--; - keys->state &= ~BT_KEYS_ID_ADDED; - -done: - /* Only re-enable if there are entries to do resolving with */ - if (bt_dev.le.rl_entries) { - addr_res_enable(BT_HCI_ADDR_RES_ENABLE); - } - -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { - set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); - } -#endif /* CONFIG_BT_OBSERVER */ - - bt_adv_foreach(adv_unpause_enabled, NULL); -} - static bool update_sec_level(struct bt_conn *conn) { if (conn->le.keys && (conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) { @@ -3969,78 +3012,6 @@ static void hci_cmd_status(struct net_buf *buf) } #if defined(CONFIG_BT_OBSERVER) -static bool is_adv_using_rand_addr(void) -{ - struct bt_le_ext_adv *adv; - - if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || - (IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - /* When advertising is not enabled or is using extended - * advertising HCI commands then only the scanner uses the set - * random address command. - */ - return false; - } - - adv = bt_adv_lookup_legacy(); - - return adv && atomic_test_bit(adv->flags, BT_ADV_ENABLED); -} - -static int le_scan_set_random_addr(bool active_scan, uint8_t *own_addr_type) -{ - int err; - - if (IS_ENABLED(CONFIG_BT_PRIVACY)) { - err = le_set_private_addr(BT_ID_DEFAULT); - if (err) { - return err; - } - - if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { - *own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; - } else { - *own_addr_type = BT_ADDR_LE_RANDOM; - } - } else { - *own_addr_type = bt_dev.id_addr[0].type; - - /* Use NRPA unless identity has been explicitly requested - * (through Kconfig). - * Use same RPA as legacy advertiser if advertising. - */ - if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - !is_adv_using_rand_addr()) { - err = le_set_private_addr(BT_ID_DEFAULT); - if (err) { - if (active_scan || !is_adv_using_rand_addr()) { - return err; - } else { - BT_WARN("Ignoring failure to set " - "address for passive scan (%d)", - err); - } - } - - *own_addr_type = BT_ADDR_LE_RANDOM; - } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - *own_addr_type == BT_ADDR_LE_RANDOM) { - /* If scanning with Identity Address we must set the - * random identity address for both active and passive - * scanner in order to receive adv reports that are - * directed towards this identity. - */ - err = set_random_address(&bt_dev.id_addr[0].a); - if (err) { - return err; - } - } - } - - return 0; -} - static int start_le_scan_ext(struct bt_hci_ext_scan_phy *phy_1m, struct bt_hci_ext_scan_phy *phy_coded, uint16_t duration) @@ -4060,12 +3031,12 @@ static int start_le_scan_ext(struct bt_hci_ext_scan_phy *phy_1m, /* Allow bt_le_oob_get_local to be called directly before * starting a scan limited by timeout. */ - if (IS_ENABLED(CONFIG_BT_PRIVACY) && !rpa_is_new()) { + if (IS_ENABLED(CONFIG_BT_PRIVACY) && !bt_id_rpa_is_new()) { atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); } } - err = le_scan_set_random_addr(active_scan, &own_addr_type); + err = bt_id_set_scan_own_addr(active_scan, &own_addr_type); if (err) { return err; } @@ -4139,7 +3110,7 @@ static int start_le_scan_legacy(uint8_t scan_type, uint16_t interval, uint16_t w } active_scan = scan_type == BT_HCI_LE_SCAN_ACTIVE; - err = le_scan_set_random_addr(active_scan, &set_param.addr_type); + err = bt_id_set_scan_own_addr(active_scan, &set_param.addr_type); if (err) { return err; } @@ -4156,7 +3127,7 @@ static int start_le_scan_legacy(uint8_t scan_type, uint16_t interval, uint16_t w return err; } - err = set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); + err = bt_le_scan_set_enable(BT_HCI_LE_SCAN_ENABLE); if (err) { return err; } @@ -4201,7 +3172,7 @@ int bt_le_scan_update(bool fast_scan) if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { int err; - err = set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); + err = bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); if (err) { return err; } @@ -4369,7 +3340,7 @@ static void le_scan_timeout(struct net_buf *buf) atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); #if defined(CONFIG_BT_SMP) - pending_id_keys_update(); + bt_id_pending_keys_update(); #endif SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&scan_cbs, listener, next, node) { @@ -4906,7 +3877,7 @@ static void le_adv_set_terminated(struct net_buf *buf) atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); #if defined(CONFIG_BT_SMP) - pending_id_keys_update(); + bt_id_pending_keys_update(); #endif if (adv->cb && adv->cb->sent) { @@ -6078,35 +5049,6 @@ static int set_event_mask(void) return bt_hci_cmd_send_sync(BT_HCI_OP_SET_EVENT_MASK, buf, NULL); } -static uint8_t bt_read_public_addr(bt_addr_le_t *addr) -{ - struct bt_hci_rp_read_bd_addr *rp; - struct net_buf *rsp; - int err; - - /* Read Bluetooth Address */ - err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp); - if (err) { - BT_WARN("Failed to read public address"); - return 0U; - } - - rp = (void *)rsp->data; - - if (!bt_addr_cmp(&rp->bdaddr, BT_ADDR_ANY) || - !bt_addr_cmp(&rp->bdaddr, BT_ADDR_NONE)) { - BT_DBG("Controller has no public address"); - net_buf_unref(rsp); - return 0U; - } - - bt_addr_copy(&addr->a, &rp->bdaddr); - addr->type = BT_ADDR_LE_PUBLIC; - - net_buf_unref(rsp); - return 1U; -} - #if defined(CONFIG_BT_DEBUG) static const char *ver_str(uint8_t ver) { @@ -6237,7 +5179,7 @@ static void hci_vs_init(void) bt_addr_le_t addr; if ((bt_dev.hci_version < BT_HCI_VERSION_5_0) || - bt_read_public_addr(&addr)) { + bt_id_read_public_addr(&addr)) { BT_WARN("Controller doesn't seem to support " "Zephyr vendor HCI"); return; @@ -6348,31 +5290,9 @@ static int hci_init(void) #if defined(CONFIG_BT_HCI_VS_EXT) hci_vs_init(); #endif - if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { - BT_DBG("No user identity. Trying to set public."); - - bt_setup_public_id_addr(); - } - - if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { - BT_DBG("No public address. Trying to set static random."); - - err = bt_setup_random_id_addr(); - if (err) { - BT_ERR("Unable to set identity address"); - return err; - } - - /* The passive scanner just sends a dummy address type in the - * command. If the first activity does this, and the dummy type - * is a random address, it needs a valid value, even though it's - * not actually used. - */ - err = set_random_address(&bt_dev.id_addr[0].a); - if (err) { - BT_ERR("Unable to set random address"); - return err; - } + err = bt_id_init(); + if (err) { + return err; } return 0; @@ -6543,10 +5463,6 @@ static int bt_init(void) } } -#if defined(CONFIG_BT_PRIVACY) - k_delayed_work_init(&bt_dev.rpa_update, rpa_timeout); -#endif - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (!bt_dev.id_count) { BT_INFO("No ID address. App must call settings_load()"); @@ -6835,384 +5751,6 @@ const char *bt_get_name(void) #endif } -int bt_set_id_addr(const bt_addr_le_t *addr) -{ - bt_addr_le_t non_const_addr; - - if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - BT_ERR("Setting identity not allowed after bt_enable()"); - return -EBUSY; - } - - bt_addr_le_copy(&non_const_addr, addr); - - return bt_id_create(&non_const_addr, NULL); -} - -void bt_id_get(bt_addr_le_t *addrs, size_t *count) -{ - if (addrs) { - size_t to_copy = MIN(*count, bt_dev.id_count); - - memcpy(addrs, bt_dev.id_addr, to_copy * sizeof(bt_addr_le_t)); - *count = to_copy; - } else { - *count = bt_dev.id_count; - } -} - -static int id_find(const bt_addr_le_t *addr) -{ - uint8_t id; - - for (id = 0U; id < bt_dev.id_count; id++) { - if (!bt_addr_le_cmp(addr, &bt_dev.id_addr[id])) { - return id; - } - } - - return -ENOENT; -} - -static void id_create(uint8_t id, bt_addr_le_t *addr, uint8_t *irk) -{ - if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { - bt_addr_le_copy(&bt_dev.id_addr[id], addr); - } else { - bt_addr_le_t new_addr; - - do { - bt_addr_le_create_static(&new_addr); - /* Make sure we didn't generate a duplicate */ - } while (id_find(&new_addr) >= 0); - - bt_addr_le_copy(&bt_dev.id_addr[id], &new_addr); - - if (addr) { - bt_addr_le_copy(addr, &bt_dev.id_addr[id]); - } - } - -#if defined(CONFIG_BT_PRIVACY) - { - uint8_t zero_irk[16] = { 0 }; - - if (irk && memcmp(irk, zero_irk, 16)) { - memcpy(&bt_dev.irk[id], irk, 16); - } else { - bt_rand(&bt_dev.irk[id], 16); - if (irk) { - memcpy(irk, &bt_dev.irk[id], 16); - } - } - } -#endif - /* Only store if stack was already initialized. Before initialization - * we don't know the flash content, so it's potentially harmful to - * try to write anything there. - */ - if (IS_ENABLED(CONFIG_BT_SETTINGS) && - atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - bt_settings_save_id(); - } -} - -int bt_id_create(bt_addr_le_t *addr, uint8_t *irk) -{ - int new_id; - - if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { - if (addr->type != BT_ADDR_LE_RANDOM || - !BT_ADDR_IS_STATIC(&addr->a)) { - BT_ERR("Only static random identity address supported"); - return -EINVAL; - } - - if (id_find(addr) >= 0) { - return -EALREADY; - } - } - - if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { - return -EINVAL; - } - - if (bt_dev.id_count == ARRAY_SIZE(bt_dev.id_addr)) { - return -ENOMEM; - } - - /* bt_rand is not available before Bluetooth enable has been called */ - if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) { - uint8_t zero_irk[16] = { 0 }; - - if (!(addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY))) { - return -EINVAL; - } - - if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !(irk && memcmp(irk, zero_irk, 16))) { - return -EINVAL; - } - } - - new_id = bt_dev.id_count++; - id_create(new_id, addr, irk); - - return new_id; -} - -int bt_id_reset(uint8_t id, bt_addr_le_t *addr, uint8_t *irk) -{ - struct adv_id_check_data check_data = { - .id = id, - .adv_enabled = false, - }; - - if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { - if (addr->type != BT_ADDR_LE_RANDOM || - !BT_ADDR_IS_STATIC(&addr->a)) { - BT_ERR("Only static random identity address supported"); - return -EINVAL; - } - - if (id_find(addr) >= 0) { - return -EALREADY; - } - } - - if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { - return -EINVAL; - } - - if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { - return -EINVAL; - } - - bt_adv_foreach(adv_id_check_func, &check_data); - if (check_data.adv_enabled) { - return -EBUSY; - } - - if (IS_ENABLED(CONFIG_BT_CONN) && - bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { - int err; - - err = bt_unpair(id, NULL); - if (err) { - return err; - } - } - - id_create(id, addr, irk); - - return id; -} - -int bt_id_delete(uint8_t id) -{ - struct adv_id_check_data check_data = { - .id = id, - .adv_enabled = false, - }; - - if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { - return -EINVAL; - } - - if (!bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { - return -EALREADY; - } - - bt_adv_foreach(adv_id_check_func, &check_data); - if (check_data.adv_enabled) { - return -EBUSY; - } - - if (IS_ENABLED(CONFIG_BT_CONN)) { - int err; - - err = bt_unpair(id, NULL); - if (err) { - return err; - } - } - -#if defined(CONFIG_BT_PRIVACY) - (void)memset(bt_dev.irk[id], 0, 16); -#endif - bt_addr_le_copy(&bt_dev.id_addr[id], BT_ADDR_LE_ANY); - - if (id == bt_dev.id_count - 1) { - bt_dev.id_count--; - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && - atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - bt_settings_save_id(); - } - - return 0; -} - -#if defined(CONFIG_BT_PRIVACY) -static void bt_read_identity_root(uint8_t *ir) -{ - /* Invalid IR */ - memset(ir, 0, 16); - -#if defined(CONFIG_BT_HCI_VS_EXT) - struct bt_hci_rp_vs_read_key_hierarchy_roots *rp; - struct net_buf *rsp; - int err; - - if (!BT_VS_CMD_READ_KEY_ROOTS(bt_dev.vs_commands)) { - return; - } - - err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS, NULL, - &rsp); - if (err) { - BT_WARN("Failed to read identity root"); - return; - } - - if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && - rsp->len != sizeof(struct bt_hci_rp_vs_read_key_hierarchy_roots)) { - BT_WARN("Invalid Vendor HCI extensions"); - net_buf_unref(rsp); - return; - } - - rp = (void *)rsp->data; - memcpy(ir, rp->ir, 16); - - net_buf_unref(rsp); -#endif /* defined(CONFIG_BT_HCI_VS_EXT) */ -} -#endif /* defined(CONFIG_BT_PRIVACY) */ - -void bt_setup_public_id_addr(void) -{ - bt_addr_le_t addr; - uint8_t *irk = NULL; - - bt_dev.id_count = bt_read_public_addr(&addr); - - if (!bt_dev.id_count) { - return; - } - -#if defined(CONFIG_BT_PRIVACY) - uint8_t ir_irk[16]; - uint8_t ir[16]; - - bt_read_identity_root(ir); - - if (!bt_smp_irk_get(ir, ir_irk)) { - irk = ir_irk; - } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); - } -#endif /* defined(CONFIG_BT_PRIVACY) */ - - id_create(BT_ID_DEFAULT, &addr, irk); -} - -#if defined(CONFIG_BT_HCI_VS_EXT) -uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) -{ - struct bt_hci_rp_vs_read_static_addrs *rp; - struct net_buf *rsp; - int err, i; - uint8_t cnt; - - if (!BT_VS_CMD_READ_STATIC_ADDRS(bt_dev.vs_commands)) { - BT_WARN("Read Static Addresses command not available"); - return 0; - } - - err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS, NULL, &rsp); - if (err) { - BT_WARN("Failed to read static addresses"); - return 0; - } - - if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && - rsp->len < sizeof(struct bt_hci_rp_vs_read_static_addrs)) { - BT_WARN("Invalid Vendor HCI extensions"); - net_buf_unref(rsp); - return 0; - } - - rp = (void *)rsp->data; - cnt = MIN(rp->num_addrs, size); - - if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && - rsp->len != (sizeof(struct bt_hci_rp_vs_read_static_addrs) + - rp->num_addrs * - sizeof(struct bt_hci_vs_static_addr))) { - BT_WARN("Invalid Vendor HCI extensions"); - net_buf_unref(rsp); - return 0; - } - - for (i = 0; i < cnt; i++) { - memcpy(&addrs[i], rp->a, sizeof(struct bt_hci_vs_static_addr)); - } - - net_buf_unref(rsp); - if (!cnt) { - BT_WARN("No static addresses stored in controller"); - } - - return cnt; -} -#endif /* CONFIG_BT_HCI_VS_EXT */ - -int bt_setup_random_id_addr(void) -{ -#if defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) - /* Only read the addresses if the user has not already configured one or - * more identities (!bt_dev.id_count). - */ - if (!bt_dev.id_count) { - struct bt_hci_vs_static_addr addrs[CONFIG_BT_ID_MAX]; - - bt_dev.id_count = bt_read_static_addr(addrs, CONFIG_BT_ID_MAX); - - if (bt_dev.id_count) { - for (uint8_t i = 0; i < bt_dev.id_count; i++) { - bt_addr_le_t addr; - uint8_t *irk = NULL; -#if defined(CONFIG_BT_PRIVACY) - uint8_t ir_irk[16]; - - if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) { - irk = ir_irk; - } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - atomic_set_bit(bt_dev.flags, - BT_DEV_STORE_ID); - } -#endif /* CONFIG_BT_PRIVACY */ - - bt_addr_copy(&addr.a, &addrs[i].bdaddr); - addr.type = BT_ADDR_LE_RANDOM; - - id_create(i, &addr, irk); - } - - return 0; - } - } -#endif /* defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) */ - - if (IS_ENABLED(CONFIG_BT_PRIVACY) && IS_ENABLED(CONFIG_BT_SETTINGS)) { - atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); - } - - return bt_id_create(NULL, NULL); -} - bool bt_addr_le_is_bonded(uint8_t id, const bt_addr_le_t *addr) { if (IS_ENABLED(CONFIG_BT_SMP)) { @@ -8050,7 +6588,7 @@ static int le_adv_update(struct bt_le_ext_adv *adv, int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); bool scannable, use_name; if (!adv) { @@ -8103,109 +6641,17 @@ static uint8_t get_adv_channel_map(uint32_t options) return channel_map; } -static int le_adv_set_random_addr(struct bt_le_ext_adv *adv, uint32_t options, - bool dir_adv, uint8_t *own_addr_type) -{ - const bt_addr_le_t *id_addr; - int err = 0; - - /* Set which local identity address we're advertising with */ - id_addr = &bt_dev.id_addr[adv->id]; - - if (options & BT_LE_ADV_OPT_CONNECTABLE) { - if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA) && - !BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { - return -ENOTSUP; - } - - if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !(options & BT_LE_ADV_OPT_USE_IDENTITY)) { - err = le_adv_set_private_addr(adv); - if (err) { - return err; - } - - if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA)) { - *own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; - } else { - *own_addr_type = BT_ADDR_LE_RANDOM; - } - } else { - /* - * If Static Random address is used as Identity - * address we need to restore it before advertising - * is enabled. Otherwise NRPA used for active scan - * could be used for advertising. - */ - if (id_addr->type == BT_ADDR_LE_RANDOM) { - err = set_adv_random_address(adv, &id_addr->a); - if (err) { - return err; - } - } - - *own_addr_type = id_addr->type; - - if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA)) { - *own_addr_type |= BT_HCI_OWN_ADDR_RPA_MASK; - } - } - } else { - if (options & BT_LE_ADV_OPT_USE_IDENTITY) { - if (id_addr->type == BT_ADDR_LE_RANDOM) { - err = set_adv_random_address(adv, &id_addr->a); - } - - *own_addr_type = id_addr->type; - } else if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { - /* In case advertising set random address is not - * available we must handle the shared random address - * problem. - */ -#if defined(CONFIG_BT_OBSERVER) - bool scan_enabled = false; - - /* If active scan with NRPA is ongoing refresh NRPA */ - if (!IS_ENABLED(CONFIG_BT_PRIVACY) && - !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && - atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) { - scan_enabled = true; - set_le_scan_enable(false); - } -#endif /* defined(CONFIG_BT_OBSERVER) */ - err = le_adv_set_private_addr(adv); - *own_addr_type = BT_ADDR_LE_RANDOM; - -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { - set_le_scan_enable(true); - } -#endif /* defined(CONFIG_BT_OBSERVER) */ - } else { - err = le_adv_set_private_addr(adv); - *own_addr_type = BT_ADDR_LE_RANDOM; - } - - if (err) { - return err; - } - } - - return 0; -} static int le_adv_start_add_conn(const struct bt_le_ext_adv *adv, struct bt_conn **out_conn) { - struct adv_id_check_data check_data = { + struct bt_adv_id_check_data check_data = { .id = adv->id, .adv_enabled = false }; struct bt_conn *conn; - bt_adv_foreach(adv_id_check_connectable_func, &check_data); + bt_le_ext_adv_foreach(adv_id_check_connectable_func, &check_data); if (check_data.adv_enabled) { return -ENOTSUP; } @@ -8257,7 +6703,7 @@ int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv, return -EINVAL; } - if (!bt_le_adv_random_addr_check(param)) { + if (!bt_id_adv_random_addr_check(param)) { return -EINVAL; } @@ -8279,7 +6725,7 @@ int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv, adv->id = param->id; bt_dev.adv_conn_id = adv->id; - err = le_adv_set_random_addr(adv, param->options, dir_adv, + err = bt_id_set_adv_own_addr(adv, param->options, dir_adv, &set_param.own_addr_type); if (err) { return err; @@ -8346,7 +6792,7 @@ int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv, } } - err = set_le_adv_enable(adv, true); + err = bt_le_adv_set_enable(adv, true); if (err) { BT_ERR("Failed to start advertiser"); if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) { @@ -8401,7 +6847,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, cp = net_buf_add(buf, sizeof(*cp)); (void)memset(cp, 0, sizeof(*cp)); - err = le_adv_set_random_addr(adv, param->options, dir_adv, + err = bt_id_set_adv_own_addr(adv, param->options, dir_adv, &cp->own_addr_type); if (err) { return err; @@ -8495,7 +6941,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, atomic_set_bit(adv->flags, BT_ADV_PARAMS_SET); if (atomic_test_and_clear_bit(adv->flags, BT_ADV_RANDOM_ADDR_PENDING)) { - err = set_adv_random_address(adv, &adv->random_addr.a); + err = bt_id_set_adv_random_addr(adv, &adv->random_addr.a); if (err) { return err; } @@ -8579,7 +7025,7 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, } } - err = set_le_adv_enable_ext(adv, true, &start_param); + err = bt_le_adv_set_enable_ext(adv, true, &start_param); if (err) { BT_ERR("Failed to start advertiser"); if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) { @@ -8634,7 +7080,7 @@ int bt_le_adv_start(const struct bt_le_adv_param *param, int bt_le_adv_stop(void) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); int err; if (!adv) { @@ -8663,12 +7109,12 @@ int bt_le_adv_stop(void) if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - err = set_le_adv_enable_ext(adv, false, NULL); + err = bt_le_adv_set_enable_ext(adv, false, NULL); if (err) { return err; } } else { - err = set_le_adv_enable_legacy(adv, false); + err = bt_le_adv_set_enable_legacy(adv, false); if (err) { return err; } @@ -8683,9 +7129,9 @@ int bt_le_adv_stop(void) !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY)) { /* If scan is ongoing set back NRPA */ if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { - set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); - le_set_private_addr(BT_ID_DEFAULT); - set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); + bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); + bt_id_set_private_addr(BT_ID_DEFAULT); + bt_le_scan_set_enable(BT_HCI_LE_SCAN_ENABLE); } } #endif /* defined(CONFIG_BT_OBSERVER) */ @@ -8696,7 +7142,7 @@ int bt_le_adv_stop(void) #if defined(CONFIG_BT_PERIPHERAL) void bt_le_adv_resume(void) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); struct bt_conn *conn; bool persist_paused = false; int err; @@ -8725,10 +7171,10 @@ void bt_le_adv_resume(void) if (IS_ENABLED(CONFIG_BT_PRIVACY) && !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - le_adv_set_private_addr(adv); + bt_id_set_adv_private_addr(adv); } - err = set_le_adv_enable(adv, true); + err = bt_le_adv_set_enable(adv, true); if (err) { BT_DBG("Controller cannot resume connectable advertising (%d)", err); @@ -8845,11 +7291,11 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, if (atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { if (IS_ENABLED(CONFIG_BT_PRIVACY) && !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - le_adv_set_private_addr(adv); + bt_id_set_adv_private_addr(adv); } } else { if (!atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - le_adv_set_private_addr(adv); + bt_id_set_adv_private_addr(adv); } } @@ -8859,7 +7305,7 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, bt_le_ext_adv_set_data(adv, NULL, 0, NULL, 0); } - err = set_le_adv_enable_ext(adv, true, param); + err = bt_le_adv_set_enable_ext(adv, true, param); if (err) { BT_ERR("Failed to start advertiser"); if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) { @@ -8894,7 +7340,7 @@ int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv) atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); #if defined(CONFIG_BT_SMP) - pending_id_keys_update(); + bt_id_pending_keys_update(); #endif } @@ -8903,7 +7349,7 @@ int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv) le_adv_stop_free_conn(adv, 0); } - return set_le_adv_enable_ext(adv, false, NULL); + return bt_le_adv_set_enable_ext(adv, false, NULL); } int bt_le_ext_adv_set_data(struct bt_le_ext_adv *adv, @@ -8998,7 +7444,7 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) return -EINVAL; } - if (param->type && !bt_le_scan_random_addr_check()) { + if (param->type && !bt_id_scan_random_addr_check()) { return -EINVAL; } @@ -9008,7 +7454,7 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) } if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { - err = set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); + err = bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); if (err) { atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); return err; @@ -9088,7 +7534,7 @@ int bt_le_scan_stop(void) atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); #if defined(CONFIG_BT_SMP) - pending_id_keys_update(); + bt_id_pending_keys_update(); #endif } @@ -9396,173 +7842,3 @@ int bt_br_set_discoverable(bool enable) } } #endif /* CONFIG_BT_BREDR */ - -#if defined(CONFIG_BT_BREDR) -int bt_br_oob_get_local(struct bt_br_oob *oob) -{ - bt_addr_copy(&oob->addr, &bt_dev.id_addr[0].a); - - return 0; -} -#endif /* CONFIG_BT_BREDR */ - -int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob) -{ - struct bt_le_ext_adv *adv; - int err; - - if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - return -EAGAIN; - } - - if (id >= CONFIG_BT_ID_MAX) { - return -EINVAL; - } - - adv = bt_adv_lookup_legacy(); - - if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !(adv && adv->id == id && - atomic_test_bit(adv->flags, BT_ADV_ENABLED) && - atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && - bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { - if (IS_ENABLED(CONFIG_BT_CENTRAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { - struct bt_conn *conn; - - conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, - BT_CONN_CONNECT_SCAN); - if (conn) { - /* Cannot set new RPA while creating - * connections. - */ - bt_conn_unref(conn); - return -EINVAL; - } - } - - if (adv && - atomic_test_bit(adv->flags, BT_ADV_ENABLED) && - atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && - (bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { - /* Cannot set a new RPA address while advertising with - * random static identity address for a different - * identity. - */ - return -EINVAL; - } - - if (IS_ENABLED(CONFIG_BT_OBSERVER) && - id != BT_ID_DEFAULT && - (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) || - atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING))) { - /* Cannot switch identity of scanner or initiator */ - return -EINVAL; - } - - le_rpa_invalidate(); - le_update_private_addr(); - - bt_addr_le_copy(&oob->addr, &bt_dev.random_addr); - } else { - bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[id]); - } - - if (IS_ENABLED(CONFIG_BT_SMP)) { - err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data); - if (err && err != -ENOTSUP) { - return err; - } - } - - return 0; -} - -#if defined(CONFIG_BT_EXT_ADV) -int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv, - struct bt_le_oob *oob) -{ - int err; - - if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - return -EAGAIN; - } - - if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - /* Don't refresh RPA addresses if the RPA is new. - * This allows back to back calls to this function or - * bt_le_oob_get_local to not invalidate the previously set - * RPAs. - */ - if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED) && - !rpa_is_new()) { - if (IS_ENABLED(CONFIG_BT_CENTRAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { - struct bt_conn *conn; - - conn = bt_conn_lookup_state_le( - BT_ID_DEFAULT, NULL, - BT_CONN_CONNECT_SCAN); - - if (conn) { - /* Cannot set new RPA while creating - * connections. - */ - bt_conn_unref(conn); - return -EINVAL; - } - } - - le_rpa_invalidate(); - le_update_private_addr(); - } - - bt_addr_le_copy(&oob->addr, &adv->random_addr); - } else { - bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[adv->id]); - } - - if (IS_ENABLED(CONFIG_BT_SMP)) { - err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data); - if (err && err != -ENOTSUP) { - return err; - } - } - - return 0; -} -#endif /* defined(CONFIG_BT_EXT_ADV) */ - -#if defined(CONFIG_BT_SMP) -#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) -int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk) -{ - return bt_smp_le_oob_set_tk(conn, tk); -} -#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ - -#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) -int bt_le_oob_set_sc_data(struct bt_conn *conn, - const struct bt_le_oob_sc_data *oobd_local, - const struct bt_le_oob_sc_data *oobd_remote) -{ - if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - return -EAGAIN; - } - - return bt_smp_le_oob_set_sc_data(conn, oobd_local, oobd_remote); -} - -int bt_le_oob_get_sc_data(struct bt_conn *conn, - const struct bt_le_oob_sc_data **oobd_local, - const struct bt_le_oob_sc_data **oobd_remote) -{ - if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - return -EAGAIN; - } - - return bt_smp_le_oob_get_sc_data(conn, oobd_local, oobd_remote); -} -#endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */ -#endif /* defined(CONFIG_BT_SMP) */ diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index 89ac5e9e4d6..9f4211f5cf6 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -326,6 +326,11 @@ struct bt_hci_cmd_state_set { bool val; }; +struct bt_adv_id_check_data { + uint8_t id; + bool adv_enabled; +}; + /* Set command state related with the command buffer */ void bt_hci_cmd_state_set_init(struct net_buf *buf, struct bt_hci_cmd_state_set *state, @@ -364,7 +369,16 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param, const bt_addr_le_t *peer); void bt_le_adv_resume(void); -bool bt_le_scan_random_addr_check(void); +int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable); +int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv, + bool enable, + const struct bt_le_ext_adv_start_param *param); +struct bt_le_ext_adv *bt_le_adv_lookup_legacy(void); +int bt_le_adv_set_enable(struct bt_le_ext_adv *adv, bool enable); +void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), + void *data); + +int bt_le_scan_set_enable(uint8_t enable); void bt_hci_host_num_completed_packets(struct net_buf *buf); diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c new file mode 100644 index 00000000000..5a2173c7a6a --- /dev/null +++ b/subsys/bluetooth/host/id.c @@ -0,0 +1,1748 @@ +/* + * Copyright (c) 2017-2021 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include "hci_core.h" +#include "id.h" +#include "smp.h" +#include "conn_internal.h" +#include "keys.h" +#include "common/rpa.h" + +#include "settings.h" + +#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE) +#define LOG_MODULE_NAME bt_id +#include "common/log.h" + +#if defined(CONFIG_BT_OBSERVER) || defined(CONFIG_BT_BROADCASTER) +const bt_addr_le_t *bt_lookup_id_addr(uint8_t id, const bt_addr_le_t *addr) +{ + if (IS_ENABLED(CONFIG_BT_SMP)) { + struct bt_keys *keys; + + keys = bt_keys_find_irk(id, addr); + if (keys) { + BT_DBG("Identity %s matched RPA %s", + bt_addr_le_str(&keys->addr), + bt_addr_le_str(addr)); + return &keys->addr; + } + } + + return addr; +} +#endif /* CONFIG_BT_OBSERVER || CONFIG_BT_CONN */ + +static void adv_id_check_func(struct bt_le_ext_adv *adv, void *data) +{ + struct bt_adv_id_check_data *check_data = data; + + if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { + /* Only check if the ID is in use, as the advertiser can be + * started and stopped without reconfiguring parameters. + */ + if (check_data->id == adv->id) { + check_data->adv_enabled = true; + } + } else { + if (check_data->id == adv->id && + atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + check_data->adv_enabled = true; + } + } +} + +#if defined(CONFIG_BT_PRIVACY) +static void adv_is_private_enabled(struct bt_le_ext_adv *adv, void *data) +{ + bool *adv_enabled = data; + + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + *adv_enabled = true; + } +} +#endif /* defined(CONFIG_BT_PRIVACY) */ + +#if defined(CONFIG_BT_SMP) +static void adv_is_limited_enabled(struct bt_le_ext_adv *adv, void *data) +{ + bool *adv_enabled = data; + + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { + *adv_enabled = true; + } +} + +static void adv_pause_enabled(struct bt_le_ext_adv *adv, void *data) +{ + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + atomic_set_bit(adv->flags, BT_ADV_PAUSED); + bt_le_adv_set_enable(adv, false); + } +} + +static void adv_unpause_enabled(struct bt_le_ext_adv *adv, void *data) +{ + if (atomic_test_and_clear_bit(adv->flags, BT_ADV_PAUSED)) { + bt_le_adv_set_enable(adv, true); + } +} +#endif /* defined(CONFIG_BT_SMP) */ + +static int set_random_address(const bt_addr_t *addr) +{ + struct net_buf *buf; + int err; + + BT_DBG("%s", bt_addr_str(addr)); + + /* Do nothing if we already have the right address */ + if (!bt_addr_cmp(addr, &bt_dev.random_addr.a)) { + return 0; + } + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(*addr)); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_mem(buf, addr, sizeof(*addr)); + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf, NULL); + if (err) { + return err; + } + + bt_addr_copy(&bt_dev.random_addr.a, addr); + bt_dev.random_addr.type = BT_ADDR_LE_RANDOM; + return 0; +} + +int bt_id_set_adv_random_addr(struct bt_le_ext_adv *adv, + const bt_addr_t *addr) +{ + struct bt_hci_cp_le_set_adv_set_random_addr *cp; + struct net_buf *buf; + int err; + + if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + return set_random_address(addr); + } + + BT_DBG("%s", bt_addr_str(addr)); + + if (!atomic_test_bit(adv->flags, BT_ADV_PARAMS_SET)) { + bt_addr_copy(&adv->random_addr.a, addr); + adv->random_addr.type = BT_ADDR_LE_RANDOM; + atomic_set_bit(adv->flags, BT_ADV_RANDOM_ADDR_PENDING); + return 0; + } + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, + sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + + cp->handle = adv->handle; + bt_addr_copy(&cp->bdaddr, addr); + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, buf, + NULL); + if (err) { + return err; + } + + bt_addr_copy(&adv->random_addr.a, addr); + adv->random_addr.type = BT_ADDR_LE_RANDOM; + return 0; +} + +static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data) +{ + if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { + atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); + } +} + +static void le_rpa_invalidate(void) +{ + /* RPA must be submitted */ + atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_SET); + + /* Invalidate RPA */ + if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED))) { + atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); + } + + bt_le_ext_adv_foreach(adv_rpa_invalidate, NULL); +} + +#if defined(CONFIG_BT_PRIVACY) +static void le_rpa_timeout_submit(void) +{ + /* Check if RPA timer is running. */ + if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_SET)) { + return; + } + + k_delayed_work_submit(&bt_dev.rpa_update, RPA_TIMEOUT); +} + +/* this function sets new RPA only if current one is no longer valid */ +int bt_id_set_private_addr(uint8_t id) +{ + bt_addr_t rpa; + int err; + + /* check if RPA is valid */ + if (atomic_test_bit(bt_dev.flags, BT_DEV_RPA_VALID)) { + return 0; + } + + err = bt_rpa_create(bt_dev.irk[id], &rpa); + if (!err) { + err = set_random_address(&rpa); + if (!err) { + atomic_set_bit(bt_dev.flags, BT_DEV_RPA_VALID); + } + } + + le_rpa_timeout_submit(); + + if (err) { + return err; + } + + if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { + BT_INFO("RPA: %s", bt_addr_str(&rpa)); + } + + return 0; +} + +int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) +{ + bt_addr_t rpa; + int err; + + if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + return bt_id_set_private_addr(adv->id); + } + + /* check if RPA is valid */ + if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID)) { + return 0; + } + + if (adv == bt_le_adv_lookup_legacy() && adv->id == BT_ID_DEFAULT) { + /* Make sure that a Legacy advertiser using default ID has same + * RPA address as scanner roles. + */ + err = bt_id_set_private_addr(BT_ID_DEFAULT); + if (err) { + return err; + } + + err = bt_id_set_adv_random_addr(adv, &bt_dev.random_addr.a); + if (!err) { + atomic_set_bit(adv->flags, BT_ADV_RPA_VALID); + } + + return 0; + } + + err = bt_rpa_create(bt_dev.irk[adv->id], &rpa); + if (!err) { + err = bt_id_set_adv_random_addr(adv, &rpa); + if (!err) { + atomic_set_bit(adv->flags, BT_ADV_RPA_VALID); + } + } + + if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { + le_rpa_timeout_submit(); + } + + if (err) { + return err; + } + + if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { + BT_INFO("RPA: %s", bt_addr_str(&rpa)); + } + + return 0; +} +#else +int bt_id_set_private_addr(uint8_t id) +{ + bt_addr_t nrpa; + int err; + + err = bt_rand(nrpa.val, sizeof(nrpa.val)); + if (err) { + return err; + } + + BT_ADDR_SET_NRPA(&nrpa); + + err = set_random_address(&nrpa); + if (err) { + return err; + } + + if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { + BT_INFO("NRPA: %s", bt_addr_str(&nrpa)); + } + + return 0; +} + +int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) +{ + bt_addr_t nrpa; + int err; + + err = bt_rand(nrpa.val, sizeof(nrpa.val)); + if (err) { + return err; + } + + BT_ADDR_SET_NRPA(&nrpa); + + err = bt_id_set_adv_random_addr(adv, &nrpa); + if (err) { + return err; + } + + if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) { + BT_INFO("NRPA: %s", bt_addr_str(&nrpa)); + } + + return 0; +} +#endif /* defined(CONFIG_BT_PRIVACY) */ + +static void adv_update_rpa(struct bt_le_ext_adv *adv, void *data) +{ + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + !atomic_test_bit(adv->flags, BT_ADV_LIMITED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + int err; + + bt_le_adv_set_enable_ext(adv, false, NULL); + + err = bt_id_set_adv_private_addr(adv); + if (err) { + BT_WARN("Failed to update advertiser RPA address (%d)", + err); + } + + bt_le_adv_set_enable_ext(adv, true, NULL); + } +} + +static void le_update_private_addr(void) +{ + struct bt_le_ext_adv *adv = NULL; + bool adv_enabled = false; + uint8_t id = BT_ID_DEFAULT; + int err; + + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { + bt_le_ext_adv_foreach(adv_update_rpa, NULL); + } + +#if defined(CONFIG_BT_OBSERVER) + bool scan_enabled = false; + + if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN) && + !(IS_ENABLED(CONFIG_BT_EXT_ADV) && + atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED))) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); + scan_enabled = true; + } +#endif + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + IS_ENABLED(CONFIG_BT_WHITELIST) && + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { + /* Canceled initiating procedure will be restarted by + * connection complete event. + */ + bt_le_create_conn_cancel(); + } + + if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + adv = bt_le_adv_lookup_legacy(); + + if (adv && + atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + adv_enabled = true; + id = adv->id; + bt_le_adv_set_enable_legacy(adv, false); + } + } + + /* If both advertiser and scanner is running then the advertiser + * ID must be BT_ID_DEFAULT, this will update the RPA address + * for both roles. + */ + err = bt_id_set_private_addr(id); + if (err) { + BT_WARN("Failed to update RPA address (%d)", err); + return; + } + + if (adv && adv_enabled) { + bt_le_adv_set_enable_legacy(adv, true); + } + +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_ENABLE); + } +#endif +} + +#if defined(CONFIG_BT_PRIVACY) +static void rpa_timeout(struct k_work *work) +{ + bool adv_enabled = false; + + BT_DBG(""); + + if (IS_ENABLED(CONFIG_BT_CENTRAL)) { + struct bt_conn *conn = + bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, + BT_CONN_CONNECT_SCAN); + + if (conn) { + bt_conn_unref(conn); + bt_le_create_conn_cancel(); + } + } + + le_rpa_invalidate(); + + bt_le_ext_adv_foreach(adv_is_private_enabled, &adv_enabled); + + /* IF no roles using the RPA is running we can stop the RPA timer */ + if (!(adv_enabled || + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || + (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) { + return; + } + + le_update_private_addr(); +} +#endif /* CONFIG_BT_PRIVACY */ + +bool bt_id_scan_random_addr_check(void) +{ + struct bt_le_ext_adv *adv; + + if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || + (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + /* Advertiser is not enabled or advertiser and scanner are using + * a different random address. + */ + return true; + } + + adv = bt_le_adv_lookup_legacy(); + if (!adv) { + return true; + } + + /* If the advertiser is not active there is no issue */ + if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + return true; + } + + /* When privacy is enabled the random address will not be set + * immediately before starting the role, because the RPA might still be + * valid and only updated on RPA timeout. + */ + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + /* Cannot start scannor or initiator if the random address is + * used by the advertiser for an RPA with a different identity + * or for a random static identity address. + */ + if ((atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && + bt_dev.id_addr[adv->id].type == BT_ADDR_LE_RANDOM) || + adv->id != BT_ID_DEFAULT) { + return false; + } + } + + /* If privacy is not enabled then the random address will be attempted + * to be set before enabling the role. If another role is already using + * the random address then this command will fail, and should return + * the error code to the application. + */ + return true; +} + +bool bt_id_adv_random_addr_check(const struct bt_le_adv_param *param) +{ + if (!IS_ENABLED(CONFIG_BT_OBSERVER) || + (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + /* If scanner roles are not enabled or advertiser and scanner + * are using a different random address. + */ + return true; + } + + /* If scanner roles are not active there is no issue. */ + if (!(atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || + atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING))) { + return true; + } + + /* When privacy is enabled the random address will not be set + * immediately before starting the role, because the RPA might still be + * valid and only updated on RPA timeout. + */ + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + /* Cannot start an advertiser with random static identity or + * using an RPA generated for a different identity than scanner + * roles. + */ + if (((param->options & BT_LE_ADV_OPT_USE_IDENTITY) && + bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM) || + param->id != BT_ID_DEFAULT) { + return false; + } + } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && + atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_RANDOM) { + /* Scanning with random static identity. Stop the advertiser + * from overwriting the passive scanner identity address. + * In this case the LE Set Random Address command does not + * protect us in the case of a passive scanner. + * Explicitly stop it here. + */ + + if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE) && + (param->options & BT_LE_ADV_OPT_USE_IDENTITY)) { + /* Attempt to set non-connectable NRPA */ + return false; + } else if (bt_dev.id_addr[param->id].type == + BT_ADDR_LE_RANDOM && + param->id != BT_ID_DEFAULT) { + /* Attempt to set connectable, or non-connectable with + * identity different than scanner. + */ + return false; + } + } + + /* If privacy is not enabled then the random address will be attempted + * to be set before enabling the role. If another role is already using + * the random address then this command will fail, and should return + * the error code to the application. + */ + return true; +} + +#if defined(CONFIG_BT_SMP) +static int le_set_privacy_mode(const bt_addr_le_t *addr, uint8_t mode) +{ + struct bt_hci_cp_le_set_privacy_mode cp; + struct net_buf *buf; + int err; + + /* Check if set privacy mode command is supported */ + if (!BT_CMD_TEST(bt_dev.supported_commands, 39, 2)) { + BT_WARN("Set privacy mode command is not supported"); + return 0; + } + + BT_DBG("addr %s mode 0x%02x", bt_addr_le_str(addr), mode); + + bt_addr_le_copy(&cp.id_addr, addr); + cp.mode = mode; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PRIVACY_MODE, sizeof(cp)); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_mem(buf, &cp, sizeof(cp)); + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PRIVACY_MODE, buf, NULL); + if (err) { + return err; + } + + return 0; +} + +static int addr_res_enable(uint8_t enable) +{ + struct net_buf *buf; + + BT_DBG("%s", enable ? "enabled" : "disabled"); + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, 1); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_u8(buf, enable); + + return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, + buf, NULL); +} + +static int hci_id_add(uint8_t id, const bt_addr_le_t *addr, uint8_t peer_irk[16]) +{ + struct bt_hci_cp_le_add_dev_to_rl *cp; + struct net_buf *buf; + + BT_DBG("addr %s", bt_addr_le_str(addr)); + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_RL, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_le_copy(&cp->peer_id_addr, addr); + memcpy(cp->peer_irk, peer_irk, 16); + +#if defined(CONFIG_BT_PRIVACY) + memcpy(cp->local_irk, bt_dev.irk[id], 16); +#else + (void)memset(cp->local_irk, 0, 16); +#endif + + return bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_RL, buf, NULL); +} + +static void pending_id_update(struct bt_keys *keys, void *data) +{ + if (keys->state & BT_KEYS_ID_PENDING_ADD) { + keys->state &= ~BT_KEYS_ID_PENDING_ADD; + bt_id_add(keys); + return; + } + + if (keys->state & BT_KEYS_ID_PENDING_DEL) { + keys->state &= ~BT_KEYS_ID_PENDING_DEL; + bt_id_del(keys); + return; + } +} + +static void bt_id_pending_keys_update_set(struct bt_keys *keys, uint8_t flag) +{ + atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING); + keys->state |= flag; +} + +void bt_id_pending_keys_update(void) +{ + if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ID_PENDING)) { + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + IS_ENABLED(CONFIG_BT_PRIVACY)) { + bt_keys_foreach(BT_KEYS_ALL, pending_id_update, NULL); + } else { + bt_keys_foreach(BT_KEYS_IRK, pending_id_update, NULL); + } + } +} + +void bt_id_add(struct bt_keys *keys) +{ + struct bt_conn *conn; + int err; + + BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); + + /* Nothing to be done if host-side resolving is used */ + if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { + bt_dev.le.rl_entries++; + keys->state |= BT_KEYS_ID_ADDED; + return; + } + + conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); + if (conn) { + bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); + bt_conn_unref(conn); + return; + } + + if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { + bool adv_enabled = false; + + bt_le_ext_adv_foreach(adv_is_limited_enabled, &adv_enabled); + if (adv_enabled) { + bt_id_pending_keys_update_set(keys, + BT_KEYS_ID_PENDING_ADD); + return; + } + } + +#if defined(CONFIG_BT_OBSERVER) + bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); + + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && scan_enabled && + atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) { + bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); + } +#endif + + bt_le_ext_adv_foreach(adv_pause_enabled, NULL); + +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); + } +#endif /* CONFIG_BT_OBSERVER */ + + /* If there are any existing entries address resolution will be on */ + if (bt_dev.le.rl_entries) { + err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE); + if (err) { + BT_WARN("Failed to disable address resolution"); + goto done; + } + } + + if (bt_dev.le.rl_entries == bt_dev.le.rl_size) { + BT_WARN("Resolving list size exceeded. Switching to host."); + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_RL, NULL, NULL); + if (err) { + BT_ERR("Failed to clear resolution list"); + goto done; + } + + bt_dev.le.rl_entries++; + keys->state |= BT_KEYS_ID_ADDED; + + goto done; + } + + err = hci_id_add(keys->id, &keys->addr, keys->irk.val); + if (err) { + BT_ERR("Failed to add IRK to controller"); + goto done; + } + + bt_dev.le.rl_entries++; + keys->state |= BT_KEYS_ID_ADDED; + + /* + * According to Core Spec. 5.0 Vol 1, Part A 5.4.5 Privacy Feature + * + * By default, network privacy mode is used when private addresses are + * resolved and generated by the Controller, so advertising packets from + * peer devices that contain private addresses will only be accepted. + * By changing to the device privacy mode device is only concerned about + * its privacy and will accept advertising packets from peer devices + * that contain their identity address as well as ones that contain + * a private address, even if the peer device has distributed its IRK in + * the past. + */ + err = le_set_privacy_mode(&keys->addr, BT_HCI_LE_PRIVACY_MODE_DEVICE); + if (err) { + BT_ERR("Failed to set privacy mode"); + goto done; + } + +done: + addr_res_enable(BT_HCI_ADDR_RES_ENABLE); + +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_ENABLE); + } +#endif /* CONFIG_BT_OBSERVER */ + + bt_le_ext_adv_foreach(adv_unpause_enabled, NULL); +} + +static void keys_add_id(struct bt_keys *keys, void *data) +{ + if (keys->state & BT_KEYS_ID_ADDED) { + hci_id_add(keys->id, &keys->addr, keys->irk.val); + } +} + +static int hci_id_del(const bt_addr_le_t *addr) +{ + struct bt_hci_cp_le_rem_dev_from_rl *cp; + struct net_buf *buf; + + BT_DBG("addr %s", bt_addr_le_str(addr)); + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_RL, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_le_copy(&cp->peer_id_addr, addr); + + return bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_RL, buf, NULL); +} + +void bt_id_del(struct bt_keys *keys) +{ + struct bt_conn *conn; + int err; + + BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); + + if (!bt_dev.le.rl_size || + bt_dev.le.rl_entries > bt_dev.le.rl_size + 1) { + bt_dev.le.rl_entries--; + keys->state &= ~BT_KEYS_ID_ADDED; + return; + } + + conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); + if (conn) { + bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL); + bt_conn_unref(conn); + return; + } + + if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { + bool adv_enabled = false; + + bt_le_ext_adv_foreach(adv_is_limited_enabled, &adv_enabled); + if (adv_enabled) { + bt_id_pending_keys_update_set(keys, + BT_KEYS_ID_PENDING_ADD); + return; + } + } + +#if defined(CONFIG_BT_OBSERVER) + bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); + + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && scan_enabled && + atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) { + bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL); + } +#endif /* CONFIG_BT_OBSERVER */ + + bt_le_ext_adv_foreach(adv_pause_enabled, NULL); + +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); + } +#endif /* CONFIG_BT_OBSERVER */ + + err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE); + if (err) { + BT_ERR("Disabling address resolution failed (err %d)", err); + goto done; + } + + /* We checked size + 1 earlier, so here we know we can fit again */ + if (bt_dev.le.rl_entries > bt_dev.le.rl_size) { + bt_dev.le.rl_entries--; + keys->state &= ~BT_KEYS_ID_ADDED; + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + IS_ENABLED(CONFIG_BT_PRIVACY)) { + bt_keys_foreach(BT_KEYS_ALL, keys_add_id, NULL); + } else { + bt_keys_foreach(BT_KEYS_IRK, keys_add_id, NULL); + } + goto done; + } + + err = hci_id_del(&keys->addr); + if (err) { + BT_ERR("Failed to remove IRK from controller"); + goto done; + } + + bt_dev.le.rl_entries--; + keys->state &= ~BT_KEYS_ID_ADDED; + +done: + /* Only re-enable if there are entries to do resolving with */ + if (bt_dev.le.rl_entries) { + addr_res_enable(BT_HCI_ADDR_RES_ENABLE); + } + +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + bt_le_scan_set_enable(BT_HCI_LE_SCAN_ENABLE); + } +#endif /* CONFIG_BT_OBSERVER */ + + bt_le_ext_adv_foreach(adv_unpause_enabled, NULL); +} +#endif /* defined(CONFIG_BT_SMP) */ + + +int bt_set_id_addr(const bt_addr_le_t *addr) +{ + bt_addr_le_t non_const_addr; + + if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + BT_ERR("Setting identity not allowed after bt_enable()"); + return -EBUSY; + } + + bt_addr_le_copy(&non_const_addr, addr); + + return bt_id_create(&non_const_addr, NULL); +} + +void bt_id_get(bt_addr_le_t *addrs, size_t *count) +{ + if (addrs) { + size_t to_copy = MIN(*count, bt_dev.id_count); + + memcpy(addrs, bt_dev.id_addr, to_copy * sizeof(bt_addr_le_t)); + *count = to_copy; + } else { + *count = bt_dev.id_count; + } +} + +static int id_find(const bt_addr_le_t *addr) +{ + uint8_t id; + + for (id = 0U; id < bt_dev.id_count; id++) { + if (!bt_addr_le_cmp(addr, &bt_dev.id_addr[id])) { + return id; + } + } + + return -ENOENT; +} + +static void id_create(uint8_t id, bt_addr_le_t *addr, uint8_t *irk) +{ + if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { + bt_addr_le_copy(&bt_dev.id_addr[id], addr); + } else { + bt_addr_le_t new_addr; + + do { + bt_addr_le_create_static(&new_addr); + /* Make sure we didn't generate a duplicate */ + } while (id_find(&new_addr) >= 0); + + bt_addr_le_copy(&bt_dev.id_addr[id], &new_addr); + + if (addr) { + bt_addr_le_copy(addr, &bt_dev.id_addr[id]); + } + } + +#if defined(CONFIG_BT_PRIVACY) + { + uint8_t zero_irk[16] = { 0 }; + + if (irk && memcmp(irk, zero_irk, 16)) { + memcpy(&bt_dev.irk[id], irk, 16); + } else { + bt_rand(&bt_dev.irk[id], 16); + if (irk) { + memcpy(irk, &bt_dev.irk[id], 16); + } + } + } +#endif + /* Only store if stack was already initialized. Before initialization + * we don't know the flash content, so it's potentially harmful to + * try to write anything there. + */ + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + bt_settings_save_id(); + } +} + +int bt_id_create(bt_addr_le_t *addr, uint8_t *irk) +{ + int new_id; + + if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { + if (addr->type != BT_ADDR_LE_RANDOM || + !BT_ADDR_IS_STATIC(&addr->a)) { + BT_ERR("Only static random identity address supported"); + return -EINVAL; + } + + if (id_find(addr) >= 0) { + return -EALREADY; + } + } + + if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { + return -EINVAL; + } + + if (bt_dev.id_count == ARRAY_SIZE(bt_dev.id_addr)) { + return -ENOMEM; + } + + /* bt_rand is not available before Bluetooth enable has been called */ + if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) { + uint8_t zero_irk[16] = { 0 }; + + if (!(addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY))) { + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_BT_PRIVACY) && + !(irk && memcmp(irk, zero_irk, 16))) { + return -EINVAL; + } + } + + new_id = bt_dev.id_count++; + id_create(new_id, addr, irk); + + return new_id; +} + +int bt_id_reset(uint8_t id, bt_addr_le_t *addr, uint8_t *irk) +{ + struct bt_adv_id_check_data check_data = { + .id = id, + .adv_enabled = false, + }; + + if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { + if (addr->type != BT_ADDR_LE_RANDOM || + !BT_ADDR_IS_STATIC(&addr->a)) { + BT_ERR("Only static random identity address supported"); + return -EINVAL; + } + + if (id_find(addr) >= 0) { + return -EALREADY; + } + } + + if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { + return -EINVAL; + } + + if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { + return -EINVAL; + } + + bt_le_ext_adv_foreach(adv_id_check_func, &check_data); + if (check_data.adv_enabled) { + return -EBUSY; + } + + if (IS_ENABLED(CONFIG_BT_CONN) && + bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { + int err; + + err = bt_unpair(id, NULL); + if (err) { + return err; + } + } + + id_create(id, addr, irk); + + return id; +} + +int bt_id_delete(uint8_t id) +{ + struct bt_adv_id_check_data check_data = { + .id = id, + .adv_enabled = false, + }; + + if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { + return -EINVAL; + } + + if (!bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { + return -EALREADY; + } + + bt_le_ext_adv_foreach(adv_id_check_func, &check_data); + if (check_data.adv_enabled) { + return -EBUSY; + } + + if (IS_ENABLED(CONFIG_BT_CONN)) { + int err; + + err = bt_unpair(id, NULL); + if (err) { + return err; + } + } + +#if defined(CONFIG_BT_PRIVACY) + (void)memset(bt_dev.irk[id], 0, 16); +#endif + bt_addr_le_copy(&bt_dev.id_addr[id], BT_ADDR_LE_ANY); + + if (id == bt_dev.id_count - 1) { + bt_dev.id_count--; + } + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + bt_settings_save_id(); + } + + return 0; +} + +#if defined(CONFIG_BT_PRIVACY) +static void bt_read_identity_root(uint8_t *ir) +{ + /* Invalid IR */ + memset(ir, 0, 16); + +#if defined(CONFIG_BT_HCI_VS_EXT) + struct bt_hci_rp_vs_read_key_hierarchy_roots *rp; + struct net_buf *rsp; + int err; + + if (!BT_VS_CMD_READ_KEY_ROOTS(bt_dev.vs_commands)) { + return; + } + + err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS, NULL, + &rsp); + if (err) { + BT_WARN("Failed to read identity root"); + return; + } + + if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && + rsp->len != sizeof(struct bt_hci_rp_vs_read_key_hierarchy_roots)) { + BT_WARN("Invalid Vendor HCI extensions"); + net_buf_unref(rsp); + return; + } + + rp = (void *)rsp->data; + memcpy(ir, rp->ir, 16); + + net_buf_unref(rsp); +#endif /* defined(CONFIG_BT_HCI_VS_EXT) */ +} +#endif /* defined(CONFIG_BT_PRIVACY) */ + +uint8_t bt_id_read_public_addr(bt_addr_le_t *addr) +{ + struct bt_hci_rp_read_bd_addr *rp; + struct net_buf *rsp; + int err; + + /* Read Bluetooth Address */ + err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp); + if (err) { + BT_WARN("Failed to read public address"); + return 0U; + } + + rp = (void *)rsp->data; + + if (!bt_addr_cmp(&rp->bdaddr, BT_ADDR_ANY) || + !bt_addr_cmp(&rp->bdaddr, BT_ADDR_NONE)) { + BT_DBG("Controller has no public address"); + net_buf_unref(rsp); + return 0U; + } + + bt_addr_copy(&addr->a, &rp->bdaddr); + addr->type = BT_ADDR_LE_PUBLIC; + + net_buf_unref(rsp); + return 1U; +} + +void bt_setup_public_id_addr(void) +{ + bt_addr_le_t addr; + uint8_t *irk = NULL; + + bt_dev.id_count = bt_id_read_public_addr(&addr); + + if (!bt_dev.id_count) { + return; + } + +#if defined(CONFIG_BT_PRIVACY) + uint8_t ir_irk[16]; + uint8_t ir[16]; + + bt_read_identity_root(ir); + + if (!bt_smp_irk_get(ir, ir_irk)) { + irk = ir_irk; + } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); + } +#endif /* defined(CONFIG_BT_PRIVACY) */ + + id_create(BT_ID_DEFAULT, &addr, irk); +} + +#if defined(CONFIG_BT_HCI_VS_EXT) +uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) +{ + struct bt_hci_rp_vs_read_static_addrs *rp; + struct net_buf *rsp; + int err, i; + uint8_t cnt; + + if (!BT_VS_CMD_READ_STATIC_ADDRS(bt_dev.vs_commands)) { + BT_WARN("Read Static Addresses command not available"); + return 0; + } + + err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS, NULL, &rsp); + if (err) { + BT_WARN("Failed to read static addresses"); + return 0; + } + + if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && + rsp->len < sizeof(struct bt_hci_rp_vs_read_static_addrs)) { + BT_WARN("Invalid Vendor HCI extensions"); + net_buf_unref(rsp); + return 0; + } + + rp = (void *)rsp->data; + cnt = MIN(rp->num_addrs, size); + + if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && + rsp->len != (sizeof(struct bt_hci_rp_vs_read_static_addrs) + + rp->num_addrs * + sizeof(struct bt_hci_vs_static_addr))) { + BT_WARN("Invalid Vendor HCI extensions"); + net_buf_unref(rsp); + return 0; + } + + for (i = 0; i < cnt; i++) { + memcpy(&addrs[i], rp->a, sizeof(struct bt_hci_vs_static_addr)); + } + + net_buf_unref(rsp); + if (!cnt) { + BT_WARN("No static addresses stored in controller"); + } + + return cnt; +} +#endif /* CONFIG_BT_HCI_VS_EXT */ + +int bt_setup_random_id_addr(void) +{ +#if defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) + /* Only read the addresses if the user has not already configured one or + * more identities (!bt_dev.id_count). + */ + if (!bt_dev.id_count) { + struct bt_hci_vs_static_addr addrs[CONFIG_BT_ID_MAX]; + + bt_dev.id_count = bt_read_static_addr(addrs, CONFIG_BT_ID_MAX); + + if (bt_dev.id_count) { + for (uint8_t i = 0; i < bt_dev.id_count; i++) { + bt_addr_le_t addr; + uint8_t *irk = NULL; +#if defined(CONFIG_BT_PRIVACY) + uint8_t ir_irk[16]; + + if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) { + irk = ir_irk; + } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + atomic_set_bit(bt_dev.flags, + BT_DEV_STORE_ID); + } +#endif /* CONFIG_BT_PRIVACY */ + + bt_addr_copy(&addr.a, &addrs[i].bdaddr); + addr.type = BT_ADDR_LE_RANDOM; + + id_create(i, &addr, irk); + } + + return 0; + } + } +#endif /* defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) */ + + if (IS_ENABLED(CONFIG_BT_PRIVACY) && IS_ENABLED(CONFIG_BT_SETTINGS)) { + atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); + } + + return bt_id_create(NULL, NULL); +} + +#if defined(CONFIG_BT_CENTRAL) +static inline bool rpa_timeout_valid_check(void) +{ +#if defined(CONFIG_BT_PRIVACY) + /* Check if create conn timeout will happen before RPA timeout. */ + return k_delayed_work_remaining_get(&bt_dev.rpa_update) > + (10 * bt_dev.create_param.timeout); +#else + return true; +#endif +} + +int bt_id_set_create_conn_own_addr(bool use_filter, uint8_t *own_addr_type) +{ + int err; + + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + if (use_filter || rpa_timeout_valid_check()) { + err = bt_id_set_private_addr(BT_ID_DEFAULT); + if (err) { + return err; + } + } else { + /* Force new RPA timeout so that RPA timeout is not + * triggered while direct initiator is active. + */ + le_rpa_invalidate(); + le_update_private_addr(); + } + + if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { + *own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; + } else { + *own_addr_type = BT_ADDR_LE_RANDOM; + } + } else { + const bt_addr_le_t *addr = &bt_dev.id_addr[BT_ID_DEFAULT]; + + /* If Static Random address is used as Identity address we + * need to restore it before creating connection. Otherwise + * NRPA used for active scan could be used for connection. + */ + if (addr->type == BT_ADDR_LE_RANDOM) { + err = set_random_address(&addr->a); + if (err) { + return err; + } + } + + *own_addr_type = addr->type; + } + + return 0; +} +#endif /* defined(CONFIG_BT_CENTRAL) */ + +#if defined(CONFIG_BT_OBSERVER) +static bool is_adv_using_rand_addr(void) +{ + struct bt_le_ext_adv *adv; + + if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || + (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + /* When advertising is not enabled or is using extended + * advertising HCI commands then only the scanner uses the set + * random address command. + */ + return false; + } + + adv = bt_le_adv_lookup_legacy(); + + return adv && atomic_test_bit(adv->flags, BT_ADV_ENABLED); +} + +int bt_id_set_scan_own_addr(bool active_scan, uint8_t *own_addr_type) +{ + int err; + + if (IS_ENABLED(CONFIG_BT_PRIVACY)) { + err = bt_id_set_private_addr(BT_ID_DEFAULT); + if (err) { + return err; + } + + if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { + *own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; + } else { + *own_addr_type = BT_ADDR_LE_RANDOM; + } + } else { + *own_addr_type = bt_dev.id_addr[0].type; + + /* Use NRPA unless identity has been explicitly requested + * (through Kconfig). + * Use same RPA as legacy advertiser if advertising. + */ + if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && + !is_adv_using_rand_addr()) { + err = bt_id_set_private_addr(BT_ID_DEFAULT); + if (err) { + if (active_scan || !is_adv_using_rand_addr()) { + return err; + } else { + BT_WARN("Ignoring failure to set " + "address for passive scan (%d)", + err); + } + } + + *own_addr_type = BT_ADDR_LE_RANDOM; + } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && + *own_addr_type == BT_ADDR_LE_RANDOM) { + /* If scanning with Identity Address we must set the + * random identity address for both active and passive + * scanner in order to receive adv reports that are + * directed towards this identity. + */ + err = set_random_address(&bt_dev.id_addr[0].a); + if (err) { + return err; + } + } + } + + return 0; +} +#endif /* defined(CONFIG_BT_OBSERVER) */ + +int bt_id_set_adv_own_addr(struct bt_le_ext_adv *adv, uint32_t options, + bool dir_adv, uint8_t *own_addr_type) +{ + const bt_addr_le_t *id_addr; + int err = 0; + + /* Set which local identity address we're advertising with */ + id_addr = &bt_dev.id_addr[adv->id]; + + if (options & BT_LE_ADV_OPT_CONNECTABLE) { + if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA) && + !BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { + return -ENOTSUP; + } + + if (IS_ENABLED(CONFIG_BT_PRIVACY) && + !(options & BT_LE_ADV_OPT_USE_IDENTITY)) { + err = bt_id_set_adv_private_addr(adv); + if (err) { + return err; + } + + if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA)) { + *own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; + } else { + *own_addr_type = BT_ADDR_LE_RANDOM; + } + } else { + /* + * If Static Random address is used as Identity + * address we need to restore it before advertising + * is enabled. Otherwise NRPA used for active scan + * could be used for advertising. + */ + if (id_addr->type == BT_ADDR_LE_RANDOM) { + err = bt_id_set_adv_random_addr(adv, &id_addr->a); + if (err) { + return err; + } + } + + *own_addr_type = id_addr->type; + + if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA)) { + *own_addr_type |= BT_HCI_OWN_ADDR_RPA_MASK; + } + } + } else { + if (options & BT_LE_ADV_OPT_USE_IDENTITY) { + if (id_addr->type == BT_ADDR_LE_RANDOM) { + err = bt_id_set_adv_random_addr(adv, &id_addr->a); + } + + *own_addr_type = id_addr->type; + } else if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + /* In case advertising set random address is not + * available we must handle the shared random address + * problem. + */ +#if defined(CONFIG_BT_OBSERVER) + bool scan_enabled = false; + + /* If active scan with NRPA is ongoing refresh NRPA */ + if (!IS_ENABLED(CONFIG_BT_PRIVACY) && + !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && + atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) { + scan_enabled = true; + bt_le_scan_set_enable(false); + } +#endif /* defined(CONFIG_BT_OBSERVER) */ + err = bt_id_set_adv_private_addr(adv); + *own_addr_type = BT_ADDR_LE_RANDOM; + +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + bt_le_scan_set_enable(true); + } +#endif /* defined(CONFIG_BT_OBSERVER) */ + } else { + err = bt_id_set_adv_private_addr(adv); + *own_addr_type = BT_ADDR_LE_RANDOM; + } + + if (err) { + return err; + } + } + + return 0; +} + +#if defined(CONFIG_BT_BREDR) +int bt_br_oob_get_local(struct bt_br_oob *oob) +{ + bt_addr_copy(&oob->addr, &bt_dev.id_addr[0].a); + + return 0; +} +#endif /* CONFIG_BT_BREDR */ + +int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob) +{ + struct bt_le_ext_adv *adv; + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + if (id >= CONFIG_BT_ID_MAX) { + return -EINVAL; + } + + adv = bt_le_adv_lookup_legacy(); + + if (IS_ENABLED(CONFIG_BT_PRIVACY) && + !(adv && adv->id == id && + atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && + bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { + struct bt_conn *conn; + + conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, + BT_CONN_CONNECT_SCAN); + if (conn) { + /* Cannot set new RPA while creating + * connections. + */ + bt_conn_unref(conn); + return -EINVAL; + } + } + + if (adv && + atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && + (bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { + /* Cannot set a new RPA address while advertising with + * random static identity address for a different + * identity. + */ + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_BT_OBSERVER) && + id != BT_ID_DEFAULT && + (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) || + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING))) { + /* Cannot switch identity of scanner or initiator */ + return -EINVAL; + } + + le_rpa_invalidate(); + le_update_private_addr(); + + bt_addr_le_copy(&oob->addr, &bt_dev.random_addr); + } else { + bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[id]); + } + + if (IS_ENABLED(CONFIG_BT_SMP)) { + err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data); + if (err && err != -ENOTSUP) { + return err; + } + } + + return 0; +} + +#if defined(CONFIG_BT_EXT_ADV) +int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv, + struct bt_le_oob *oob) +{ + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + if (IS_ENABLED(CONFIG_BT_PRIVACY) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + /* Don't refresh RPA addresses if the RPA is new. + * This allows back to back calls to this function or + * bt_le_oob_get_local to not invalidate the previously set + * RPAs. + */ + if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED) && + !bt_id_rpa_is_new()) { + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { + struct bt_conn *conn; + + conn = bt_conn_lookup_state_le( + BT_ID_DEFAULT, NULL, + BT_CONN_CONNECT_SCAN); + + if (conn) { + /* Cannot set new RPA while creating + * connections. + */ + bt_conn_unref(conn); + return -EINVAL; + } + } + + le_rpa_invalidate(); + le_update_private_addr(); + } + + bt_addr_le_copy(&oob->addr, &adv->random_addr); + } else { + bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[adv->id]); + } + + if (IS_ENABLED(CONFIG_BT_SMP)) { + err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data); + if (err && err != -ENOTSUP) { + return err; + } + } + + return 0; +} +#endif /* defined(CONFIG_BT_EXT_ADV) */ + +#if defined(CONFIG_BT_SMP) +#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) +int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk) +{ + return bt_smp_le_oob_set_tk(conn, tk); +} +#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ + +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) +int bt_le_oob_set_sc_data(struct bt_conn *conn, + const struct bt_le_oob_sc_data *oobd_local, + const struct bt_le_oob_sc_data *oobd_remote) +{ + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + return bt_smp_le_oob_set_sc_data(conn, oobd_local, oobd_remote); +} + +int bt_le_oob_get_sc_data(struct bt_conn *conn, + const struct bt_le_oob_sc_data **oobd_local, + const struct bt_le_oob_sc_data **oobd_remote) +{ + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + return bt_smp_le_oob_get_sc_data(conn, oobd_local, oobd_remote); +} +#endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */ +#endif /* defined(CONFIG_BT_SMP) */ + +int bt_id_init(void) +{ + int err; + + if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { + BT_DBG("No user identity. Trying to set public."); + + bt_setup_public_id_addr(); + } + + if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { + BT_DBG("No public address. Trying to set static random."); + + err = bt_setup_random_id_addr(); + if (err) { + BT_ERR("Unable to set identity address"); + return err; + } + + /* The passive scanner just sends a dummy address type in the + * command. If the first activity does this, and the dummy type + * is a random address, it needs a valid value, even though it's + * not actually used. + */ + err = set_random_address(&bt_dev.id_addr[0].a); + if (err) { + BT_ERR("Unable to set random address"); + return err; + } + } + +#if defined(CONFIG_BT_PRIVACY) + k_delayed_work_init(&bt_dev.rpa_update, rpa_timeout); +#endif + + return 0; +} diff --git a/subsys/bluetooth/host/id.h b/subsys/bluetooth/host/id.h new file mode 100644 index 00000000000..13e2f9594aa --- /dev/null +++ b/subsys/bluetooth/host/id.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define RPA_TIMEOUT_MS (CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC) +#define RPA_TIMEOUT K_MSEC(RPA_TIMEOUT_MS) + +static inline bool bt_id_rpa_is_new(void) +{ +#if defined(CONFIG_BT_PRIVACY) + /* RPA is considered new if there is less than half a second since the + * timeout was started. + */ + return k_delayed_work_remaining_get(&bt_dev.rpa_update) > + (RPA_TIMEOUT_MS - 500); +#else + return false; +#endif +} + +int bt_id_init(void); + +uint8_t bt_id_read_public_addr(bt_addr_le_t *addr); + +int bt_id_set_create_conn_own_addr(bool use_filter, uint8_t *own_addr_type); + +int bt_id_set_scan_own_addr(bool active_scan, uint8_t *own_addr_type); + +int bt_id_set_adv_own_addr(struct bt_le_ext_adv *adv, uint32_t options, + bool dir_adv, uint8_t *own_addr_type); + +bool bt_id_adv_random_addr_check(const struct bt_le_adv_param *param); + +bool bt_id_scan_random_addr_check(void); + +int bt_id_set_adv_random_addr(struct bt_le_ext_adv *adv, + const bt_addr_t *addr); +int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv); + +int bt_id_set_private_addr(uint8_t id); + +void bt_id_pending_keys_update(void);