Merge branch 'nimble/repeated_pairing_rpa_fix_nimble-1.1.0' into 'nimble-1.1.0-idf'

NimBLE: Add NRPA, Fix repeated pairing request failure in RPA feature and minor fix in `os_mempool.c` (Backport nimble-1.1.0)

See merge request espressif/esp-nimble!52
This commit is contained in:
Hrishikesh Dhayagude
2020-07-23 13:29:50 +08:00
7 changed files with 172 additions and 27 deletions
+38 -5
View File
@@ -19,6 +19,9 @@
* under the License.
*/
#ifndef H_BLE_HS_PVCY_
#define H_BLE_HS_PVCY_
#include "host/ble_hs.h"
#ifdef __cplusplus
@@ -26,15 +29,45 @@ extern "C" {
#endif
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
/* Called to configure local(own) privacy (RPA) when using host based privacy. In
* Host based privacy as controller is not aware of RPA, we do it via
* 'BLE_ADDR_RANDOM' addr_type route.
#define NIMBLE_HOST_DISABLE_PRIVACY 0x00
#define NIMBLE_HOST_ENABLE_RPA 0x01
#define NIMBLE_HOST_ENABLE_NRPA 0x02
/* Called to configure local(own) privacy (RPA/NRPA) when using Host based privacy.
* In Host based privacy, as controller is not aware of RPA/NRPA address is in use,
* we do it through 'BLE_ADDR_RANDOM (0x01)' addr_type route. This is necessary
* so as to set the private address as random address in controller.
* Remember to configure `BLE_SM_PAIR_KEY_DIST_ID` in our & their
* key distributions for using RPA. For NRPA part of privacy it is not
* necessary to configure key distributions in host, as anyway NRPA is non-resolvable.
* Please call this API once host-controller are synced as we set the private
* (RPA/NRPA) address using host-controller HCI commands.
*
* @param enable RPA when enable is not 0
* disable RPA otherwise
* To give brief information on how to use this feature,
* please refer to following steps while using RPA feature:
*
* 1. Include "host/ble_hs_pvcy.h".
* 2. Set own_addr_type to `BLE_OWN_ADDR_RANDOM`.
* 3. Add `BLE_SM_PAIR_KEY_DIST_ID` to key distribution in
* `ble_hs_cfg.sm_our_key_dist` & `ble_hs_cfg.sm_their_key_dist`.
* 4. Call `ble_hs_pvcy_rpa_config(1)` in Host-Controller sync callback.
*
* In case of NRPA, steps 1, 2 and calling ble_hs_pvcy_rpa_config(2) will
* suffice.
*
* @param enable RPA when param = 1 (NIMBLE_HOST_ENABLE_RPA)
* enable NRPA when param = 2 (NIMBLE_HOST_ENABLE_NRPA)
* disable privacy when param = 0 (NIMBLE_HOST_DISABLE_PRIVACY)
*
* @return return 0 when successful.
* return appropriate error code otherwise
*/
int ble_hs_pvcy_rpa_config(uint8_t enable);
#endif
#ifdef __cplusplus
}
#endif
#endif
+31
View File
@@ -67,6 +67,37 @@ ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr)
}
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
/**
* Sets the device's pseudo Non Resolvable Private Address when 'Host based
* privacy' is in use.
*
* @return 0 on success;
* Appropriate error code if failure.
*/
int
ble_hs_id_set_nrpa_rnd()
{
ble_addr_t nrpa_addr;
int rc;
ble_hs_id_gen_rnd(1, &nrpa_addr);
ble_hs_lock();
/* set the NRPA address as pseudo random address in controller */
rc = ble_hs_hci_util_set_random_addr(nrpa_addr.val);
if (rc != 0) {
goto done;
}
memcpy(ble_hs_id_rnd, nrpa_addr.val, BLE_DEV_ADDR_LEN);
done:
ble_hs_unlock();
return rc;
}
/**
* Sets the device's pseudo RPA address when 'Host based privacy' is in use.
* The address type (RPA) is inferred from the most-significant bits. The
+1
View File
@@ -36,6 +36,7 @@ void ble_hs_id_rnd_reset(void);
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type);
int ble_hs_id_set_pseudo_rnd(const uint8_t *);
int ble_hs_id_set_nrpa_rnd(void);
#endif
#ifdef __cplusplus
}
+10 -2
View File
@@ -22,6 +22,7 @@
#include "stats/stats.h"
#include "ble_hs_priv.h"
#include "ble_hs_resolv_priv.h"
#include "host/ble_hs_pvcy.h"
static uint8_t ble_hs_pvcy_started;
static uint8_t ble_hs_pvcy_irk[16];
@@ -329,7 +330,7 @@ ble_hs_pvcy_rpa_config(uint8_t enable)
{
int rc = 0;
if (enable != 0) {
if (enable != NIMBLE_HOST_DISABLE_PRIVACY) {
rc = ble_hs_pvcy_ensure_started();
if (rc != 0) {
return rc;
@@ -337,8 +338,15 @@ ble_hs_pvcy_rpa_config(uint8_t enable)
ble_hs_resolv_enable(true);
/* Configure NRPA address related flags according to input parameter */
if (enable == NIMBLE_HOST_ENABLE_NRPA) {
ble_hs_resolv_nrpa_enable();
} else {
ble_hs_resolv_nrpa_disable();
}
/* Generate local RPA address and set it in controller */
rc = ble_hs_gen_own_rpa_random();
rc = ble_hs_gen_own_private_rnd();
} else {
ble_hs_resolv_enable(false);
}
+86 -18
View File
@@ -50,6 +50,9 @@ struct ble_hs_resolv_data {
struct ble_npl_callout rpa_timer;
};
/* NRPA bit: Enables NRPA as private address. */
static bool nrpa_pvcy;
/*** APIs for Peer Device Records.
*
* These Peer records are necessary to take care of Peers with RPA address when
@@ -178,6 +181,44 @@ is_rpa_resolvable_by_peer_rec(struct ble_hs_dev_records *p_dev_rec, uint8_t *pee
return false;
}
static void
ble_rpa_replace_id_with_rand_addr(uint8_t *addr_type, uint8_t *peer_addr)
{
struct ble_hs_dev_records *p_dev_rec;
ble_addr_t p_addr = {0};
struct ble_hs_conn *conn = NULL;
p_dev_rec = ble_rpa_find_peer_dev_rec(peer_addr);
if (p_dev_rec != NULL) {
if (memcmp(p_dev_rec->rand_addr, p_dev_rec->identity_addr, BLE_DEV_ADDR_LEN)) {
/* OTA address (before resolving) gets saved in RAND_ADDR when the peer
* record is fetched from resolving list. Replace peer address
* with rand_addr to maintain status quo for new pairing/encryption request. */
p_addr.type = *addr_type;
memcpy(&p_addr.val[0], peer_addr, BLE_DEV_ADDR_LEN);
ble_hs_lock();
conn = ble_hs_conn_find_by_addr(&p_addr);
/* Rewrite the peer address history in ble_hs_conn. Need to take
* this step to avoid taking wrong address during re-pairing
* process */
if (conn != NULL) {
conn->bhc_peer_rpa_addr.type = p_dev_rec->rand_addr_type;
memcpy(&conn->bhc_peer_rpa_addr.val[0], p_dev_rec->rand_addr, BLE_DEV_ADDR_LEN);
conn->bhc_peer_addr.type = p_dev_rec->rand_addr_type;
memcpy(&conn->bhc_peer_addr.val[0], p_dev_rec->rand_addr, BLE_DEV_ADDR_LEN);
BLE_HS_LOG(DEBUG, "\n Replace Identity addr with random addr received at"
" start of the connection\n");
}
ble_hs_unlock();
}
}
return;
}
/* Add peer to peer device records.
*
* @return 0 if added successfully,
@@ -224,6 +265,7 @@ ble_rpa_find_rl_from_peer_records(uint8_t *peer_addr, uint8_t *peer_addr_type)
if (is_rpa_resolvable_by_peer_rec(p_dev_rec, peer_addr)) {
memcpy(p_dev_rec->rand_addr, peer_addr, BLE_DEV_ADDR_LEN);
p_dev_rec->rand_addr_type = *peer_addr_type;
rl = ble_hs_resolv_list_find(p_dev_rec->identity_addr);
if (rl) {
memcpy(peer_addr, p_dev_rec->identity_addr, BLE_DEV_ADDR_LEN);
@@ -274,13 +316,10 @@ ble_rpa_replace_peer_params_with_rl(uint8_t *peer_addr, uint8_t *addr_type,
if (is_rpa) {
ble_hs_log_flat_buf(peer_addr, BLE_DEV_ADDR_LEN);
rl_tmp = ble_hs_resolv_list_find(peer_addr);
BLE_HS_LOG(DEBUG, "\n");
/* Try to find from your peer_device records, if RL doesn't
* exist */
if (rl_tmp == NULL) {
rl_tmp = ble_rpa_find_rl_from_peer_records(peer_addr, addr_type);
}
/* Try to find RL from your peer_device records */
rl_tmp = ble_rpa_find_rl_from_peer_records(peer_addr, addr_type);
}
if (rl != NULL) {
@@ -305,6 +344,10 @@ is_ble_hs_resolv_enabled(void)
bool
ble_host_rpa_enabled(void)
{
if (nrpa_pvcy) {
return false;
}
if (is_ble_hs_resolv_enabled() && ble_hs_pvcy_enabled()) {
return true;
}
@@ -385,12 +428,16 @@ ble_hs_resolv_gen_priv_addr(struct ble_hs_resolv_entry *rl, int local)
addr[2] = ecb.cipher_text[13];
}
/* Called to generate RPA address and this address is set in controller as
* Random address. This is necessary in Host based privacy because controller is unaware of RPA
* address is being used */
/* Called to generate private (RPA/NRPA) address and this address is set in controller as
* Random address. This is necessary in Host based privacy because controller
* is unaware of private address is being used */
int
ble_hs_gen_own_rpa_random(void)
ble_hs_gen_own_private_rnd(void)
{
if (nrpa_pvcy) {
return ble_hs_id_set_nrpa_rnd();
}
struct ble_hs_resolv_entry *rl = &g_ble_hs_resolv_list[0];
ble_hs_resolv_gen_priv_addr(rl, 1);
@@ -412,12 +459,11 @@ ble_hs_get_rpa_local(void)
static void
ble_hs_resolv_rpa_timer_cb(struct ble_npl_event *ev)
{
if (ble_host_rpa_enabled()) {
BLE_HS_LOG(DEBUG, "RPA Timeout; start active adv & scan with new RPA\n");
if (ble_host_rpa_enabled() || (nrpa_pvcy)) {
BLE_HS_LOG(DEBUG, "RPA/NRPA Timeout; start active adv & scan with new Private address \n");
ble_gap_preempt();
/* Generate local RPA */
ble_hs_gen_own_rpa_random();
/* Generate local private address */
ble_hs_gen_own_private_rnd();
ble_npl_callout_reset(&g_ble_hs_resolv_data.rpa_timer,
(int32_t)g_ble_hs_resolv_data.rpa_tmo);
ble_gap_preempt_done();
@@ -561,7 +607,7 @@ ble_hs_resolv_list_add(uint8_t *cmdbuf)
int
ble_hs_resolv_list_rmv(uint8_t addr_type, uint8_t *ident_addr)
{
int position;
int position, rc = BLE_HS_ENOENT;
/* Remove from IRK records */
position = ble_hs_is_on_resolv_list(ident_addr, addr_type);
@@ -573,10 +619,15 @@ ble_hs_resolv_list_rmv(uint8_t addr_type, uint8_t *ident_addr)
ble_hs_resolv_entry));
--g_ble_hs_resolv_data.rl_cnt;
return 0;
rc = 0;
}
return BLE_HS_ENOENT;
/* As we are removing the RL record, it is needed to change
* peer_address to its latest received OTA address, this helps when existing bond at
* peer side is removed */
ble_rpa_replace_id_with_rand_addr(&addr_type, ident_addr);
return rc;
}
/**
@@ -595,6 +646,23 @@ ble_hs_resolv_list_clear_all(void)
return;
}
/**
* Called by host stack to enable NRPA privacy flag for future reference
*/
void
ble_hs_resolv_nrpa_enable(void)
{
nrpa_pvcy = true;
}
/**
* Called by host stack to disable NRPA privacy flag
*/
void
ble_hs_resolv_nrpa_disable(void)
{
nrpa_pvcy = false;
}
/**
* Called to enable or disable address resolution in the host
*
+4 -1
View File
@@ -53,6 +53,7 @@ struct ble_hs_peer_sec {
*/
struct ble_hs_dev_records {
bool rec_used;
uint8_t rand_addr_type;
uint8_t pseudo_addr[BLE_DEV_ADDR_LEN];
uint8_t rand_addr[BLE_DEV_ADDR_LEN];
uint8_t identity_addr[BLE_DEV_ADDR_LEN];
@@ -61,7 +62,7 @@ struct ble_hs_dev_records {
/* Add a device to the resolving list */
int ble_hs_resolv_list_add(uint8_t *cmdbuf);
int ble_hs_gen_own_rpa_random(void);
int ble_hs_gen_own_private_rnd(void);
uint8_t *ble_hs_get_rpa_local(void);
/* Remove a device from the resolving list */
@@ -71,6 +72,8 @@ void ble_hs_resolv_list_clear_all(void);
/* Address resolution enable command */
void ble_hs_resolv_enable(bool);
void ble_hs_resolv_nrpa_enable(void);
void ble_hs_resolv_nrpa_disable(void);
/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */
struct ble_hs_resolv_entry *
+2 -1
View File
@@ -346,7 +346,8 @@ os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
omi->omi_num_blocks = cur->mp_num_blocks;
omi->omi_num_free = cur->mp_num_free;
omi->omi_min_free = cur->mp_min_free;
strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name));
strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name) - 1);
omi->omi_name[sizeof(omi->omi_name) - 1] = '\0';
return (cur);
}