Bluetooth: Add full storage support for multiple identities

Update the storage handling to take into account multiple identities.
We can save a bit of code by using the new bt_id_create() API from
within settings.c.

Also make the treatment of addr & irk parameters to bt_id_create()
consistent, in that NULL is acceptable for both of them.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-07-16 14:39:06 +03:00 committed by Johan Hedberg
commit e70c556dcc
5 changed files with 72 additions and 90 deletions

View file

@ -132,10 +132,11 @@ void bt_id_get(bt_addr_le_t *addrs, size_t *count);
* If an insufficient amount of identities were recovered the app may then
* call bt_id_create() to create new ones.
*
* @param addr Address to use for the new identity. If initialized to
* BT_ADDR_LE_ANY the stack will generate a new static
* @param addr Address to use for the new identity. If NULL or initialized
* to BT_ADDR_LE_ANY the stack will generate a new static
* random address for the identity and copy it to the given
* parameter upon return from this function.
* parameter upon return from this function (in case the
* parameter was non-NULL).
* @param irk Identity Resolving Key (16 bytes) to be used with this
* identity. If set to all zeroes or NULL, the stack will
* generate a random IRK for the identity and copy it back

View file

@ -4193,20 +4193,8 @@ int bt_addr_le_create_static(bt_addr_le_t *addr)
return 0;
}
int bt_set_static_addr(const bt_addr_le_t *addr)
int bt_setup_id_addr(void)
{
if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) {
BT_ERR("Only static random address supported as identity");
return -EINVAL;
}
return set_random_address(&addr->a);
}
static int setup_id_addr(void)
{
int err;
#if defined(CONFIG_BT_HCI_VS_EXT)
/* Check for VS_Read_Static_Addresses support. Only read the
* addresses if the user has not already configured one or
@ -4215,7 +4203,7 @@ static int setup_id_addr(void)
if (!bt_dev.id_count && (bt_dev.vs_commands[1] & BIT(0))) {
struct bt_hci_rp_vs_read_static_addrs *rp;
struct net_buf *rsp;
int i;
int err, i;
err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS,
NULL, &rsp);
@ -4234,7 +4222,7 @@ static int setup_id_addr(void)
net_buf_unref(rsp);
if (bt_dev.id_count) {
return bt_set_static_addr(&bt_dev.id_addr[0]);
return set_random_address(&bt_dev.id_addr[0].a);
}
BT_WARN("No static addresses stored in controller");
@ -4245,21 +4233,7 @@ static int setup_id_addr(void)
generate:
#endif
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Expecing identity addr to be handled by settings");
return 0;
} else {
err = bt_addr_le_create_static(&bt_dev.id_addr[0]);
if (err) {
return err;
}
bt_dev.id_count = 1;
BT_WARN("Using temporary static random address %s",
bt_addr_str(&bt_dev.id_addr[0].a));
return bt_set_static_addr(&bt_dev.id_addr[0]);
}
return bt_id_create(NULL, NULL);
}
#if defined(CONFIG_BT_DEBUG)
@ -4454,17 +4428,14 @@ static int hci_init(void)
hci_vs_init();
#endif
if (!bt_addr_le_cmp(&bt_dev.id_addr[0], BT_ADDR_LE_ANY) ||
!bt_addr_le_cmp(&bt_dev.id_addr[0], BT_ADDR_LE_NONE)) {
if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) {
BT_DBG("No public address. Trying to set static random.");
err = setup_id_addr();
err = bt_setup_id_addr();
if (err) {
BT_ERR("Unable to set identity address");
return err;
}
}
if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_dev_show_info();
}
@ -4620,6 +4591,12 @@ static int bt_init(void)
bt_le_scan_update(false);
}
if (bt_dev.id_count > 0) {
atomic_set_bit(bt_dev.flags, BT_DEV_PRESET_ID);
} else if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_WARN("No ID address. Expecting one to come from storage.");
}
return 0;
}
@ -4863,7 +4840,8 @@ int bt_id_create(bt_addr_le_t *addr, u8_t *irk)
{
int new_id;
if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) {
if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY) &&
(addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a))) {
BT_ERR("Only static random identity address supported");
return -EINVAL;
}
@ -4877,20 +4855,22 @@ int bt_id_create(bt_addr_le_t *addr, u8_t *irk)
}
new_id = bt_dev.id_count++;
if (new_id == BT_ID_DEFAULT) {
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);
}
if (bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
bt_addr_le_copy(&bt_dev.id_addr[new_id], addr);
} else {
bt_addr_le_create_static(&bt_dev.id_addr[new_id]);
bt_addr_le_copy(addr, &bt_dev.id_addr[new_id]);
if (addr) {
bt_addr_le_copy(addr, &bt_dev.id_addr[new_id]);
}
}
#if defined(CONFIG_BT_PRIVACY)
if (atomic_test_bit(bt_dev.flags, BT_DEV_READY) ||
new_id != BT_ID_DEFAULT) {
if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
u8_t zero_irk[16] = { 0 };
if (irk && memcmp(irk, zero_irk, 16)) {
@ -4903,6 +4883,14 @@ int bt_id_create(bt_addr_le_t *addr, u8_t *irk)
}
}
#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();
}
return new_id;
}

View file

@ -30,6 +30,7 @@ enum {
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,
@ -58,6 +59,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))
struct bt_dev_le {
@ -193,6 +195,6 @@ struct bt_keys;
int bt_id_add(struct bt_keys *keys);
int bt_id_del(struct bt_keys *keys);
int bt_set_static_addr(const bt_addr_le_t *addr);
int bt_setup_id_addr(void);
void bt_dev_show_info(void);

View file

@ -108,6 +108,12 @@ static int set(int argc, char **argv, char *val)
}
if (!strcmp(argv[0], "id")) {
/* Any previously provided identities supersede flash */
if (atomic_test_bit(bt_dev.flags, BT_DEV_PRESET_ID)) {
BT_WARN("Ignoring identities stored in flash");
return 0;
}
len = sizeof(bt_dev.id_addr);
settings_bytes_from_str(val, &bt_dev.id_addr, &len);
if (len < sizeof(bt_dev.id_addr[0])) {
@ -156,25 +162,21 @@ static int set(int argc, char **argv, char *val)
return 0;
}
static void generate_static_addr(void)
#if defined(CONFIG_BT_PRIVACY)
#define ID_SIZE_MAX sizeof(bt_dev.irk)
#else
#define ID_SIZE_MAX sizeof(bt_dev.id_addr)
#endif
#define ID_DATA_LEN(array) (bt_dev.id_count * sizeof(array[0]))
static void save_id(struct k_work *work)
{
char buf[BT_SETTINGS_SIZE(sizeof(bt_dev.id_addr))];
char buf[BT_SETTINGS_SIZE(ID_SIZE_MAX)];
char *str;
BT_DBG("Generating new static random address");
if (bt_addr_le_create_static(&bt_dev.id_addr[0])) {
BT_ERR("Failed to generate static addr");
return;
}
bt_dev.id_count = 1;
bt_set_static_addr(&bt_dev.id_addr[0]);
BT_DBG("New ID Addr: %s", bt_addr_le_str(&bt_dev.id_addr[0]));
str = settings_str_from_bytes(&bt_dev.id_addr[0],
sizeof(bt_dev.id_addr[0]),
str = settings_str_from_bytes(&bt_dev.id_addr,
ID_DATA_LEN(bt_dev.id_addr),
buf, sizeof(buf));
if (!str) {
BT_ERR("Unable to encode ID Addr as value");
@ -183,24 +185,10 @@ static void generate_static_addr(void)
BT_DBG("Saving ID addr as value %s", str);
settings_save_one("bt/id", str);
}
#if defined(CONFIG_BT_PRIVACY)
static void generate_irk(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(bt_dev.irk))];
char *str;
BT_DBG("Generating new IRK");
if (bt_rand(bt_dev.irk, sizeof(bt_dev.irk))) {
BT_ERR("Failed to generate IRK");
return;
}
BT_DBG("New local IRK: %s", bt_hex(bt_dev.irk, 16));
str = settings_str_from_bytes(bt_dev.irk, 16, buf, sizeof(buf));
str = settings_str_from_bytes(bt_dev.irk, ID_DATA_LEN(bt_dev.irk),
buf, sizeof(buf));
if (!str) {
BT_ERR("Unable to encode IRK as value");
return;
@ -208,8 +196,15 @@ static void generate_irk(void)
BT_DBG("Saving IRK as value %s", str);
settings_save_one("bt/irk", str);
#endif
}
K_WORK_DEFINE(save_id_work, save_id);
void bt_settings_save_id(void)
{
k_work_submit(&save_id_work);
}
#endif /* CONFIG_BT_PRIVACY */
static int commit(void)
{
@ -217,26 +212,20 @@ static int commit(void)
BT_DBG("");
if (!bt_addr_le_cmp(&bt_dev.id_addr[0], BT_ADDR_LE_ANY) ||
!bt_addr_le_cmp(&bt_dev.id_addr[0], BT_ADDR_LE_NONE)) {
generate_static_addr();
}
#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
if (bt_dev.name[0] == '\0') {
bt_set_name(CONFIG_BT_DEVICE_NAME);
}
#endif
if (!bt_dev.id_count) {
int err;
#if defined(CONFIG_BT_PRIVACY)
{
u8_t zero[16] = { 0 };
if (!memcmp(bt_dev.irk, zero, 16)) {
generate_irk();
err = bt_setup_id_addr();
if (err) {
BT_ERR("Unable to setup an identity address");
return err;
}
}
#endif /* CONFIG_BT_PRIVACY */
for (h = _bt_settings_start; h < _bt_settings_end; h++) {
if (h->commit) {

View file

@ -31,4 +31,6 @@ void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
bt_addr_le_t *addr, const char *key);
int bt_settings_decode_key(char *key, bt_addr_le_t *addr);
void bt_settings_save_id(void);
int bt_settings_init(void);