mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-17 19:07:23 +00:00
nimble/ll: Refactor RPA handling in resolving code
- peer and local are always generated when peer is added to resolved list - users get current RPA when needed - RPAs are re-generated only from RPA timer
This commit is contained in:
@@ -33,13 +33,13 @@ extern "C" {
|
|||||||
struct ble_ll_resolv_entry
|
struct ble_ll_resolv_entry
|
||||||
{
|
{
|
||||||
uint8_t rl_addr_type;
|
uint8_t rl_addr_type;
|
||||||
uint8_t rl_local_rpa_set;
|
|
||||||
uint8_t rl_reserved;
|
uint8_t rl_reserved;
|
||||||
uint8_t rl_priv_mode;
|
uint8_t rl_priv_mode;
|
||||||
uint8_t rl_local_irk[16];
|
uint8_t rl_local_irk[16];
|
||||||
uint8_t rl_peer_irk[16];
|
uint8_t rl_peer_irk[16];
|
||||||
uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
|
uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
|
||||||
uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN];
|
uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN];
|
||||||
|
uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[];
|
extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[];
|
||||||
@@ -76,7 +76,7 @@ uint8_t ble_ll_resolv_enabled(void);
|
|||||||
/* Reset private address resolution */
|
/* Reset private address resolution */
|
||||||
void ble_ll_resolv_list_reset(void);
|
void ble_ll_resolv_list_reset(void);
|
||||||
|
|
||||||
void ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local,
|
void ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local,
|
||||||
uint8_t *addr);
|
uint8_t *addr);
|
||||||
|
|
||||||
/* Generate a resolvable private address. */
|
/* Generate a resolvable private address. */
|
||||||
|
|||||||
@@ -2753,7 +2753,7 @@ ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type,
|
|||||||
*/
|
*/
|
||||||
if (rl) {
|
if (rl) {
|
||||||
hdr |= BLE_ADV_PDU_HDR_TXADD_RAND;
|
hdr |= BLE_ADV_PDU_HDR_TXADD_RAND;
|
||||||
ble_ll_resolv_gen_priv_addr(rl, 1, dptr);
|
ble_ll_resolv_get_priv_addr(rl, 1, dptr);
|
||||||
addr = NULL;
|
addr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,11 +72,68 @@ ble_ll_resolv_list_chg_allowed(void)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to generate a resolvable private address in rl structure
|
||||||
|
*
|
||||||
|
* @param rl
|
||||||
|
* @param local
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local)
|
||||||
|
{
|
||||||
|
uint8_t *irk;
|
||||||
|
uint8_t *prand;
|
||||||
|
uint32_t *irk32;
|
||||||
|
uint32_t *key32;
|
||||||
|
uint32_t *pt32;
|
||||||
|
struct ble_encryption_block ecb;
|
||||||
|
uint8_t *addr;
|
||||||
|
|
||||||
|
assert(rl != NULL);
|
||||||
|
|
||||||
|
if (local) {
|
||||||
|
addr = rl->rl_local_rpa;
|
||||||
|
irk = rl->rl_local_irk;
|
||||||
|
} else {
|
||||||
|
addr = rl->rl_peer_rpa;
|
||||||
|
irk = rl->rl_peer_irk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get prand */
|
||||||
|
prand = addr + 3;
|
||||||
|
ble_ll_rand_prand_get(prand);
|
||||||
|
|
||||||
|
/* Calculate hash, hash = ah(local IRK, prand) */
|
||||||
|
|
||||||
|
irk32 = (uint32_t *)irk;
|
||||||
|
key32 = (uint32_t *)&ecb.key[0];
|
||||||
|
key32[0] = irk32[0];
|
||||||
|
key32[1] = irk32[1];
|
||||||
|
key32[2] = irk32[2];
|
||||||
|
key32[3] = irk32[3];
|
||||||
|
pt32 = (uint32_t *)&ecb.plain_text[0];
|
||||||
|
pt32[0] = 0;
|
||||||
|
pt32[1] = 0;
|
||||||
|
pt32[2] = 0;
|
||||||
|
ecb.plain_text[12] = 0;
|
||||||
|
ecb.plain_text[13] = prand[2];
|
||||||
|
ecb.plain_text[14] = prand[1];
|
||||||
|
ecb.plain_text[15] = prand[0];
|
||||||
|
|
||||||
|
/* Calculate hash */
|
||||||
|
ble_hw_encrypt_block(&ecb);
|
||||||
|
|
||||||
|
addr[0] = ecb.cipher_text[15];
|
||||||
|
addr[1] = ecb.cipher_text[14];
|
||||||
|
addr[2] = ecb.cipher_text[13];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the Resolvable private address timer expires. This timer
|
* Called when the Resolvable private address timer expires. This timer
|
||||||
* is used to regenerate local RPA's in the resolving list.
|
* is used to regenerate local and peers RPA's in the resolving list.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev)
|
ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -86,9 +143,11 @@ ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev)
|
|||||||
rl = &g_ble_ll_resolv_list[0];
|
rl = &g_ble_ll_resolv_list[0];
|
||||||
for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
|
for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
|
||||||
OS_ENTER_CRITICAL(sr);
|
OS_ENTER_CRITICAL(sr);
|
||||||
rl->rl_local_rpa_set = 0;
|
ble_ll_resolv_gen_priv_addr(rl, 1);
|
||||||
ble_ll_resolv_gen_priv_addr(rl, 1, rl->rl_local_rpa);
|
OS_EXIT_CRITICAL(sr);
|
||||||
rl->rl_local_rpa_set = 1;
|
|
||||||
|
OS_ENTER_CRITICAL(sr);
|
||||||
|
ble_ll_resolv_gen_priv_addr(rl, 0);
|
||||||
OS_EXIT_CRITICAL(sr);
|
OS_EXIT_CRITICAL(sr);
|
||||||
++rl;
|
++rl;
|
||||||
}
|
}
|
||||||
@@ -237,30 +296,37 @@ ble_ll_resolv_list_add(uint8_t *cmdbuf)
|
|||||||
addr_type = cmdbuf[0];
|
addr_type = cmdbuf[0];
|
||||||
ident_addr = cmdbuf + 1;
|
ident_addr = cmdbuf + 1;
|
||||||
|
|
||||||
rc = BLE_ERR_SUCCESS;
|
/* spec is not clear on how to handle this but make sure host is aware
|
||||||
if (!ble_ll_is_on_resolv_list(ident_addr, addr_type)) {
|
* that new keys are not used in that case
|
||||||
rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt];
|
*/
|
||||||
rl->rl_addr_type = addr_type;
|
if (ble_ll_is_on_resolv_list(ident_addr, addr_type)) {
|
||||||
rl->rl_local_rpa_set = 0;
|
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||||
memcpy(&rl->rl_identity_addr[0], ident_addr, BLE_DEV_ADDR_LEN);
|
|
||||||
swap_buf(rl->rl_peer_irk, cmdbuf + 7, 16);
|
|
||||||
swap_buf(rl->rl_local_irk, cmdbuf + 23, 16);
|
|
||||||
|
|
||||||
/* By default use ptivacy network mode */
|
|
||||||
rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add peer IRK to HW resolving list. If we can add it, also
|
|
||||||
* generate a local RPA now to save time later.
|
|
||||||
*/
|
|
||||||
rc = ble_hw_resolv_list_add(rl->rl_peer_irk);
|
|
||||||
if (!rc) {
|
|
||||||
ble_ll_resolv_gen_priv_addr(rl, 1, rl->rl_local_rpa);
|
|
||||||
rl->rl_local_rpa_set = 1;
|
|
||||||
}
|
|
||||||
++g_ble_ll_resolv_data.rl_cnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt];
|
||||||
|
memset (rl, 0, sizeof(*rl));
|
||||||
|
|
||||||
|
rl->rl_addr_type = addr_type;
|
||||||
|
memcpy(&rl->rl_identity_addr[0], ident_addr, BLE_DEV_ADDR_LEN);
|
||||||
|
swap_buf(rl->rl_peer_irk, cmdbuf + 7, 16);
|
||||||
|
swap_buf(rl->rl_local_irk, cmdbuf + 23, 16);
|
||||||
|
|
||||||
|
/* By default use privacy network mode */
|
||||||
|
rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK;
|
||||||
|
|
||||||
|
/* Add peer IRK to HW resolving list. Should always succeed since we
|
||||||
|
* already checked if there is room for it.
|
||||||
|
*/
|
||||||
|
rc = ble_hw_resolv_list_add(rl->rl_peer_irk);
|
||||||
|
assert (rc == BLE_ERR_SUCCESS);
|
||||||
|
|
||||||
|
/* generate a local and peer RPAs now, those will be updated by timer
|
||||||
|
* when resolution is enabled
|
||||||
|
*/
|
||||||
|
ble_ll_resolv_gen_priv_addr(rl, 1);
|
||||||
|
ble_ll_resolv_gen_priv_addr(rl, 0);
|
||||||
|
++g_ble_ll_resolv_data.rl_cnt;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,65 +487,23 @@ ble_ll_resolv_get_rpa_tmo(void)
|
|||||||
return g_ble_ll_resolv_data.rpa_tmo;
|
return g_ble_ll_resolv_data.rpa_tmo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to generate a resolvable private address
|
|
||||||
*
|
|
||||||
* @param rl
|
|
||||||
* @param local
|
|
||||||
* @param addr Pointer to resolvable private address
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local,
|
ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local,
|
||||||
uint8_t *addr)
|
uint8_t *addr)
|
||||||
{
|
{
|
||||||
uint8_t *irk;
|
os_sr_t sr;
|
||||||
uint8_t *prand;
|
|
||||||
uint32_t *irk32;
|
|
||||||
uint32_t *key32;
|
|
||||||
uint32_t *pt32;
|
|
||||||
struct ble_encryption_block ecb;
|
|
||||||
|
|
||||||
assert(rl != NULL);
|
assert(rl != NULL);
|
||||||
assert(addr != NULL);
|
assert(addr != NULL);
|
||||||
|
|
||||||
/* If the local rpa has already been generated, just copy it */
|
OS_ENTER_CRITICAL(sr);
|
||||||
if (local && rl->rl_local_rpa_set) {
|
|
||||||
memcpy(addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get prand */
|
|
||||||
prand = addr + 3;
|
|
||||||
ble_ll_rand_prand_get(prand);
|
|
||||||
|
|
||||||
/* Calculate hash, hash = ah(local IRK, prand) */
|
|
||||||
if (local) {
|
if (local) {
|
||||||
irk = rl->rl_local_irk;
|
memcpy(addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
|
||||||
} else {
|
} else {
|
||||||
irk = rl->rl_peer_irk;
|
memcpy(addr, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
irk32 = (uint32_t *)irk;
|
OS_EXIT_CRITICAL(sr);
|
||||||
key32 = (uint32_t *)&ecb.key[0];
|
|
||||||
key32[0] = irk32[0];
|
|
||||||
key32[1] = irk32[1];
|
|
||||||
key32[2] = irk32[2];
|
|
||||||
key32[3] = irk32[3];
|
|
||||||
pt32 = (uint32_t *)&ecb.plain_text[0];
|
|
||||||
pt32[0] = 0;
|
|
||||||
pt32[1] = 0;
|
|
||||||
pt32[2] = 0;
|
|
||||||
ecb.plain_text[12] = 0;
|
|
||||||
ecb.plain_text[13] = prand[2];
|
|
||||||
ecb.plain_text[14] = prand[1];
|
|
||||||
ecb.plain_text[15] = prand[0];
|
|
||||||
|
|
||||||
/* Calculate hash */
|
|
||||||
ble_hw_encrypt_block(&ecb);
|
|
||||||
|
|
||||||
addr[0] = ecb.cipher_text[15];
|
|
||||||
addr[1] = ecb.cipher_text[14];
|
|
||||||
addr[2] = ecb.cipher_text[13];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -507,7 +531,7 @@ ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int local)
|
|||||||
irk = rl->rl_peer_irk;
|
irk = rl->rl_peer_irk;
|
||||||
}
|
}
|
||||||
if (ble_ll_resolv_irk_nonzero(irk)) {
|
if (ble_ll_resolv_irk_nonzero(irk)) {
|
||||||
ble_ll_resolv_gen_priv_addr(rl, local, rpa);
|
ble_ll_resolv_get_priv_addr(rl, local, rpa);
|
||||||
rc = 1;
|
rc = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ ble_ll_scan_req_pdu_make(struct ble_ll_scan_sm *scansm, uint8_t *adv_addr,
|
|||||||
* section 6.3).
|
* section 6.3).
|
||||||
*/
|
*/
|
||||||
if (rl) {
|
if (rl) {
|
||||||
ble_ll_resolv_gen_priv_addr(rl, 1, rpa);
|
ble_ll_resolv_get_priv_addr(rl, 1, rpa);
|
||||||
scana = rpa;
|
scana = rpa;
|
||||||
} else {
|
} else {
|
||||||
ble_ll_scan_refresh_nrpa(scansm);
|
ble_ll_scan_refresh_nrpa(scansm);
|
||||||
|
|||||||
Reference in New Issue
Block a user