mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-26 20:00:02 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user