blob: c49e42bf508495116075b99b530d9fcb65a995cb [file] [log] [blame]
/*
* Copyright (c) 2017-2021 Nordic Semiconductor ASA
* Copyright (c) 2015-2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/check.h>
#include <zephyr/bluetooth/addr.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci_vs.h>
#include <zephyr/bluetooth/buf.h>
#include <zephyr/drivers/bluetooth/hci_driver.h>
#include <zephyr/sys/__assert.h>
#include "hci_core.h"
#include "id.h"
#include "scan.h"
#include "adv.h"
#include "smp.h"
#include "conn_internal.h"
#include "keys.h"
#include "common/rpa.h"
#include "settings.h"
#include <zephyr/bluetooth/hci.h>
#include "common/bt_str.h"
#define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_id);
struct bt_adv_id_check_data {
uint8_t id;
bool adv_enabled;
};
#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)
{
CHECKIF(id >= CONFIG_BT_ID_MAX || addr == NULL) {
return NULL;
}
if (IS_ENABLED(CONFIG_BT_SMP)) {
struct bt_keys *keys;
keys = bt_keys_find_irk(id, addr);
if (keys) {
LOG_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;
}
}
}
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;
}
}
#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;
LOG_DBG("%s", bt_addr_str(addr));
/* Do nothing if we already have the right address */
if (bt_addr_eq(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;
CHECKIF(adv == NULL || addr == NULL) {
return -EINVAL;
}
if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
return set_random_address(addr);
}
LOG_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;
}
if (&adv->random_addr.a != addr) {
bt_addr_copy(&adv->random_addr.a, addr);
}
adv->random_addr.type = BT_ADDR_LE_RANDOM;
return 0;
}
/* If rpa sharing is enabled, then rpa expired cb of adv-sets belonging
* to same id is verified to return true. If not, adv-sets will continue
* with old rpa through out the rpa rotations.
*/
static void adv_rpa_expired(struct bt_le_ext_adv *adv, void *data)
{
bool rpa_invalid = true;
#if defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY)
/* Notify the user about the RPA timeout and set the RPA validity. */
if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID) &&
adv->cb && adv->cb->rpa_expired) {
rpa_invalid = adv->cb->rpa_expired(adv);
}
#endif
if (IS_ENABLED(CONFIG_BT_RPA_SHARING)) {
if (adv->id >= bt_dev.id_count) {
return;
}
bool *rpa_invalid_set_ptr = data;
if (!rpa_invalid) {
rpa_invalid_set_ptr[adv->id] = false;
}
} else {
if (rpa_invalid) {
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
}
}
}
static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data)
{
/* RPA of Advertisers limited by timeot or number of packets only expire
* when they are stopped.
*/
if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED) &&
!atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
adv_rpa_expired(adv, data);
}
}
#if defined(CONFIG_BT_RPA_SHARING)
static void adv_rpa_clear_data(struct bt_le_ext_adv *adv, void *data)
{
if (adv->id >= bt_dev.id_count) {
return;
}
bool *rpa_invalid_set_ptr = data;
if (rpa_invalid_set_ptr[adv->id]) {
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
bt_addr_copy(&bt_dev.rpa[adv->id], BT_ADDR_NONE);
} else {
LOG_WRN("Adv sets rpa expired cb with id %d returns false\n", adv->id);
}
}
#endif
static void le_rpa_invalidate(void)
{
/* 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);
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
if (bt_dev.id_count == 0) {
return;
}
bool rpa_expired_data[bt_dev.id_count];
bt_le_ext_adv_foreach(adv_rpa_invalidate, &rpa_expired_data);
#if defined(CONFIG_BT_RPA_SHARING)
/* rpa_expired data collected. now clear data based on data collected. */
bt_le_ext_adv_foreach(adv_rpa_clear_data, &rpa_expired_data);
#endif
}
}
#if defined(CONFIG_BT_PRIVACY)
#if defined(CONFIG_BT_RPA_TIMEOUT_DYNAMIC)
static void le_rpa_timeout_update(void)
{
int err = 0;
if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_CHANGED)) {
struct net_buf *buf;
struct bt_hci_cp_le_set_rpa_timeout *cp;
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT,
sizeof(*cp));
if (!buf) {
LOG_ERR("Failed to create HCI RPA timeout command");
err = -ENOBUFS;
goto submit;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->rpa_timeout = sys_cpu_to_le16(bt_dev.rpa_timeout);
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RPA_TIMEOUT, buf, NULL);
if (err) {
LOG_ERR("Failed to send HCI RPA timeout command");
goto submit;
}
}
submit:
if (err) {
atomic_set_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_CHANGED);
}
}
#endif
static void le_rpa_timeout_submit(void)
{
#if defined(CONFIG_BT_RPA_TIMEOUT_DYNAMIC)
le_rpa_timeout_update();
#endif
(void)k_work_schedule(&bt_dev.rpa_update, K_SECONDS(bt_dev.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;
CHECKIF(id >= CONFIG_BT_ID_MAX) {
return -EINVAL;
}
/* 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)) {
LOG_INF("RPA: %s", bt_addr_str(&rpa));
}
return 0;
}
#if defined(CONFIG_BT_RPA_SHARING)
static int adv_rpa_get(struct bt_le_ext_adv *adv, bt_addr_t *rpa)
{
int err;
if (bt_addr_eq(&bt_dev.rpa[adv->id], BT_ADDR_NONE)) {
err = bt_rpa_create(bt_dev.irk[adv->id], &bt_dev.rpa[adv->id]);
if (err) {
return err;
}
}
bt_addr_copy(rpa, &bt_dev.rpa[adv->id]);
return 0;
}
#else
static int adv_rpa_get(struct bt_le_ext_adv *adv, bt_addr_t *rpa)
{
int err;
err = bt_rpa_create(bt_dev.irk[adv->id], rpa);
if (err) {
return err;
}
return 0;
}
#endif /* defined(CONFIG_BT_RPA_SHARING) */
int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv)
{
bt_addr_t rpa;
int err;
CHECKIF(adv == NULL) {
return -EINVAL;
}
if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
(adv->options & BT_LE_ADV_OPT_USE_NRPA)) {
/* The host doesn't support setting NRPAs when BT_PRIVACY=y.
* In that case you probably want to use an RPA anyway.
*/
LOG_ERR("NRPA not supported when BT_PRIVACY=y");
return -ENOSYS;
}
if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
BT_DEV_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)) {
/* Schedule the RPA timer if it is not running.
* The RPA may be valid without the timer running.
*/
if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) {
le_rpa_timeout_submit();
}
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 = adv_rpa_get(adv, &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)) {
LOG_INF("RPA: %s", bt_addr_str(&rpa));
}
return 0;
}
#else
int bt_id_set_private_addr(uint8_t id)
{
bt_addr_t nrpa;
int err;
CHECKIF(id >= CONFIG_BT_ID_MAX) {
return -EINVAL;
}
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)) {
LOG_INF("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;
CHECKIF(adv == NULL) {
return -EINVAL;
}
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)) {
LOG_INF("NRPA: %s", bt_addr_str(&nrpa));
}
return 0;
}
#endif /* defined(CONFIG_BT_PRIVACY) */
static void adv_pause_rpa(struct bt_le_ext_adv *adv, void *data)
{
bool *adv_enabled = data;
/* Disable advertising sets to prepare them for RPA update. */
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;
err = bt_le_adv_set_enable_ext(adv, false, NULL);
if (err) {
LOG_ERR("Failed to disable advertising (err %d)", err);
}
atomic_set_bit(adv->flags, BT_ADV_RPA_UPDATE);
*adv_enabled = true;
}
}
static bool le_adv_rpa_timeout(void)
{
bool adv_enabled = false;
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
/* Pause all advertising sets using RPAs */
bt_le_ext_adv_foreach(adv_pause_rpa, &adv_enabled);
} else {
/* Check if advertising set is enabled */
bt_le_ext_adv_foreach(adv_is_private_enabled, &adv_enabled);
}
}
return adv_enabled;
}
static void adv_enable_rpa(struct bt_le_ext_adv *adv, void *data)
{
if (atomic_test_and_clear_bit(adv->flags, BT_ADV_RPA_UPDATE)) {
int err;
err = bt_id_set_adv_private_addr(adv);
if (err) {
LOG_WRN("Failed to update advertiser RPA address (%d)", err);
}
err = bt_le_adv_set_enable_ext(adv, true, NULL);
if (err) {
LOG_ERR("Failed to enable advertising (err %d)", err);
}
}
}
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 defined(CONFIG_BT_OBSERVER)
bool scan_enabled = false;
if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) &&
!(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_FILTER_ACCEPT_LIST) &&
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_BROADCASTER) &&
!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
BT_DEV_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) {
LOG_WRN("Failed to update RPA address (%d)", err);
return;
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER) &&
IS_ENABLED(CONFIG_BT_EXT_ADV) &&
BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
bt_le_ext_adv_foreach(adv_enable_rpa, NULL);
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER) &&
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
}
static void le_force_rpa_timeout(void)
{
#if defined(CONFIG_BT_PRIVACY)
struct k_work_sync sync;
k_work_cancel_delayable_sync(&bt_dev.rpa_update, &sync);
#endif
(void)le_adv_rpa_timeout();
le_rpa_invalidate();
le_update_private_addr();
}
#if defined(CONFIG_BT_PRIVACY)
static void rpa_timeout(struct k_work *work)
{
bool adv_enabled;
LOG_DBG("");
if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
struct bt_conn *conn =
bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL,
BT_CONN_CONNECTING_SCAN);
if (conn) {
bt_conn_unref(conn);
bt_le_create_conn_cancel();
}
}
adv_enabled = le_adv_rpa_timeout();
le_rpa_invalidate();
/* 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_DEV_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 scanner 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)
{
CHECKIF(param == NULL) {
return false;
}
if (!IS_ENABLED(CONFIG_BT_OBSERVER) ||
(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
BT_DEV_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;
}
void bt_id_adv_limited_stopped(struct bt_le_ext_adv *adv)
{
adv_rpa_expired(adv, NULL);
}
#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)) {
LOG_WRN("Set privacy mode command is not supported");
return 0;
}
LOG_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;
LOG_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;
if (id >= CONFIG_BT_ID_MAX) {
return -EINVAL;
}
LOG_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)
(void)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_type(BT_KEYS_ALL, pending_id_update, NULL);
} else {
bt_keys_foreach_type(BT_KEYS_IRK, pending_id_update, NULL);
}
}
}
struct bt_id_conflict {
struct bt_keys *candidate;
struct bt_keys *found;
};
/* The Controller Resolve List is constrained by 7.8.38 "LE Add Device To
* Resolving List command". The Host is designed with the assumption that all
* local bonds can be put in the resolve list if there is room. Therefore we
* must refuse bonds that conflict in the resolve list. Notably, this prevents
* multiple local identities to bond with the same remote identity.
*/
void find_rl_conflict(struct bt_keys *resident, void *user_data)
{
struct bt_id_conflict *conflict = user_data;
bool addr_conflict;
bool irk_conflict;
__ASSERT_NO_MSG(conflict != NULL);
__ASSERT_NO_MSG(conflict->candidate != NULL);
__ASSERT_NO_MSG(resident != NULL);
/* Only uncommitted bonds can be in conflict with committed bonds. */
__ASSERT_NO_MSG((conflict->candidate->state & BT_KEYS_ID_ADDED) == 0);
if (conflict->found) {
return;
}
/* Test against committed bonds only. */
if ((resident->state & BT_KEYS_ID_ADDED) == 0) {
return;
}
addr_conflict = bt_addr_le_eq(&conflict->candidate->addr, &resident->addr);
/* All-zero IRK is "no IRK", and does not conflict with other Zero-IRKs. */
irk_conflict = (!bt_irk_eq(&conflict->candidate->irk, &(struct bt_irk){}) &&
bt_irk_eq(&conflict->candidate->irk, &resident->irk));
if (addr_conflict || irk_conflict) {
conflict->found = resident;
}
}
struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate)
{
struct bt_id_conflict conflict = {
.candidate = candidate,
};
bt_keys_foreach_type(BT_KEYS_IRK, find_rl_conflict, &conflict);
return conflict.found;
}
void bt_id_add(struct bt_keys *keys)
{
CHECKIF(keys == NULL) {
return;
}
struct bt_conn *conn;
int err;
LOG_DBG("addr %s", bt_addr_le_str(&keys->addr));
__ASSERT_NO_MSG(keys != NULL);
/* We assume (and could assert) !bt_id_find_conflict(keys) here. */
/* 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_CONNECTING);
if (conn) {
bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD);
bt_conn_unref(conn);
return;
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER) &&
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
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
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) {
LOG_WRN("Failed to disable address resolution");
goto done;
}
}
if (bt_dev.le.rl_entries == bt_dev.le.rl_size) {
LOG_WRN("Resolving list size exceeded. Switching to host.");
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_RL, NULL, NULL);
if (err) {
LOG_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) {
LOG_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) {
LOG_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 */
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
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;
LOG_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;
CHECKIF(keys == NULL) {
return;
}
LOG_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) {
__ASSERT_NO_MSG(bt_dev.le.rl_entries > 0);
if (bt_dev.le.rl_entries > 0) {
bt_dev.le.rl_entries--;
}
keys->state &= ~BT_KEYS_ID_ADDED;
return;
}
conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECTING);
if (conn) {
bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL);
bt_conn_unref(conn);
return;
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER) &&
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_DEL);
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 */
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
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) {
LOG_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_type(BT_KEYS_ALL, keys_add_id, NULL);
} else {
bt_keys_foreach_type(BT_KEYS_IRK, keys_add_id, NULL);
}
goto done;
}
err = hci_id_del(&keys->addr);
if (err) {
LOG_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 */
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
bt_le_ext_adv_foreach(adv_unpause_enabled, NULL);
}
}
#endif /* defined(CONFIG_BT_SMP) */
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_eq(addr, &bt_dev.id_addr[id])) {
return id;
}
}
return -ENOENT;
}
static int id_create(uint8_t id, bt_addr_le_t *addr, uint8_t *irk)
{
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) {
bt_addr_le_copy(&bt_dev.id_addr[id], addr);
} else {
bt_addr_le_t new_addr;
do {
int err;
err = bt_addr_le_create_static(&new_addr);
if (err) {
return err;
}
/* 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 {
int err;
err = bt_rand(&bt_dev.irk[id], 16);
if (err) {
return err;
}
if (irk) {
memcpy(irk, &bt_dev.irk[id], 16);
}
}
#if defined(CONFIG_BT_RPA_SHARING)
bt_addr_copy(&bt_dev.rpa[id], BT_ADDR_NONE);
#endif
}
#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)) {
(void)bt_settings_store_id();
(void)bt_settings_store_irk();
}
return 0;
}
int bt_id_create(bt_addr_le_t *addr, uint8_t *irk)
{
int new_id, err;
if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) {
return -EINVAL;
}
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) {
if (id_find(addr) >= 0) {
return -EALREADY;
}
if (addr->type == BT_ADDR_LE_PUBLIC && IS_ENABLED(CONFIG_BT_HCI_SET_PUBLIC_ADDR)) {
/* set the single public address */
if (bt_dev.id_count != 0) {
return -EALREADY;
}
bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], addr);
bt_dev.id_count++;
return BT_ID_DEFAULT;
} else if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) {
LOG_ERR("Only random static identity address supported");
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_eq(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++;
err = id_create(new_id, addr, irk);
if (err) {
bt_dev.id_count--;
return err;
}
return new_id;
}
int bt_id_reset(uint8_t id, bt_addr_le_t *addr, uint8_t *irk)
{
int err;
if (addr && !bt_addr_le_eq(addr, BT_ADDR_LE_ANY)) {
if (addr->type != BT_ADDR_LE_RANDOM ||
!BT_ADDR_IS_STATIC(&addr->a)) {
LOG_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;
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
struct bt_adv_id_check_data check_data = {
.id = id,
.adv_enabled = false,
};
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_eq(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) {
err = bt_unpair(id, NULL);
if (err) {
return err;
}
}
err = id_create(id, addr, irk);
if (err) {
return err;
}
return id;
}
int bt_id_delete(uint8_t id)
{
if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) {
return -EINVAL;
}
if (bt_addr_le_eq(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) {
return -EALREADY;
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
struct bt_adv_id_check_data check_data = {
.id = id,
.adv_enabled = false,
};
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)) {
(void)bt_settings_store_id();
(void)bt_settings_store_irk();
}
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) {
LOG_WRN("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)) {
LOG_WRN("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;
CHECKIF(addr == NULL) {
LOG_WRN("Invalid input parameters");
return 0U;
}
/* Read Bluetooth Address */
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp);
if (err) {
LOG_WRN("Failed to read public address");
return 0U;
}
rp = (void *)rsp->data;
if (bt_addr_eq(&rp->bdaddr, BT_ADDR_ANY) ||
bt_addr_eq(&rp->bdaddr, BT_ADDR_NONE)) {
LOG_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;
}
int 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 0;
}
#if defined(CONFIG_BT_PRIVACY)
uint8_t ir_irk[16];
uint8_t ir[16];
bt_read_identity_root(ir);
if (!IS_ENABLED(CONFIG_BT_PRIVACY_RANDOMIZE_IR)) {
if (!bt_smp_irk_get(ir, ir_irk)) {
irk = ir_irk;
}
}
#endif /* defined(CONFIG_BT_PRIVACY) */
/* If true, `id_create` will randomize the IRK. */
if (!irk && IS_ENABLED(CONFIG_BT_PRIVACY)) {
/* `id_create` will not store the id when called before BT_DEV_READY.
* But since part of the id will be randomized, it needs to be stored.
*/
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID);
}
}
return 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)) {
LOG_WRN("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) {
LOG_WRN("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)) {
LOG_WRN("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))) {
LOG_WRN("Invalid Vendor HCI extensions");
net_buf_unref(rsp);
return 0;
}
for (i = 0; i < cnt; i++) {
memcpy(&addrs[i], &rp->a[i], sizeof(struct bt_hci_vs_static_addr));
}
net_buf_unref(rsp);
if (!cnt) {
LOG_WRN("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++) {
int err;
bt_addr_le_t addr;
uint8_t *irk = NULL;
#if defined(CONFIG_BT_PRIVACY)
uint8_t ir_irk[16];
if (!IS_ENABLED(CONFIG_BT_PRIVACY_RANDOMIZE_IR)) {
if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) {
irk = ir_irk;
}
}
#endif /* CONFIG_BT_PRIVACY */
/* If true, `id_create` will randomize the IRK. */
if (!irk && IS_ENABLED(CONFIG_BT_PRIVACY)) {
/* `id_create` will not store the id when called before
* BT_DEV_READY. But since part of the id will be
* randomized, it needs to be stored.
*/
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID);
}
}
bt_addr_copy(&addr.a, &addrs[i].bdaddr);
addr.type = BT_ADDR_LE_RANDOM;
err = id_create(i, &addr, irk);
if (err) {
return err;
}
}
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)
uint32_t remaining_ms = k_ticks_to_ms_floor32(
k_work_delayable_remaining_get(&bt_dev.rpa_update));
/* Check if create conn timeout will happen before RPA timeout. */
return remaining_ms > (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;
CHECKIF(own_addr_type == NULL) {
return -EINVAL;
}
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_force_rpa_timeout();
}
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_DEV_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;
CHECKIF(own_addr_type == NULL) {
return -EINVAL;
}
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;
}
LOG_WRN("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;
}
} else {
LOG_DBG("Not changing the address");
}
}
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;
CHECKIF(adv == NULL || own_addr_type == NULL) {
return -EINVAL;
}
/* Set which local identity address we're advertising with */
id_addr = &bt_dev.id_addr[adv->id];
/* Short-circuit to force NRPA usage */
if (options & BT_LE_ADV_OPT_USE_NRPA) {
if (options & BT_LE_ADV_OPT_USE_IDENTITY) {
LOG_ERR("Can't set both IDENTITY & NRPA");
return -EINVAL;
}
err = bt_id_set_adv_private_addr(adv);
if (err) {
return err;
}
*own_addr_type = BT_ADDR_LE_RANDOM;
return 0;
}
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_DEV_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)) {
scan_enabled = true;
bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE);
}
#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(BT_HCI_LE_SCAN_ENABLE);
}
#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_CLASSIC)
int bt_br_oob_get_local(struct bt_br_oob *oob)
{
CHECKIF(oob == NULL) {
return -EINVAL;
}
bt_addr_copy(&oob->addr, &bt_dev.id_addr[0].a);
return 0;
}
#endif /* CONFIG_BT_CLASSIC */
int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob)
{
struct bt_le_ext_adv *adv = NULL;
int err;
CHECKIF(oob == NULL) {
return -EINVAL;
}
if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
return -EAGAIN;
}
if (id >= CONFIG_BT_ID_MAX) {
return -EINVAL;
}
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
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_CONNECTING_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) &&
CONFIG_BT_ID_MAX > 1 &&
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_force_rpa_timeout();
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;
CHECKIF(adv == NULL || oob == NULL) {
return -EINVAL;
}
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_CONNECTING_SCAN);
if (conn) {
/* Cannot set new RPA while creating
* connections.
*/
bt_conn_unref(conn);
return -EINVAL;
}
}
le_force_rpa_timeout();
}
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)
{
CHECKIF(conn == NULL || tk == NULL) {
return -EINVAL;
}
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)
{
CHECKIF(conn == NULL) {
return -EINVAL;
}
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)
{
CHECKIF(conn == NULL) {
return -EINVAL;
}
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 defined(CONFIG_BT_PRIVACY)
k_work_init_delayable(&bt_dev.rpa_update, rpa_timeout);
#if defined(CONFIG_BT_RPA_SHARING)
for (uint8_t id = 0U; id < ARRAY_SIZE(bt_dev.rpa); id++) {
bt_addr_copy(&bt_dev.rpa[id], BT_ADDR_NONE);
}
#endif
#endif
if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) {
LOG_DBG("No user identity. Trying to set public.");
err = bt_setup_public_id_addr();
if (err) {
LOG_ERR("Unable to set identity address");
return err;
}
}
if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) {
LOG_DBG("No public address. Trying to set static random.");
err = bt_setup_random_id_addr();
if (err) {
LOG_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) {
LOG_ERR("Unable to set random address");
return err;
}
}
return 0;
}