You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/08/24 00:53:19 UTC

[05/50] [abbrv] incubator-mynewt-core git commit: MYNEWT-358: nrf51 cannot connect to directed advertisers w/privacy

MYNEWT-358: nrf51 cannot connect to directed advertisers w/privacy

In order to fix this issue I have added the local RPA to the resolving list and
modified the code so that the RPA timer is a true LL timer that will be used
to regenerate local RPAs at the specified timeout. This allows the local RPA
to be generated early and not during an IFS interval


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/726a600c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/726a600c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/726a600c

Branch: refs/heads/master
Commit: 726a600cd594f7c6ae6092a3df58d469178806aa
Parents: a955c2f
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Aug 11 14:19:56 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Aug 11 17:49:46 2016 -0700

----------------------------------------------------------------------
 .../include/controller/ble_ll_resolv.h          |   7 +-
 net/nimble/controller/src/ble_ll_adv.c          |  17 +++
 net/nimble/controller/src/ble_ll_conn.c         |   1 +
 net/nimble/controller/src/ble_ll_resolv.c       | 150 +++++++++++++++----
 net/nimble/controller/src/ble_ll_scan.c         |   2 +-
 5 files changed, 142 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/726a600c/net/nimble/controller/include/controller/ble_ll_resolv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_resolv.h b/net/nimble/controller/include/controller/ble_ll_resolv.h
index 251543b..6c63c79 100644
--- a/net/nimble/controller/include/controller/ble_ll_resolv.h
+++ b/net/nimble/controller/include/controller/ble_ll_resolv.h
@@ -23,15 +23,18 @@
 /*
  * An entry in the resolving list.
  *      The identity address is stored in little endian format.
+ *      The local rpa is stored in little endian format.
  *      The IRKs are stored in big endian format.
  */
 struct ble_ll_resolv_entry
 {
-    uint8_t rl_reserved;
     uint8_t rl_addr_type;
-    uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
+    uint8_t rl_local_rpa_set;
+    uint16_t rl_reserved;
     uint8_t rl_local_irk[16];
     uint8_t rl_peer_irk[16];
+    uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
+    uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN];
 };
 
 extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[];

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/726a600c/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c
index 1f43a5d..0c6df3b 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -121,6 +121,23 @@ struct ble_ll_adv_sm g_ble_ll_adv_sm;
 
 
 #if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+/**
+ * Called to change advertisers ADVA and INITA (for directed advertisements)
+ * as an advertiser needs to adhere to the resolvable private address generation
+ * timer.
+ *
+ * NOTE: the resolvable private address code uses its own timer to regenerate
+ * local resolvable private addresses. The advertising code uses its own
+ * timer to reset the INITA (for directed advertisements). This code also sets
+ * the appropriate txadd and rxadd bits that will go into the advertisement.
+ *
+ * Another thing to note: it is possible that an IRK is all zeroes in the
+ * resolving list. That is why we need to check if the generated address is
+ * in fact a RPA as a resolving list entry with all zeroes will use the
+ * identity address (which may be a private address or public).
+ *
+ * @param advsm
+ */
 void
 ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/726a600c/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index bfbdf99..fb95367 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1904,6 +1904,7 @@ ble_ll_conn_event_end(void *arg)
      * The way this works is that whenever the timer expires it just gets reset
      * and we send the autheticated payload timeout event. Note that this timer
      * should run even when encryption is paused.
+     * XXX: what should be here? Was there code here that got deleted?
      */
 #endif
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/726a600c/net/nimble/controller/src/ble_ll_resolv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_resolv.c b/net/nimble/controller/src/ble_ll_resolv.c
index b4d58b0..903c95f 100644
--- a/net/nimble/controller/src/ble_ll_resolv.c
+++ b/net/nimble/controller/src/ble_ll_resolv.c
@@ -31,12 +31,15 @@
 #include "ble_ll_conn_priv.h"
 
 #if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
-
-/* Flag denoting whether or not address translation is enabled. */
-uint8_t g_ble_ll_addr_res_enabled;
-uint8_t g_ble_ll_resolv_list_size;
-uint8_t g_ble_ll_resolv_list_cnt;
-uint32_t g_ble_ll_resolv_rpa_tmo;
+struct ble_ll_resolv_data
+{
+    uint8_t addr_res_enabled;
+    uint8_t rl_size;
+    uint8_t rl_cnt;
+    uint32_t rpa_tmo;
+    struct os_callout_func rpa_timer;
+};
+struct ble_ll_resolv_data g_ble_ll_resolv_data;
 
 struct ble_ll_resolv_entry g_ble_ll_resolv_list[NIMBLE_OPT_LL_RESOLV_LIST_SIZE];
 
@@ -53,9 +56,9 @@ ble_ll_resolv_list_chg_allowed(void)
 {
     int rc;
 
-    if (g_ble_ll_addr_res_enabled && (ble_ll_adv_enabled()  ||
-                                      ble_ll_scan_enabled() ||
-                                      g_ble_ll_conn_create_sm)) {
+    if (g_ble_ll_resolv_data.addr_res_enabled &&
+            (ble_ll_adv_enabled() || ble_ll_scan_enabled() ||
+             g_ble_ll_conn_create_sm)) {
         rc = 0;
     } else {
         rc = 1;
@@ -64,6 +67,32 @@ ble_ll_resolv_list_chg_allowed(void)
 }
 
 /**
+ * Called when the Resolvable private address timer expires. This timer
+ * is used to regenerate local RPA's in the resolving list.
+ *
+ * @param arg
+ */
+void
+ble_ll_resolv_rpa_timer_cb(void *arg)
+{
+    int i;
+    os_sr_t sr;
+    struct ble_ll_resolv_entry *rl;
+
+    rl = &g_ble_ll_resolv_list[0];
+    for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
+        OS_ENTER_CRITICAL(sr);
+        rl->rl_local_rpa_set = 0;
+        ble_ll_resolv_gen_priv_addr(rl, 1, rl->rl_local_rpa);
+        rl->rl_local_rpa_set = 1;
+        OS_EXIT_CRITICAL(sr);
+        ++rl;
+    }
+    os_callout_reset(&g_ble_ll_resolv_data.rpa_timer.cf_c,
+                     (int32_t)g_ble_ll_resolv_data.rpa_tmo);
+}
+
+/**
  * Called to determine if the IRK is all zero.
  *
  * @param irk
@@ -102,7 +131,7 @@ ble_ll_resolv_list_clr(void)
     }
 
     /* Sets total on list to 0. Clears HW resolve list */
-    g_ble_ll_resolv_list_cnt = 0;
+    g_ble_ll_resolv_data.rl_cnt = 0;
     ble_hw_resolv_list_clear();
 
     return BLE_ERR_SUCCESS;
@@ -119,7 +148,7 @@ ble_ll_resolv_list_clr(void)
 int
 ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen)
 {
-    rspbuf[0] = g_ble_ll_resolv_list_size;
+    rspbuf[0] = g_ble_ll_resolv_data.rl_size;
     *rsplen = 1;
     return BLE_ERR_SUCCESS;
 }
@@ -141,7 +170,7 @@ ble_ll_is_on_resolv_list(uint8_t *addr, uint8_t addr_type)
     struct ble_ll_resolv_entry *rl;
 
     rl = &g_ble_ll_resolv_list[0];
-    for (i = 0; i < g_ble_ll_resolv_list_cnt; ++i) {
+    for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
         if ((rl->rl_addr_type == addr_type) &&
             (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) {
             return i + 1;
@@ -167,7 +196,7 @@ ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type)
     struct ble_ll_resolv_entry *rl;
 
     rl = &g_ble_ll_resolv_list[0];
-    for (i = 0; i < g_ble_ll_resolv_list_cnt; ++i) {
+    for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
         if ((rl->rl_addr_type == addr_type) &&
             (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) {
             return rl;
@@ -197,7 +226,7 @@ ble_ll_resolv_list_add(uint8_t *cmdbuf)
     }
 
     /* Check if we have any open entries */
-    if (g_ble_ll_resolv_list_cnt >= g_ble_ll_resolv_list_size) {
+    if (g_ble_ll_resolv_data.rl_cnt >= g_ble_ll_resolv_data.rl_size) {
         return BLE_ERR_MEM_CAPACITY;
     }
 
@@ -206,14 +235,23 @@ ble_ll_resolv_list_add(uint8_t *cmdbuf)
 
     rc = BLE_ERR_SUCCESS;
     if (!ble_ll_is_on_resolv_list(ident_addr, addr_type)) {
-        rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_list_cnt];
+        rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt];
         rl->rl_addr_type = addr_type;
+        rl->rl_local_rpa_set = 0;
         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);
-        ++g_ble_ll_resolv_list_cnt;
 
+        /*
+         * 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;
     }
 
     return rc;
@@ -243,11 +281,11 @@ ble_ll_resolv_list_rmv(uint8_t *cmdbuf)
 
     /* Remove from IRK records */
     position = ble_ll_is_on_resolv_list(ident_addr, addr_type);
-    if (position && (position < g_ble_ll_resolv_list_cnt)) {
+    if (position && (position < g_ble_ll_resolv_data.rl_cnt)) {
         memmove(&g_ble_ll_resolv_list[position - 1],
                 &g_ble_ll_resolv_list[position],
-                g_ble_ll_resolv_list_cnt - position);
-        --g_ble_ll_resolv_list_cnt;
+                g_ble_ll_resolv_data.rl_cnt - position);
+        --g_ble_ll_resolv_data.rl_cnt;
 
         /* Remove from HW list */
         ble_hw_resolv_list_rmv(position - 1);
@@ -267,13 +305,29 @@ int
 ble_ll_resolv_enable_cmd(uint8_t *cmdbuf)
 {
     int rc;
+    int32_t tmo;
+    uint8_t enabled;
 
     if (ble_ll_adv_enabled() || ble_ll_scan_enabled() ||
         g_ble_ll_conn_create_sm) {
         rc = BLE_ERR_CMD_DISALLOWED;
     } else {
-        g_ble_ll_addr_res_enabled = cmdbuf[0];
-        rc = BLE_ERR_SUCCESS;
+        enabled = cmdbuf[0];
+        if (enabled <= 1) {
+            /* If we change state, we need to disable/enable the RPA timer */
+            if ((enabled ^ g_ble_ll_resolv_data.addr_res_enabled) != 0) {
+                if (enabled) {
+                    tmo = (int32_t)g_ble_ll_resolv_data.rpa_tmo;
+                    os_callout_reset(&g_ble_ll_resolv_data.rpa_timer.cf_c, tmo);
+                } else {
+                    os_callout_stop(&g_ble_ll_resolv_data.rpa_timer.cf_c);
+                }
+                g_ble_ll_resolv_data.addr_res_enabled = enabled;
+            }
+            rc = BLE_ERR_SUCCESS;
+        } else {
+            rc = BLE_ERR_INV_HCI_CMD_PARMS;
+        }
     }
 
     return rc;
@@ -306,7 +360,11 @@ ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
 
     tmo_secs = le16toh(cmdbuf);
     if ((tmo_secs > 0) && (tmo_secs <= 0xA1B8)) {
-        g_ble_ll_resolv_rpa_tmo = tmo_secs * OS_TICKS_PER_SEC;
+        g_ble_ll_resolv_data.rpa_tmo = tmo_secs * OS_TICKS_PER_SEC;
+        if (g_ble_ll_resolv_data.addr_res_enabled) {
+            os_callout_reset(&g_ble_ll_resolv_data.rpa_timer.cf_c,
+                             (int32_t)g_ble_ll_resolv_data.rpa_tmo);
+        }
     } else {
         rc = BLE_ERR_INV_HCI_CMD_PARMS;
     }
@@ -323,12 +381,11 @@ ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
 uint32_t
 ble_ll_resolv_get_rpa_tmo(void)
 {
-    return g_ble_ll_resolv_rpa_tmo;
+    return g_ble_ll_resolv_data.rpa_tmo;
 }
 
 /**
- * Called the generate a resolvable private address
- *
+ * Called to generate a resolvable private address
  *
  * @param rl
  * @param local
@@ -348,6 +405,12 @@ ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local,
     assert(rl != NULL);
     assert(addr != NULL);
 
+    /* If the local rpa has already been generated, just copy it */
+    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);
@@ -427,11 +490,29 @@ int
 ble_ll_resolv_rpa(uint8_t *rpa, uint8_t *irk)
 {
     int rc;
+    uint32_t *irk32;
+    uint32_t *key32;
+    uint32_t *pt32;
     struct ble_encryption_block ecb;
 
-    memcpy(ecb.key, irk, BLE_ENC_BLOCK_SIZE);
-    memset(ecb.plain_text, 0, BLE_ENC_BLOCK_SIZE);
-    swap_buf(&ecb.plain_text[13], rpa + 3, 3);
+    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;
+    pt32[3] = 0;
+
+    ecb.plain_text[15] = rpa[3];
+    ecb.plain_text[14] = rpa[4];
+    ecb.plain_text[13] = rpa[5];
+
     ble_hw_encrypt_block(&ecb);
     if ((ecb.cipher_text[15] == rpa[0]) && (ecb.cipher_text[14] == rpa[1]) &&
         (ecb.cipher_text[13] == rpa[2])) {
@@ -451,7 +532,7 @@ ble_ll_resolv_rpa(uint8_t *rpa, uint8_t *irk)
 uint8_t
 ble_ll_resolv_enabled(void)
 {
-    return g_ble_ll_addr_res_enabled;
+    return g_ble_ll_resolv_data.addr_res_enabled;
 }
 
 /**
@@ -460,7 +541,8 @@ ble_ll_resolv_enabled(void)
 void
 ble_ll_resolv_list_reset(void)
 {
-    g_ble_ll_addr_res_enabled = 0;
+    g_ble_ll_resolv_data.addr_res_enabled = 0;
+    os_callout_stop(&g_ble_ll_resolv_data.rpa_timer.cf_c);
     ble_ll_resolv_list_clr();
     ble_ll_resolv_init();
 }
@@ -471,14 +553,18 @@ ble_ll_resolv_init(void)
     uint8_t hw_size;
 
     /* Default is 15 minutes */
-    g_ble_ll_resolv_rpa_tmo = 15 * 60 * OS_TICKS_PER_SEC;
+    g_ble_ll_resolv_data.rpa_tmo = 15 * 60 * OS_TICKS_PER_SEC;
 
     hw_size = ble_hw_resolv_list_size();
     if (hw_size > NIMBLE_OPT_LL_RESOLV_LIST_SIZE) {
         hw_size = NIMBLE_OPT_LL_RESOLV_LIST_SIZE;
     }
-    g_ble_ll_resolv_list_size = hw_size;
+    g_ble_ll_resolv_data.rl_size = hw_size;
 
+    os_callout_func_init(&g_ble_ll_resolv_data.rpa_timer,
+                         &g_ble_ll_data.ll_evq,
+                         ble_ll_resolv_rpa_timer_cb,
+                         NULL);
 }
 
 #endif  /* if BLE_LL_CFG_FEAT_LL_PRIVACY == 1 */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/726a600c/net/nimble/controller/src/ble_ll_scan.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_scan.c b/net/nimble/controller/src/ble_ll_scan.c
index 0fc4e79..29193dc 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -448,7 +448,7 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
                  * are 2 greater than the unresolved ones in the spec, so
                  * we just add 2 here.
                  */
-                addr_type += 2;
+                addr_type = g_ble_ll_resolv_list[index].rl_addr_type + 2;
             } else{
                 adv_addr = rxbuf;
             }