Bluetooth: Host: Fix issues with host IRK handling
Fix multiple issues related to the way the host handles Identity Information related to privacy 1. If the controller provided a public address the IRK for this identity would be randomly generated but not stored persistenly. 2. Fix the handling of the above issue which was fixed for the random address but would initiate settings save ID on every boot. 3. Fix the host not using the Vendor Specific HCI commands related to retrieving the Identity Root (IR) from the controller and using the key diversified function d1 to generate an IRK as specified in the BT Core spec. Make sure that a Host generated ID is only saved when it is first generated. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
091ebf905d
commit
a34d4afe7d
6 changed files with 210 additions and 94 deletions
|
@ -2265,22 +2265,38 @@ int hci_vendor_cmd_handle_common(u16_t ocf, struct net_buf *cmd,
|
|||
#endif
|
||||
|
||||
#if !defined(CONFIG_BT_HCI_VS_EXT)
|
||||
uint8_t bt_read_static_addr(bt_addr_le_t *addr)
|
||||
uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr *addr)
|
||||
{
|
||||
#if defined(CONFIG_SOC_FAMILY_NRF)
|
||||
if (((NRF_FICR->DEVICEADDR[0] != UINT32_MAX) ||
|
||||
((NRF_FICR->DEVICEADDR[1] & UINT16_MAX) != UINT16_MAX)) &&
|
||||
(NRF_FICR->DEVICEADDRTYPE & 0x01)) {
|
||||
sys_put_le32(NRF_FICR->DEVICEADDR[0], &addr->a.val[0]);
|
||||
sys_put_le16(NRF_FICR->DEVICEADDR[1], &addr->a.val[4]);
|
||||
sys_put_le32(NRF_FICR->DEVICEADDR[0], &addr->bdaddr.val[0]);
|
||||
sys_put_le16(NRF_FICR->DEVICEADDR[1], &addr->bdaddr.val[4]);
|
||||
|
||||
/* The FICR value is a just a random number, with no knowledge
|
||||
* of the Bluetooth Specification requirements for random
|
||||
* static addresses.
|
||||
*/
|
||||
BT_ADDR_SET_STATIC(&addr->a);
|
||||
BT_ADDR_SET_STATIC(&addr->bdaddr);
|
||||
|
||||
/* If no public address is provided and a static address is
|
||||
* available, then it is recommended to return an identity root
|
||||
* key (if available) from this command.
|
||||
*/
|
||||
if ((NRF_FICR->IR[0] != UINT32_MAX) &&
|
||||
(NRF_FICR->IR[1] != UINT32_MAX) &&
|
||||
(NRF_FICR->IR[2] != UINT32_MAX) &&
|
||||
(NRF_FICR->IR[3] != UINT32_MAX)) {
|
||||
sys_put_le32(NRF_FICR->IR[0], &addr->ir[0]);
|
||||
sys_put_le32(NRF_FICR->IR[1], &addr->ir[4]);
|
||||
sys_put_le32(NRF_FICR->IR[2], &addr->ir[8]);
|
||||
sys_put_le32(NRF_FICR->IR[3], &addr->ir[12]);
|
||||
} else {
|
||||
/* Mark IR as invalid */
|
||||
(void)memset(addr->ir, 0x00, sizeof(addr->ir));
|
||||
}
|
||||
|
||||
addr->type = BT_ADDR_LE_RANDOM;
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_SOC_FAMILY_NRF */
|
||||
|
|
|
@ -3959,23 +3959,6 @@ static void read_local_ver_complete(struct net_buf *buf)
|
|||
bt_dev.manufacturer = sys_le16_to_cpu(rp->manufacturer);
|
||||
}
|
||||
|
||||
static void read_bdaddr_complete(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_rp_read_bd_addr *rp = (void *)buf->data;
|
||||
|
||||
BT_DBG("status 0x%02x", rp->status);
|
||||
|
||||
if (!bt_addr_cmp(&rp->bdaddr, BT_ADDR_ANY) ||
|
||||
!bt_addr_cmp(&rp->bdaddr, BT_ADDR_NONE)) {
|
||||
BT_DBG("Controller has no public address");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_addr_copy(&bt_dev.id_addr[0].a, &rp->bdaddr);
|
||||
bt_dev.id_addr[0].type = BT_ADDR_LE_PUBLIC;
|
||||
bt_dev.id_count = 1U;
|
||||
}
|
||||
|
||||
static void read_le_features_complete(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_rp_le_read_local_features *rp = (void *)buf->data;
|
||||
|
@ -4120,16 +4103,6 @@ static int common_init(void)
|
|||
read_local_ver_complete(rsp);
|
||||
net_buf_unref(rsp);
|
||||
|
||||
/* Read Bluetooth Address */
|
||||
if (!atomic_test_bit(bt_dev.flags, BT_DEV_USER_ID_ADDR)) {
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
read_bdaddr_complete(rsp);
|
||||
net_buf_unref(rsp);
|
||||
}
|
||||
|
||||
/* Read Local Supported Commands */
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_SUPPORTED_COMMANDS, NULL,
|
||||
&rsp);
|
||||
|
@ -4654,6 +4627,35 @@ int bt_addr_le_create_static(bt_addr_le_t *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u8_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(u8_t ver)
|
||||
{
|
||||
|
@ -4754,16 +4756,18 @@ static void hci_vs_init(void)
|
|||
int err;
|
||||
|
||||
/* If heuristics is enabled, try to guess HCI VS support by looking
|
||||
* at the HCI version and identity address. We haven't tried to set
|
||||
* a static random address yet at this point, so the identity will
|
||||
* either be zeroes or a valid public address.
|
||||
* at the HCI version and identity address. We haven't set any addresses
|
||||
* at this point. So we need to read the public address.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
|
||||
(bt_dev.hci_version < BT_HCI_VERSION_5_0 ||
|
||||
(!atomic_test_bit(bt_dev.flags, BT_DEV_USER_ID_ADDR) &&
|
||||
bt_addr_le_cmp(&bt_dev.id_addr[0], BT_ADDR_LE_ANY)))) {
|
||||
BT_WARN("Controller doesn't seem to support Zephyr vendor HCI");
|
||||
return;
|
||||
if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT)) {
|
||||
bt_addr_le_t addr;
|
||||
|
||||
if ((bt_dev.hci_version < BT_HCI_VERSION_5_0) ||
|
||||
bt_read_public_addr(&addr)) {
|
||||
BT_WARN("Controller doesn't seem to support "
|
||||
"Zephyr vendor HCI");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_VERSION_INFO, NULL, &rsp);
|
||||
|
@ -4845,10 +4849,16 @@ 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_id_addr();
|
||||
|
||||
err = bt_setup_random_id_addr();
|
||||
if (err) {
|
||||
BT_ERR("Unable to set identity address");
|
||||
return err;
|
||||
|
@ -4955,26 +4965,6 @@ int bt_hci_driver_register(const struct bt_hci_driver *drv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
static int irk_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Expecting settings to handle local IRK");
|
||||
} else {
|
||||
int err;
|
||||
|
||||
err = bt_rand(&bt_dev.irk[0], 16);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
BT_WARN("Using temporary IRK");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_PRIVACY */
|
||||
|
||||
void bt_finalize_init(void)
|
||||
{
|
||||
atomic_set_bit(bt_dev.flags, BT_DEV_READY);
|
||||
|
@ -5003,11 +4993,6 @@ static int bt_init(void)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
err = irk_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
k_delayed_work_init(&bt_dev.rpa_update, rpa_timeout);
|
||||
#endif
|
||||
|
||||
|
@ -5339,11 +5324,6 @@ int bt_id_create(bt_addr_le_t *addr, u8_t *irk)
|
|||
}
|
||||
|
||||
new_id = bt_dev.id_count++;
|
||||
if (new_id == BT_ID_DEFAULT &&
|
||||
!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
|
||||
atomic_set_bit(bt_dev.flags, BT_DEV_USER_ID_ADDR);
|
||||
}
|
||||
|
||||
id_create(new_id, addr, irk);
|
||||
|
||||
return new_id;
|
||||
|
@ -5432,13 +5412,71 @@ int bt_id_delete(u8_t id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
static void bt_read_identity_root(u8_t *ir)
|
||||
{
|
||||
/* Invalid IR */
|
||||
memset(ir, 0, 16);
|
||||
|
||||
#if defined(CONFIG_BT_HCI_VS_EXT)
|
||||
static uint8_t bt_read_static_addr(bt_addr_le_t *addr)
|
||||
struct bt_hci_rp_vs_read_key_hierarchy_roots *rp;
|
||||
struct net_buf *rsp;
|
||||
int err;
|
||||
|
||||
if (!(bt_dev.vs_commands[1] & BIT(1))) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
u8_t *irk = NULL;
|
||||
|
||||
bt_dev.id_count = bt_read_public_addr(&addr);
|
||||
|
||||
if (!bt_dev.id_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
u8_t ir_irk[16];
|
||||
u8_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)
|
||||
static uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr *addrs)
|
||||
{
|
||||
struct bt_hci_rp_vs_read_static_addrs *rp;
|
||||
struct net_buf *rsp;
|
||||
int err, i;
|
||||
u8_t cnt;
|
||||
|
||||
if (!(bt_dev.vs_commands[1] & BIT(0))) {
|
||||
BT_WARN("Read Static Addresses command not available");
|
||||
return 0;
|
||||
|
@ -5449,44 +5487,66 @@ static uint8_t bt_read_static_addr(bt_addr_le_t *addr)
|
|||
BT_WARN("Failed to read static addresses");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rp = (void *)rsp->data;
|
||||
cnt = MIN(rp->num_addrs, CONFIG_BT_ID_MAX);
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
addr[i].type = BT_ADDR_LE_RANDOM;
|
||||
bt_addr_copy(&addr[i].a, &rp->a[i].bdaddr);
|
||||
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;
|
||||
}
|
||||
#elif defined(CONFIG_BT_CTLR)
|
||||
uint8_t bt_read_static_addr(bt_addr_le_t *addr);
|
||||
uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr *addrs);
|
||||
#endif /* CONFIG_BT_HCI_VS_EXT */
|
||||
|
||||
int bt_setup_id_addr(void)
|
||||
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) {
|
||||
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
|
||||
struct bt_hci_vs_static_addr addrs[CONFIG_BT_ID_MAX];
|
||||
|
||||
bt_dev.id_count = bt_read_static_addr(addrs);
|
||||
if (bt_dev.id_count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bt_dev.id_count; i++) {
|
||||
id_create(i, &addrs[i], NULL);
|
||||
if (bt_dev.id_count) {
|
||||
for (u8_t i = 0; i < bt_dev.id_count; i++) {
|
||||
bt_addr_le_t addr;
|
||||
u8_t *irk = NULL;
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
u8_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 set_random_address(&bt_dev.id_addr[0].a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ enum {
|
|||
BT_DEV_ENABLE,
|
||||
BT_DEV_READY,
|
||||
BT_DEV_PRESET_ID,
|
||||
BT_DEV_USER_ID_ADDR,
|
||||
BT_DEV_HAS_PUB_KEY,
|
||||
BT_DEV_PUB_KEY_BUSY,
|
||||
|
||||
|
@ -48,6 +47,7 @@ enum {
|
|||
BT_DEV_RPA_VALID,
|
||||
|
||||
BT_DEV_ID_PENDING,
|
||||
BT_DEV_STORE_ID,
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
BT_DEV_ISCAN,
|
||||
|
@ -61,8 +61,7 @@ enum {
|
|||
|
||||
/* Flags which should not be cleared upon HCI_Reset */
|
||||
#define BT_DEV_PERSISTENT_FLAGS (BIT(BT_DEV_ENABLE) | \
|
||||
BIT(BT_DEV_PRESET_ID) | \
|
||||
BIT(BT_DEV_USER_ID_ADDR))
|
||||
BIT(BT_DEV_PRESET_ID))
|
||||
|
||||
struct bt_dev_le {
|
||||
/* LE features */
|
||||
|
@ -199,7 +198,9 @@ struct bt_keys;
|
|||
void bt_id_add(struct bt_keys *keys);
|
||||
void bt_id_del(struct bt_keys *keys);
|
||||
|
||||
int bt_setup_id_addr(void);
|
||||
int bt_setup_random_id_addr(void);
|
||||
void bt_setup_public_id_addr(void);
|
||||
|
||||
void bt_finalize_init(void);
|
||||
|
||||
int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
|
||||
|
|
|
@ -238,26 +238,32 @@ static int commit(void)
|
|||
bt_set_name(CONFIG_BT_DEVICE_NAME);
|
||||
}
|
||||
#endif
|
||||
if (!bt_dev.id_count) {
|
||||
bt_setup_public_id_addr();
|
||||
}
|
||||
|
||||
if (!bt_dev.id_count) {
|
||||
int err;
|
||||
|
||||
err = bt_setup_id_addr();
|
||||
err = bt_setup_random_id_addr();
|
||||
if (err) {
|
||||
BT_ERR("Unable to setup an identity address");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that the identities created by bt_id_create after
|
||||
* bt_enable is saved to persistent storage. */
|
||||
if (!atomic_test_bit(bt_dev.flags, BT_DEV_PRESET_ID)) {
|
||||
bt_settings_save_id();
|
||||
}
|
||||
|
||||
if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
|
||||
bt_finalize_init();
|
||||
}
|
||||
|
||||
/* If any part of the Identity Information of the device has been
|
||||
* generated this Identity needs to be saved persistently.
|
||||
*/
|
||||
if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_STORE_ID)) {
|
||||
BT_DBG("Storing Identity Information");
|
||||
bt_settings_save_id();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -463,6 +463,25 @@ static int bt_smp_aes_cmac(const u8_t *key, const u8_t *in, size_t len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int smp_d1(const u8_t *key, u16_t d, u16_t r, u8_t res[16])
|
||||
{
|
||||
int err;
|
||||
|
||||
BT_DBG("key %s d %u r %u", bt_hex(key, 16), d, r);
|
||||
|
||||
sys_put_le16(d, &res[0]);
|
||||
sys_put_le16(r, &res[2]);
|
||||
memset(&res[4], 0, 16 - 4);
|
||||
|
||||
err = bt_encrypt_le(key, res, res);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
BT_DBG("res %s", bt_hex(res, 16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smp_f4(const u8_t *u, const u8_t *v, const u8_t *x,
|
||||
u8_t z, u8_t res[16])
|
||||
{
|
||||
|
@ -4372,6 +4391,17 @@ int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
|
|||
}
|
||||
#endif /* CONFIG_BT_SIGNING */
|
||||
|
||||
int bt_smp_irk_get(u8_t *ir, u8_t *irk)
|
||||
{
|
||||
u8_t invalid_ir[16] = { 0 };
|
||||
|
||||
if (!memcmp(ir, invalid_ir, 16)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return smp_d1(ir, 1, 0, irk);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP_SELFTEST)
|
||||
/* Test vectors are taken from RFC 4493
|
||||
* https://tools.ietf.org/html/rfc4493
|
||||
|
|
|
@ -163,3 +163,6 @@ int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf);
|
|||
* @return 0 in success, error code otherwise
|
||||
*/
|
||||
int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf);
|
||||
|
||||
/** Generate IRK from Identity Root (IR) */
|
||||
int bt_smp_irk_get(u8_t *ir, u8_t *irk);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue