diff --git a/nimble/host/include/host/ble_store.h b/nimble/host/include/host/ble_store.h index a3eca5d23..27b6d7e77 100644 --- a/nimble/host/include/host/ble_store.h +++ b/nimble/host/include/host/ble_store.h @@ -31,7 +31,8 @@ extern "C" { #define BLE_STORE_OBJ_TYPE_PEER_SEC 2 #define BLE_STORE_OBJ_TYPE_CCCD 3 #define BLE_STORE_OBJ_TYPE_PEER_DEV_REC 4 - +#define BLE_STORE_OBJ_TYPE_PEER_ADDR 6 +#define BLE_STORE_OBJ_TYPE_LOCAL_IRK 7 /** Failed to persist record; insufficient storage capacity. */ #define BLE_STORE_EVENT_OVERFLOW 1 @@ -120,6 +121,26 @@ struct ble_store_value_cccd { uint16_t flags; unsigned value_changed:1; }; +struct ble_store_key_rpa_rec{ + ble_addr_t peer_rpa_addr; + uint8_t idx; +}; +struct ble_store_value_rpa_rec{ + ble_addr_t peer_rpa_addr; + ble_addr_t peer_addr; +}; + +struct ble_store_key_local_irk { + ble_addr_t addr; + + uint8_t idx; +}; +struct ble_store_value_local_irk { + ble_addr_t addr; + + uint8_t irk[16]; +}; + /** * Used as a key for store lookups. This union must be accompanied by an @@ -128,6 +149,8 @@ struct ble_store_value_cccd { union ble_store_key { struct ble_store_key_sec sec; struct ble_store_key_cccd cccd; + struct ble_store_key_rpa_rec rpa_rec; + struct ble_store_key_local_irk local_irk; }; /** @@ -137,6 +160,8 @@ union ble_store_key { union ble_store_value { struct ble_store_value_sec sec; struct ble_store_value_cccd cccd; + struct ble_store_value_rpa_rec rpa_rec; + struct ble_store_value_local_irk local_irk; }; struct ble_store_status_event { @@ -272,6 +297,21 @@ void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value); +int ble_store_read_rpa_rec(const struct ble_store_key_rpa_rec *key, + struct ble_store_value_rpa_rec *out_value); +int ble_store_write_rpa_rec(const struct ble_store_value_rpa_rec *value); +int ble_store_delete_rpa_rec(const struct ble_store_key_rpa_rec *key); +void ble_store_key_from_value_rpa_rec(struct ble_store_key_rpa_rec *out_key, + const struct ble_store_value_rpa_rec *value); + +int ble_store_read_local_irk(const struct ble_store_key_local_irk *key, + struct ble_store_value_local_irk *out_value); +int ble_store_write_local_irk(const struct ble_store_value_local_irk *value); +int ble_store_delete_local_irk(const struct ble_store_key_local_irk *key); +void ble_store_key_from_value_local_irk(struct ble_store_key_local_irk *out_key, + const struct ble_store_value_local_irk *value); + + void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, const union ble_store_value *value); diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 546393e49..8831849df 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -5937,8 +5937,14 @@ ble_gap_encryption_initiate(uint16_t conn_handle, int ble_gap_unpair(const ble_addr_t *peer_addr) { +#if NIMBLE_BLE_SM + int rc; + int ltk_rc = 0; + int irk_rc = 0; struct ble_hs_conn *conn; - + union ble_store_value value; + union ble_store_key key; + ble_addr_t *new_addr = (ble_addr_t *) peer_addr; if (!ble_hs_is_enabled()) { return BLE_HS_EDISABLED; } @@ -5956,10 +5962,54 @@ ble_gap_unpair(const ble_addr_t *peer_addr) ble_hs_unlock(); - ble_hs_pvcy_remove_entry(peer_addr->type, - peer_addr->val); + memset(&key,0,sizeof(key)); + key.rpa_rec.peer_rpa_addr = *peer_addr; - return ble_store_util_delete_peer(peer_addr); + rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_ADDR, &key, &value); + + if (!rc) { + new_addr = &(value.rpa_rec.peer_addr); + } + + memset(&key, 0, sizeof(key)); + key.sec.peer_addr = *new_addr; + + rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_SEC, &key, &value); + + // Checking if the device is in ble_store + if (!rc) { + if (value.sec.irk_present) { + // Delete the IRK as it is Distributed + irk_rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type, + key.sec.peer_addr.val); + if (irk_rc != 0) { + BLE_HS_LOG(ERROR, "Error while removing IRK\n"); + } + } + + if (value.sec.ltk_present || value.sec.irk_present) { + // Delete the Peer record from store as LTK is present + ltk_rc = ble_store_util_delete_peer(&key.sec.peer_addr); + if (ltk_rc != 0) { + BLE_HS_LOG(ERROR, "Error while removing LTK\n"); + } + } + } + else { + rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value); + if (!rc) { + ble_store_util_delete_peer(&key.sec.peer_addr); + } + else { + BLE_HS_LOG(ERROR,"No record found for the given address in ble store"); + return rc; + } + } + + return 0; +#else + return BLE_HS_ENOTSUP; +#endif } int diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index b643653ce..0675cea2c 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -525,6 +525,7 @@ static void ble_sm_persist_keys(struct ble_sm_proc *proc) { struct ble_store_value_sec value_sec; + struct ble_store_value_rpa_rec value_rpa_rec; struct ble_hs_conn *conn; ble_addr_t peer_addr; int authenticated; @@ -611,6 +612,9 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) ble_sm_fill_store_value(&peer_addr, authenticated, sc, &proc->peer_keys, &value_sec); ble_store_write_peer_sec(&value_sec); + value_rpa_rec.peer_addr=peer_addr; + value_rpa_rec.peer_rpa_addr=conn->bhc_peer_rpa_addr; + ble_store_write_rpa_rec(&value_rpa_rec); } static int diff --git a/nimble/host/src/ble_store.c b/nimble/host/src/ble_store.c index 22e608947..7e1a05c21 100644 --- a/nimble/host/src/ble_store.c +++ b/nimble/host/src/ble_store.c @@ -306,6 +306,93 @@ ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, out_key->idx = 0; } +int +ble_store_read_rpa_rec(const struct ble_store_key_rpa_rec *key, + struct ble_store_value_rpa_rec *out_value) +{ + union ble_store_value *store_value; + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + store_value = (void *)out_value; + rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_ADDR, store_key, store_value); + return rc; +} + +int +ble_store_write_rpa_rec(const struct ble_store_value_rpa_rec *value) +{ + union ble_store_value *store_value; + int rc; + + store_value = (void *)value; + rc = ble_store_write(BLE_STORE_OBJ_TYPE_PEER_ADDR, store_value); + return rc; +} + +int +ble_store_delete_rpa_rec(const struct ble_store_key_rpa_rec *key) +{ + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + rc = ble_store_delete(BLE_STORE_OBJ_TYPE_PEER_ADDR, store_key); + return rc; +} +void +ble_store_key_from_value_rpa_rec(struct ble_store_key_rpa_rec *out_key, + const struct ble_store_value_rpa_rec *value) +{ + out_key->peer_rpa_addr = value->peer_rpa_addr; + out_key->idx = 0; +} + +int +ble_store_read_local_irk(const struct ble_store_key_local_irk *key, + struct ble_store_value_local_irk *out_value) +{ + union ble_store_value *store_value; + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + store_value = (void *)out_value; + rc = ble_store_read(BLE_STORE_OBJ_TYPE_LOCAL_IRK, store_key, store_value); + return rc; +} + +int +ble_store_write_local_irk(const struct ble_store_value_local_irk *value) +{ + union ble_store_value *store_value; + int rc; + + store_value = (void *)value; + rc = ble_store_write(BLE_STORE_OBJ_TYPE_LOCAL_IRK, store_value); + return rc; +} + +int +ble_store_delete_local_irk(const struct ble_store_key_local_irk *key) +{ + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + rc = ble_store_delete(BLE_STORE_OBJ_TYPE_LOCAL_IRK, store_key); + return rc; +} + +void +ble_store_key_from_value_local_irk(struct ble_store_key_local_irk *out_key, + const struct ble_store_value_local_irk *value) +{ + out_key->addr = value->addr; + out_key->idx = 0; +} + void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, @@ -321,6 +408,12 @@ ble_store_key_from_value(int obj_type, ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd); break; + case BLE_STORE_OBJ_TYPE_PEER_ADDR: + ble_store_key_from_value_rpa_rec(&out_key->rpa_rec, &value->rpa_rec); + break; + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + ble_store_key_from_value_local_irk(&out_key->local_irk, &value->local_irk); + break; default: BLE_HS_DBG_ASSERT(0); break; @@ -350,6 +443,14 @@ ble_store_iterate(int obj_type, key.cccd.peer_addr = *BLE_ADDR_ANY; pidx = &key.cccd.idx; break; + case BLE_STORE_OBJ_TYPE_PEER_ADDR: + key.rpa_rec.peer_rpa_addr = *BLE_ADDR_ANY; + pidx = &key.rpa_rec.idx; + break; + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + key.local_irk.addr = *BLE_ADDR_ANY; + pidx = &key.local_irk.idx; + break; default: BLE_HS_DBG_ASSERT(0); return BLE_HS_EINVAL; @@ -394,6 +495,8 @@ ble_store_clear(void) BLE_STORE_OBJ_TYPE_OUR_SEC, BLE_STORE_OBJ_TYPE_PEER_SEC, BLE_STORE_OBJ_TYPE_CCCD, + BLE_STORE_OBJ_TYPE_PEER_ADDR, + BLE_STORE_OBJ_TYPE_LOCAL_IRK }; union ble_store_key key; int obj_type; diff --git a/nimble/host/src/ble_store_util.c b/nimble/host/src/ble_store_util.c index 73c71d93b..40776d695 100644 --- a/nimble/host/src/ble_store_util.c +++ b/nimble/host/src/ble_store_util.c @@ -136,6 +136,14 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) return rc; } + memset(&key, 0, sizeof key); + key.rpa_rec.peer_rpa_addr = *peer_id_addr; + + rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_PEER_ADDR, &key); + if (rc != 0) { + return rc; + } + #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) struct ble_hs_dev_records *peer_rec = ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val); @@ -255,6 +263,7 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg) switch (event->overflow.obj_type) { case BLE_STORE_OBJ_TYPE_OUR_SEC: case BLE_STORE_OBJ_TYPE_PEER_SEC: + case BLE_STORE_OBJ_TYPE_PEER_ADDR: return ble_gap_unpair_oldest_peer(); case BLE_STORE_OBJ_TYPE_CCCD: /* Try unpairing oldest peer except current peer */ diff --git a/nimble/host/store/config/src/ble_store_config.c b/nimble/host/store/config/src/ble_store_config.c index a2c9aaf27..49cc6f784 100644 --- a/nimble/host/store/config/src/ble_store_config.c +++ b/nimble/host/store/config/src/ble_store_config.c @@ -38,6 +38,14 @@ struct ble_store_value_cccd ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; int ble_store_config_num_cccds; +struct ble_store_value_rpa_rec + ble_store_config_rpa_recs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +int ble_store_config_num_rpa_recs; + +struct ble_store_value_local_irk + ble_store_config_local_irks[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +int ble_store_config_num_local_irks; + /***************************************************************************** * $sec * *****************************************************************************/ @@ -413,6 +421,213 @@ ble_store_config_write_cccd(const struct ble_store_value_cccd *value_cccd) return 0; } +/***************************************************************************** + * $rpa-map * + *****************************************************************************/ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +static int +ble_store_config_find_rpa_rec(const struct ble_store_key_rpa_rec *key){ + struct ble_store_value_rpa_rec *rpa_rec; + int skipped = 0; + int i = 0; + + for(i = 0; i < ble_store_config_num_rpa_recs; i++){ + rpa_rec = ble_store_config_rpa_recs + i; + + if (ble_addr_cmp(&rpa_rec->peer_rpa_addr, &key->peer_rpa_addr) && ble_addr_cmp(&rpa_rec->peer_addr, &key->peer_rpa_addr)) { + continue; + } + if (key->idx > skipped) { + skipped++; + continue; + } + return i; + } + return -1; +} +#endif + +static int +ble_store_config_read_rpa_rec(const struct ble_store_key_rpa_rec *key_rpa_rec,struct ble_store_value_rpa_rec *value_rpa_rec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + int idx; + + idx = ble_store_config_find_rpa_rec(key_rpa_rec); + if (idx == -1) { + return BLE_HS_ENOENT; + } + *value_rpa_rec = ble_store_config_rpa_recs[idx]; + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_config_write_rpa_rec(const struct ble_store_value_rpa_rec *value_rpa_rec){ + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + struct ble_store_key_rpa_rec key_rpa_rec; + int idx; + int rc; + ble_store_key_from_value_rpa_rec(&key_rpa_rec, value_rpa_rec); + idx = ble_store_config_find_rpa_rec(&key_rpa_rec); + + if (idx == -1) { + if (ble_store_config_num_rpa_recs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { + BLE_HS_LOG(DEBUG, "error persisting peer addrr; too many entries (%d)\n", + ble_store_config_num_rpa_recs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_config_num_rpa_recs; + ble_store_config_num_rpa_recs++; + } + ble_store_config_rpa_recs[idx] = *value_rpa_rec; + + rc = ble_store_config_persist_rpa_recs(); + if (rc != 0) { + return rc; + } + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_config_delete_rpa_rec(const struct ble_store_key_rpa_rec *key_rpa_rec) +{ + int idx; + int rc; + + idx = ble_store_config_find_rpa_rec(key_rpa_rec); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_config_delete_obj(ble_store_config_rpa_recs, + sizeof *ble_store_config_rpa_recs, + idx, + &ble_store_config_num_rpa_recs); + if (rc != 0) { + return rc; + } + + rc = ble_store_config_persist_rpa_recs(); + if (rc != 0) { + return rc; + } + + return 0; +} + +/***************************************************************************** + * $local_irk * + *****************************************************************************/ +static int +ble_store_config_find_local_irk(const struct ble_store_key_local_irk *key) +{ + struct ble_store_value_local_irk *local_irk; + int skipped; + int i; + + skipped = 0; + for (i = 0; i < ble_store_config_num_local_irks; i++) { + local_irk = ble_store_config_local_irks + i; + + if (ble_addr_cmp(&key->addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&local_irk->addr, &key->addr)) { + continue; + } + } + + if (key->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} + +static int +ble_store_config_delete_local_irk(const struct ble_store_key_local_irk *key_irk) +{ + int idx; + int rc; + + idx = ble_store_config_find_local_irk(key_irk); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_config_delete_obj(ble_store_config_local_irks, + sizeof *ble_store_config_local_irks, + idx, + &ble_store_config_num_local_irks); + if (rc != 0) { + return rc; + } + + rc = ble_store_config_persist_local_irk(); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_config_read_local_irk(const struct ble_store_key_local_irk *key_irk, + struct ble_store_value_local_irk *value_irk) +{ + int idx; + + idx = ble_store_config_find_local_irk(key_irk); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_irk = ble_store_config_local_irks[idx]; + return 0; +} + +static int +ble_store_config_write_local_irk(const struct ble_store_value_local_irk *value_irk) +{ + struct ble_store_key_local_irk key_irk; + int idx; + int rc; + + ble_store_key_from_value_local_irk(&key_irk, value_irk); + idx = ble_store_config_find_local_irk(&key_irk); + + if (idx == -1) { + if (ble_store_config_num_local_irks >= 1) { + BLE_HS_LOG(DEBUG, "error persisting ead; too many entries (%d)\n", + ble_store_config_num_local_irks); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_config_num_local_irks; + ble_store_config_num_local_irks++; + } + + ble_store_config_local_irks[idx] = *value_irk; + + rc = ble_store_config_persist_local_irk(); + if (rc != 0) { + return rc; + } + + return 0; +} + + /***************************************************************************** * $api * *****************************************************************************/ @@ -455,6 +670,14 @@ ble_store_config_read(int obj_type, const union ble_store_key *key, rc = ble_store_config_read_cccd(&key->cccd, &value->cccd); return rc; + case BLE_STORE_OBJ_TYPE_PEER_ADDR: + rc = ble_store_config_read_rpa_rec(&key->rpa_rec, &value->rpa_rec); + return rc; + + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + rc = ble_store_config_read_local_irk(&key->local_irk, &value->local_irk); + return rc; + default: return BLE_HS_ENOTSUP; } @@ -484,6 +707,14 @@ ble_store_config_write(int obj_type, const union ble_store_value *val) rc = ble_store_config_write_cccd(&val->cccd); return rc; + case BLE_STORE_OBJ_TYPE_PEER_ADDR: + rc = ble_store_config_write_rpa_rec(&val->rpa_rec); + return rc; + + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + rc = ble_store_config_write_local_irk(&val->local_irk); + return rc; + default: return BLE_HS_ENOTSUP; } @@ -507,6 +738,14 @@ ble_store_config_delete(int obj_type, const union ble_store_key *key) rc = ble_store_config_delete_cccd(&key->cccd); return rc; + case BLE_STORE_OBJ_TYPE_PEER_ADDR: + rc = ble_store_config_delete_rpa_rec(&key->rpa_rec); + return rc; + + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + rc = ble_store_config_delete_local_irk(&key->local_irk); + return rc; + default: return BLE_HS_ENOTSUP; } @@ -526,6 +765,7 @@ ble_store_config_init(void) ble_store_config_num_our_secs = 0; ble_store_config_num_peer_secs = 0; ble_store_config_num_cccds = 0; - + ble_store_config_num_rpa_recs = 0; + ble_store_config_num_local_irks=0; ble_store_config_conf_init(); } diff --git a/nimble/host/store/config/src/ble_store_config_conf.c b/nimble/host/store/config/src/ble_store_config_conf.c index e74127ae9..93468cf2a 100644 --- a/nimble/host/store/config/src/ble_store_config_conf.c +++ b/nimble/host/store/config/src/ble_store_config_conf.c @@ -57,6 +57,12 @@ static struct conf_handler ble_store_config_conf_handler = { #define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \ (MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1) +#define BLE_STORE_CONFIG_RPA_REC_ENCODE_SZ \ + BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_rpa_rec)) + +#define BLE_STORE_CONFIG_RPA_REC_SET_ENCODE_SZ \ + (MYNEWT_VAL(BLE_STORE_MAX_BONDS) * BLE_STORE_CONFIG_RPA_REC_ENCODE_SZ + 1) + static void ble_store_config_serialize_arr(const void *arr, int obj_sz, int num_objs, char *out_buf, int buf_sz) @@ -114,6 +120,14 @@ ble_store_config_conf_set(int argc, char **argv, char *val) &ble_store_config_num_cccds); return rc; } + else if (strcmp(argv[0],"rpa_rec") == 0){ + rc = ble_store_config_deserialize_arr( + val, + ble_store_config_rpa_recs, + sizeof *ble_store_config_rpa_recs, + &ble_store_config_num_rpa_recs); + return rc; + } } return OS_ENOENT; } @@ -125,6 +139,7 @@ ble_store_config_conf_export(void (*func)(char *name, char *val), union { char sec[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ]; char cccd[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ]; + char rpa_rec[BLE_STORE_CONFIG_RPA_REC_SET_ENCODE_SZ]; } buf; ble_store_config_serialize_arr(ble_store_config_our_secs, @@ -148,6 +163,12 @@ ble_store_config_conf_export(void (*func)(char *name, char *val), sizeof buf.cccd); func("ble_hs/cccd", buf.cccd); + ble_store_config_serialize_arr(ble_store_config_rpa_recs, + sizeof *ble_store_config_rpa_recs, + ble_store_config_num_rpa_recs, + buf.rpa_rec, + sizeof buf.rpa_rec); + func("ble_hs/rpa_rec", buf.rpa_rec); return 0; } @@ -218,6 +239,22 @@ ble_store_config_persist_cccds(void) return 0; } +int +ble_store_config_persist_rpa_recs(void) +{ + char buf[BLE_STORE_CONFIG_RPA_REC_SET_ENCODE_SZ]; + int rc; + ble_store_config_serialize_arr(ble_store_config_rpa_recs, + sizeof *ble_store_config_rpa_recs, + ble_store_config_num_rpa_recs, + buf, + sizeof buf); + rc = conf_save_one("ble_hs/rpa_rec", buf); + if (rc != 0) { + return BLE_HS_ESTORE_FAIL; + } + return 0; +} void ble_store_config_conf_init(void) { diff --git a/nimble/host/store/config/src/ble_store_config_priv.h b/nimble/host/store/config/src/ble_store_config_priv.h index 61b43c53c..2b4aea4dd 100644 --- a/nimble/host/store/config/src/ble_store_config_priv.h +++ b/nimble/host/store/config/src/ble_store_config_priv.h @@ -36,11 +36,22 @@ extern struct ble_store_value_cccd ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; extern int ble_store_config_num_cccds; +extern struct ble_store_value_rpa_rec + ble_store_config_rpa_recs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +extern int ble_store_config_num_rpa_recs; + +extern struct ble_store_value_local_irk + ble_store_config_local_irks[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +extern int ble_store_config_num_local_irks; + + #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) int ble_store_config_persist_our_secs(void); int ble_store_config_persist_peer_secs(void); int ble_store_config_persist_cccds(void); +int ble_store_config_persist_rpa_recs(void); +int ble_store_config_persist_local_irk(void); void ble_store_config_conf_init(void); #else @@ -48,6 +59,8 @@ void ble_store_config_conf_init(void); static inline int ble_store_config_persist_our_secs(void) { return 0; } static inline int ble_store_config_persist_peer_secs(void) { return 0; } static inline int ble_store_config_persist_cccds(void) { return 0; } +static inline int ble_store_config_persist_rpa_recs(void) { return 0; } +static inline int ble_store_config_persist_local_irk(void) { return 0; } static inline void ble_store_config_conf_init(void) { } #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) diff --git a/nimble/host/store/config/src/ble_store_nvs.c b/nimble/host/store/config/src/ble_store_nvs.c index 2c35f5cf9..4a3df6a2c 100644 --- a/nimble/host/store/config/src/ble_store_nvs.c +++ b/nimble/host/store/config/src/ble_store_nvs.c @@ -41,7 +41,8 @@ #define NIMBLE_NVS_CCCD_SEC_KEY "cccd_sec" #define NIMBLE_NVS_PEER_RECORDS_KEY "p_dev_rec" #define NIMBLE_NVS_NAMESPACE "nimble_bond" - +#define NIMBLE_NVS_RPA_RECORDS_KEY "rpa_rec" +#define NIMBLE_NVS_LOCAL_IRK_KEY "local_irk" static const char *TAG = "NIMBLE_NVS"; /***************************************************************************** @@ -58,7 +59,11 @@ get_nvs_key_string(int obj_type, int index, char *key_string) sprintf(key_string, "%s_%d", NIMBLE_NVS_PEER_SEC_KEY, index); } else if (obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC) { sprintf(key_string, "%s_%d", NIMBLE_NVS_OUR_SEC_KEY, index); - } else { + } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR){ + sprintf(key_string, "%s_%d", NIMBLE_NVS_RPA_RECORDS_KEY, index); + } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { + sprintf(key_string, "%s_%d", NIMBLE_NVS_LOCAL_IRK_KEY, index); + } else { sprintf(key_string, "%s_%d", NIMBLE_NVS_CCCD_SEC_KEY, index); } } @@ -156,6 +161,14 @@ get_nvs_db_value(int obj_type, char *key_string, union ble_store_value *val) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { err = nvs_get_blob(nimble_handle, key_string, &val->cccd, &required_size); + + } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR) { + err = nvs_get_blob(nimble_handle, key_string, &val->rpa_rec, + &required_size); + + } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { + err = nvs_get_blob (nimble_handle, key_string, &val->local_irk, + &required_size); } else { err = nvs_get_blob(nimble_handle, key_string, &val->sec, &required_size); @@ -222,6 +235,15 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value) if (obj_type != BLE_STORE_OBJ_TYPE_CCCD) { err = get_nvs_matching_index(&cur.sec, value, num_value, sizeof(struct ble_store_value_sec)); + + } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR){ + err = get_nvs_matching_index(&cur.rpa_rec,value,num_value, + sizeof(struct ble_store_value_rpa_rec)); + + } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { + err = get_nvs_matching_index(&cur.local_irk, value, num_value, + sizeof(struct ble_store_value_local_irk)); + } else { err = get_nvs_matching_index(&cur.cccd, value, num_value, sizeof(struct ble_store_value_cccd)); @@ -347,6 +369,14 @@ ble_store_nvs_write(int obj_type, const union ble_store_value *val) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { return ble_nvs_write_key_value(key_string, &val->cccd, sizeof(struct ble_store_value_cccd)); + } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR) { + return ble_nvs_write_key_value(key_string, &val->rpa_rec, sizeof(struct + ble_store_value_rpa_rec)); + + } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { + return ble_nvs_write_key_value(key_string, &val->local_irk, sizeof(struct + ble_store_value_local_irk)); + } else { return ble_nvs_write_key_value(key_string, &val->sec, sizeof(struct ble_store_value_sec)); @@ -431,6 +461,19 @@ populate_db_from_nvs(int obj_type, void *dst, int *db_num) memcpy(db_item, &cur.cccd, sizeof(struct ble_store_value_cccd)); db_item += sizeof(struct ble_store_value_cccd); (*db_num)++; + + } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR) { + ESP_LOGD(TAG, "RPA_REC in RAM is filled up from NVS index = %d", i); + memcpy(db_item, &cur.rpa_rec, sizeof(struct ble_store_value_rpa_rec)); + db_item += sizeof(struct ble_store_value_rpa_rec); + (*db_num)++; + + } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { + ESP_LOGD(TAG, "Local IRK in RAM is filled up from NVS index = %d", i); + memcpy(db_item, &cur.local_irk, sizeof(struct ble_store_value_local_irk)); + db_item += sizeof(struct ble_store_value_local_irk); + (*db_num)++; + } else { ESP_LOGD(TAG, "KEY in RAM is filled up from NVS index = %d", i); memcpy(db_item, &cur.sec, sizeof(struct ble_store_value_sec)); @@ -476,6 +519,24 @@ ble_nvs_restore_sec_keys(void) ESP_LOGD(TAG, "ble_store_config_cccds restored %d bonds", ble_store_config_num_cccds); + err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_PEER_ADDR, ble_store_config_rpa_recs, + &ble_store_config_num_rpa_recs); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS operation failed for 'RPA_REC'"); + return err; + } + ESP_LOGD(TAG, "ble_store_config_rpa_recs restored %d bonds", + ble_store_config_num_rpa_recs); + + err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_LOCAL_IRK, ble_store_config_local_irks, + &ble_store_config_num_local_irks); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS operation failed for 'Local IRK'"); + return err; + } + ESP_LOGD(TAG, "ble_store_config_local_irks restored %d irks", + ble_store_config_num_local_irks); + return 0; } @@ -532,6 +593,64 @@ int ble_store_config_persist_cccds(void) return 0; } +int ble_store_config_persist_rpa_recs(void) +{ + int nvs_count, nvs_idx; + union ble_store_value val; + nvs_count = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_PEER_ADDR, 0, NULL, 0); + if (nvs_count == -1) { + ESP_LOGE(TAG, "NVS operation failed while persisting RPA_RECS"); + return BLE_HS_ESTORE_FAIL; + } + if (nvs_count < ble_store_config_num_rpa_recs) { + /* NVS db count less than RAM count, write operation */ + ESP_LOGD(TAG, "Persisting RPA_RECS value in NVS..."); + val.rpa_rec = ble_store_config_rpa_recs[ble_store_config_num_rpa_recs - 1]; + return ble_store_nvs_write(BLE_STORE_OBJ_TYPE_PEER_ADDR, &val); + } else if (nvs_count > ble_store_config_num_rpa_recs) { + /* NVS db count more than RAM count, delete operation */ + nvs_idx = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_PEER_ADDR, 0, + ble_store_config_rpa_recs, ble_store_config_num_rpa_recs); + if (nvs_idx == -1) { + ESP_LOGE(TAG, "NVS delete operation failed for RPA_REC"); + return BLE_HS_ESTORE_FAIL; + } + ESP_LOGD(TAG, "Deleting RPA_REC, nvs idx = %d", nvs_idx); + return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_PEER_ADDR, nvs_idx); + } + return 0; +} + +int ble_store_config_persist_local_irk(void) +{ + int nvs_count, nvs_idx; + union ble_store_value val; + + nvs_count = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_LOCAL_IRK, 0, NULL, 0); + if (nvs_count == -1) { + ESP_LOGE(TAG, "NVS operation failed while persisting EAD"); + return BLE_HS_ESTORE_FAIL; + } + + if (nvs_count < ble_store_config_num_local_irks) { + /* NVS db count less than RAM count, write operation */ + ESP_LOGD(TAG, "Persisting Local IRK value in NVS..."); + val.local_irk = ble_store_config_local_irks[ble_store_config_num_local_irks-1]; + return ble_store_nvs_write(BLE_STORE_OBJ_TYPE_LOCAL_IRK, &val); + } else if (nvs_count > ble_store_config_num_local_irks) { + /* NVS db count more than RAM count, delete operation */ + nvs_idx = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_LOCAL_IRK, 0, + ble_store_config_local_irks, ble_store_config_num_local_irks); + if (nvs_idx == -1) { + ESP_LOGE(TAG, "NVS delete operation failed for Local IRK"); + return BLE_HS_ESTORE_FAIL; + } + ESP_LOGD(TAG, "Deleting Local IRK, nvs idx = %d", nvs_idx); + return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_LOCAL_IRK, nvs_idx); + } + return 0; +} + int ble_store_config_persist_peer_secs(void) { int nvs_count, nvs_idx;