fix(nimble): Handled the deletion of RPA mapping.

This commit is contained in:
Abhinav Kudnar
2024-02-20 12:22:49 +05:30
parent 77c18856ec
commit c18b38fadd
8 changed files with 306 additions and 27 deletions
+23
View File
@@ -37,6 +37,7 @@ extern "C" {
#endif
#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
@@ -145,6 +146,18 @@ struct ble_store_value_ead {
};
#endif
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];
};
struct ble_store_key_rpa_rec{
ble_addr_t peer_rpa_addr;
uint8_t idx;
@@ -165,6 +178,7 @@ union ble_store_key {
struct ble_store_key_ead ead;
#endif
struct ble_store_key_rpa_rec rpa_rec;
struct ble_store_key_local_irk local_irk;
};
/**
@@ -178,6 +192,7 @@ union ble_store_value {
struct ble_store_value_ead ead;
#endif
struct ble_store_value_rpa_rec rpa_rec;
struct ble_store_value_local_irk local_irk;
};
struct ble_store_status_event {
@@ -356,7 +371,15 @@ int ble_store_delete_ead(const struct ble_store_key_ead *key);
void ble_store_key_from_value_ead(struct ble_store_key_ead *out_key,
const struct ble_store_value_ead *value);
#endif
/* irk store*/
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);
/*irk store */
/* rpa mapping*/
int ble_store_read_rpa_rec(const struct ble_store_key_rpa_rec *key,
struct ble_store_value_rpa_rec *out_value);
+12 -4
View File
@@ -6612,6 +6612,7 @@ 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;
@@ -6662,17 +6663,24 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
}
}
if (value.sec.ltk_present) {
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");
BLE_HS_LOG(ERROR, "Error while removing LTK\n");
}
}
}
else {
BLE_HS_LOG(ERROR,"No record found for the given address in ble store");
return rc;
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;
+16 -17
View File
@@ -202,25 +202,26 @@ ble_hs_pvcy_ensure_started(void)
void ble_hs_pvcy_set_default_irk(void)
{
struct ble_store_value_sec value_sec;
struct ble_store_key_sec key_sec;
struct ble_store_value_local_irk value_local_irk;
struct ble_store_key_local_irk key_local_irk;
uint8_t *local_id = NULL;
int rc;
memset(&key_sec, 0, sizeof key_sec);
memset(&value_sec, 0x0, sizeof value_sec);
memset(&key_local_irk, 0, sizeof key_local_irk);
memset(&value_local_irk, 0x0, sizeof value_local_irk);
ble_hs_id_addr(BLE_ADDR_PUBLIC, (const uint8_t **) &local_id, NULL);
/* Create key / value */
memcpy (key_sec.peer_addr.val , local_id, BLE_DEV_ADDR_LEN);
key_sec.peer_addr.type = BLE_ADDR_PUBLIC;
memcpy (key_local_irk.addr.val , local_id, BLE_DEV_ADDR_LEN);
key_local_irk.addr.type = BLE_ADDR_PUBLIC;
/* Read NVS for local IRK */
rc = ble_store_read_our_sec(&key_sec, &value_sec);
if (value_sec.irk_present) {
memcpy(ble_hs_pvcy_default_irk, value_sec.irk, 16);
rc = ble_store_read_local_irk(&key_local_irk, &value_local_irk);
if (!rc) {
memcpy(ble_hs_pvcy_default_irk, value_local_irk.irk, 16);
} else {
/* No entry for local IRK found . Generate one and load in NVS */
memset(ble_hs_pvcy_default_irk, 0x0, 16);
@@ -228,20 +229,18 @@ void ble_hs_pvcy_set_default_irk(void)
if (rc != 0) {
BLE_HS_LOG(ERROR, "Failed to generate local IRK");
return;
return;
}
memset(&value_sec, 0x0, sizeof value_sec);
memset(&value_local_irk, 0x0, sizeof value_local_irk);
memcpy(value_sec.irk, ble_hs_pvcy_default_irk, 16);
memcpy(&value_local_irk.irk, ble_hs_pvcy_default_irk, 16);
value_sec.irk_present = 1;
memcpy(value_local_irk.addr.val, local_id, BLE_DEV_ADDR_LEN);
memcpy(value_sec.peer_addr.val, local_id, BLE_DEV_ADDR_LEN);
value_local_irk.addr.type = BLE_ADDR_PUBLIC;
value_sec.peer_addr.type = BLE_ADDR_PUBLIC;
ble_store_write_our_sec(&value_sec);
ble_store_write_local_irk(&value_local_irk);
}
}
+55
View File
@@ -347,7 +347,52 @@ ble_store_key_from_value_ead(struct ble_store_key_ead *out_key,
out_key->idx = 0;
}
#endif
// local irk
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;
}
//
int
ble_store_read_rpa_rec(const struct ble_store_key_rpa_rec *key,
struct ble_store_value_rpa_rec *out_value)
@@ -413,6 +458,11 @@ ble_store_key_from_value(int obj_type,
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;
@@ -452,6 +502,10 @@ ble_store_iterate(int obj_type,
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;
@@ -497,6 +551,7 @@ ble_store_clear(void)
BLE_STORE_OBJ_TYPE_PEER_SEC,
BLE_STORE_OBJ_TYPE_CCCD,
BLE_STORE_OBJ_TYPE_PEER_ADDR,
BLE_STORE_OBJ_TYPE_LOCAL_IRK,
#if MYNEWT_VAL(ENC_ADV_DATA)
BLE_STORE_OBJ_TYPE_ENC_ADV_DATA,
#endif
+11 -2
View File
@@ -40,7 +40,7 @@ ble_store_util_iter_unique_peer(int obj_type,
#if MYNEWT_VAL(ENC_ADV_DATA)
obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA ||
#endif
obj_type == BLE_STORE_OBJ_TYPE_PEER_SEC);
obj_type == BLE_STORE_OBJ_TYPE_PEER_SEC || obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK);
set = arg;
@@ -139,13 +139,21 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr)
#if MYNEWT_VAL(ENC_ADV_DATA)
memset(&key, 0, sizeof key);
key.ead.peer_addr = *peer_id_addr;
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, &key);
if (rc != 0) {
return rc;
}
#endif
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);
@@ -335,6 +343,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 */
+121 -2
View File
@@ -58,6 +58,10 @@ struct ble_store_value_rpa_rec
#endif
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 *
*****************************************************************************/
@@ -561,6 +565,111 @@ ble_store_config_write_ead(const struct ble_store_value_ead *value_ead)
}
#endif
// 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;
}
/*****************************************************************************
* $rpa-map *
*****************************************************************************/
@@ -575,7 +684,7 @@ ble_store_config_find_rpa_rec(const struct ble_store_key_rpa_rec *key)
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)) {
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) {
@@ -715,7 +824,9 @@ ble_store_config_read(int obj_type, const union ble_store_key *key,
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;
}
@@ -754,6 +865,9 @@ ble_store_config_write(int obj_type, const union ble_store_value *val)
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;
@@ -786,6 +900,10 @@ ble_store_config_delete(int obj_type, const union ble_store_key *key)
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;
@@ -810,5 +928,6 @@ ble_store_config_init(void)
ble_store_config_num_eads = 0;
#endif
ble_store_config_num_rpa_recs = 0;
ble_store_config_num_local_irks=0;
ble_store_config_conf_init();
}
@@ -46,6 +46,10 @@ 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)
@@ -56,6 +60,7 @@ int ble_store_config_persist_cccds(void);
int ble_store_config_persist_eads(void);
#endif
int ble_store_config_persist_rpa_recs(void);
int ble_store_config_persist_local_irk(void);
void ble_store_config_conf_init(void);
#else
@@ -67,6 +72,7 @@ static inline int ble_store_config_persist_cccds(void) { return 0; }
static inline int ble_store_config_persist_eads(void) { return 0; }
#endif
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)
+62 -2
View File
@@ -46,6 +46,7 @@
#define NIMBLE_NVS_EAD_SEC_KEY "ead_sec"
#endif
#define NIMBLE_NVS_LOCAL_IRK_KEY "local_irk"
#define NIMBLE_NVS_RPA_RECORDS_KEY "rpa_rec"
static const char *TAG = "NIMBLE_NVS";
@@ -68,6 +69,9 @@ get_nvs_key_string(int obj_type, int index, char *key_string)
} else if (obj_type == NIMBLE_NVS_EAD_SEC_KEY) {
sprintf(key_string, "%s_%d", NIMBLE_NVS_EAD_SEC_KEY, index);
#endif
} else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) {
sprintf(key_string, "%s_%d", NIMBLE_NVS_LOCAL_IRK_KEY, index);
} else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR){
sprintf(key_string, "%s_%d", NIMBLE_NVS_RPA_RECORDS_KEY, index);
}else {
@@ -177,6 +181,10 @@ get_nvs_db_value(int obj_type, char *key_string, union ble_store_value *val)
err = nvs_get_blob(nimble_handle, key_string, &val->ead,
&required_size);
#endif
} else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) {
err = nvs_get_blob (nimble_handle, key_string, &val->local_irk,
&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);
@@ -252,7 +260,11 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value)
err = get_nvs_matching_index(&cur.sec, value, num_value,
sizeof(struct ble_store_value_ead));
#endif
} else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR){
} 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 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 {
@@ -385,8 +397,12 @@ ble_store_nvs_write(int obj_type, const union ble_store_value *val)
return ble_nvs_write_key_value(key_string, &val->ead, sizeof(struct
ble_store_value_ead));
#endif
} 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 if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR) {
return ble_nvs_write_key_value(key_string, &val->rpa_rec, sizeof(struct
return ble_nvs_write_key_value(key_string, &val->rpa_rec, sizeof(struct
ble_store_value_rpa_rec));
} else {
@@ -480,6 +496,12 @@ populate_db_from_nvs(int obj_type, void *dst, int *db_num)
db_item += sizeof(struct ble_store_value_ead);
(*db_num)++;
#endif
} 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 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));
@@ -540,6 +562,15 @@ ble_nvs_restore_sec_keys(void)
ESP_LOGD(TAG, "ble_store_config_eads restored %d bonds",
ble_store_config_num_eads);
#endif
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);
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) {
@@ -636,6 +667,35 @@ int ble_store_config_persist_eads(void)
return 0;
}
#endif
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_rpa_recs(void)
{