diff --git a/nimble/host/include/host/ble_hs_pvcy.h b/nimble/host/include/host/ble_hs_pvcy.h index aca742051..19087f220 100644 --- a/nimble/host/include/host/ble_hs_pvcy.h +++ b/nimble/host/include/host/ble_hs_pvcy.h @@ -29,12 +29,36 @@ 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 diff --git a/nimble/host/src/ble_hs_id.c b/nimble/host/src/ble_hs_id.c index fc35e93cd..63f750c9e 100644 --- a/nimble/host/src/ble_hs_id.c +++ b/nimble/host/src/ble_hs_id.c @@ -69,6 +69,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 diff --git a/nimble/host/src/ble_hs_id_priv.h b/nimble/host/src/ble_hs_id_priv.h index c031b9511..85260ec48 100644 --- a/nimble/host/src/ble_hs_id_priv.h +++ b/nimble/host/src/ble_hs_id_priv.h @@ -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 } diff --git a/nimble/host/src/ble_hs_pvcy.c b/nimble/host/src/ble_hs_pvcy.c index f6af3df2c..9e92c660f 100644 --- a/nimble/host/src/ble_hs_pvcy.c +++ b/nimble/host/src/ble_hs_pvcy.c @@ -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]; @@ -307,7 +308,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; @@ -315,8 +316,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); } diff --git a/nimble/host/src/ble_hs_resolv.c b/nimble/host/src/ble_hs_resolv.c index 7f2413898..60c77c9b8 100644 --- a/nimble/host/src/ble_hs_resolv.c +++ b/nimble/host/src/ble_hs_resolv.c @@ -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 @@ -305,6 +308,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 +392,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 +423,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(); @@ -595,6 +605,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 * diff --git a/nimble/host/src/ble_hs_resolv_priv.h b/nimble/host/src/ble_hs_resolv_priv.h index 568aa89ab..e76a26a55 100644 --- a/nimble/host/src/ble_hs_resolv_priv.h +++ b/nimble/host/src/ble_hs_resolv_priv.h @@ -61,7 +61,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 +71,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 *