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/05/25 19:17:00 UTC

[7/9] incubator-mynewt-core git commit: BLE Host - Add peer address to ltk store.

BLE Host - Add peer address to ltk store.


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/7b6fcb93
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/7b6fcb93
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/7b6fcb93

Branch: refs/heads/develop
Commit: 7b6fcb93922587c40480eb492a15d9421d830958
Parents: 23fda23
Author: Christopher Collins <cc...@apache.org>
Authored: Wed May 25 09:36:17 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed May 25 12:16:46 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_store.h        | 20 +++++
 net/nimble/host/src/ble_att_svr.c               | 23 ++---
 net/nimble/host/src/ble_l2cap_sm.c              | 90 +++++++++++++-------
 net/nimble/host/src/ble_store.c                 | 20 +++++
 .../host/src/test/ble_hs_test_util_store.c      | 37 +++++---
 net/nimble/host/src/test/ble_l2cap_sm_test.c    |  1 +
 6 files changed, 139 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b6fcb93/net/nimble/host/include/host/ble_store.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_store.h b/net/nimble/host/include/host/ble_store.h
index 5d54ce9..08bcb9e 100644
--- a/net/nimble/host/include/host/ble_store.h
+++ b/net/nimble/host/include/host/ble_store.h
@@ -27,17 +27,35 @@
 #define BLE_STORE_OBJ_TYPE_CCCD         3
 
 #define BLE_STORE_PEER_ADDR_TYPE_NONE   0xff
+#define BLE_STORE_AUTHREQ_NONE          0xff
 
 struct ble_store_key_ltk {
+    /**
+     * Key by peer identity address;
+     * peer_addr_type=BLE_STORE_PEER_ADDR_TYPE_NONE means don't key off peer.
+     */
+    uint8_t addr[6];
+    uint8_t addr_type;
+
+    /** Key by ediv; ediv_present=0 means don't key off ediv. */
     uint16_t ediv;
+    unsigned ediv_present:1;
+
+    /** Key by rand_num; rand_num_present=0 means don't key off rand_num. */
     uint64_t rand_num;
+    unsigned rand_num_present:1;
 };
 
 struct ble_store_value_ltk {
+    uint8_t addr[6];
+    uint8_t addr_type;
     uint16_t ediv;
     uint64_t rand_num;
     uint8_t key[16];
+
     unsigned authenticated:1;
+    unsigned sc:1;
+
 };
 
 struct ble_store_key_cccd {
@@ -88,6 +106,8 @@ int ble_store_read(int obj_type, union ble_store_key *key,
 int ble_store_write(int obj_type, union ble_store_value *val);
 int ble_store_delete(int obj_type, union ble_store_key *key);
 
+int ble_store_read_peer_ltk(struct ble_store_key_ltk *key_ltk,
+                            struct ble_store_value_ltk *value_ltk);
 int ble_store_read_cccd(struct ble_store_key_cccd *key,
                         struct ble_store_value_cccd *out_value);
 int ble_store_write_cccd(struct ble_store_value_cccd *value);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b6fcb93/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index 47e4418..49238ac 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -357,17 +357,20 @@ ble_att_svr_write(uint16_t conn_handle, struct ble_att_svr_entry *entry,
 
     BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
 
-    if (conn_handle != BLE_HS_CONN_HANDLE_NONE &&
-        !(entry->ha_flags & BLE_ATT_F_WRITE)) {
-
-        att_err = BLE_ATT_ERR_WRITE_NOT_PERMITTED;
-        rc = BLE_HS_ENOTSUP;
-        goto err;
-    }
+    /* Bypass permissions and security checks if we are writing our own
+     * attribute.
+     */
+    if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
+        if (!(entry->ha_flags & BLE_ATT_F_WRITE)) {
+            att_err = BLE_ATT_ERR_WRITE_NOT_PERMITTED;
+            rc = BLE_HS_ENOTSUP;
+            goto err;
+        }
 
-    rc = ble_att_svr_check_security(conn_handle, 0, entry, &att_err);
-    if (rc != 0) {
-        goto err;
+        rc = ble_att_svr_check_security(conn_handle, 0, entry, &att_err);
+        if (rc != 0) {
+            goto err;
+        }
     }
 
     BLE_HS_DBG_ASSERT(entry->ha_cb != NULL);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b6fcb93/net/nimble/host/src/ble_l2cap_sm.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sm.c b/net/nimble/host/src/ble_l2cap_sm.c
index 5f20c18..e9d5230 100644
--- a/net/nimble/host/src/ble_l2cap_sm.c
+++ b/net/nimble/host/src/ble_l2cap_sm.c
@@ -490,6 +490,7 @@ ble_l2cap_sm_key_exchange_events(struct ble_l2cap_sm_proc *proc)
                sizeof store_value.ltk.key);
         store_value.ltk.authenticated =
             !!(proc->flags & BLE_L2CAP_SM_PROC_F_AUTHENTICATED);
+        store_value.ltk.sc = 0;
         ble_store_write(BLE_STORE_OBJ_TYPE_OUR_LTK, &store_value);
     }
 
@@ -500,6 +501,7 @@ ble_l2cap_sm_key_exchange_events(struct ble_l2cap_sm_proc *proc)
                sizeof store_value.ltk.key);
         store_value.ltk.authenticated =
             !!(proc->flags & BLE_L2CAP_SM_PROC_F_AUTHENTICATED);
+        store_value.ltk.sc = 0;
         ble_store_write(BLE_STORE_OBJ_TYPE_PEER_LTK, &store_value);
     }
 
@@ -1763,16 +1765,20 @@ ble_l2cap_sm_lt_key_req_ltk_handle(struct hci_le_lt_key_req *evt)
     union ble_store_key store_key;
     struct ble_l2cap_sm_proc *proc;
     struct ble_l2cap_sm_proc *prev;
-    int app_rc;
+    int store_rc;
     int rc;
 
     /* Tell applicaiton to look up LTK by ediv/rand pair. */
+    /* XXX: Also filter by peer address? */
+    memset(&store_key, 0, sizeof store_key);
     store_key.ltk.ediv = evt->encrypted_diversifier;
+    store_key.ltk.ediv_present = 1;
     store_key.ltk.rand_num = evt->random_number;
-    app_rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_LTK, &store_key,
-                            &store_value);
-    if (app_rc == 0) {
-        /* App provided a key; send it to the controller. */
+    store_key.ltk.rand_num_present = 1;
+    store_rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_LTK, &store_key,
+                              &store_value);
+    if (store_rc == 0) {
+        /* Store provided a key; send it to the controller. */
         rc = ble_l2cap_sm_lt_key_req_reply_tx(evt->connection_handle,
                                               store_value.ltk.key);
     } else {
@@ -1788,7 +1794,7 @@ ble_l2cap_sm_lt_key_req_ltk_handle(struct hci_le_lt_key_req *evt)
                                   &prev);
     if (proc == NULL) {
         rc = BLE_HS_EUNKNOWN;
-    } else if (app_rc == 0 && rc == 0) {
+    } else if (store_rc == 0 && rc == 0) {
         proc->state = BLE_L2CAP_SM_PROC_STATE_ENC_CHANGE;
         if (store_value.ltk.authenticated) {
             proc->flags |= BLE_L2CAP_SM_PROC_F_AUTHENTICATED;
@@ -1799,14 +1805,14 @@ ble_l2cap_sm_lt_key_req_ltk_handle(struct hci_le_lt_key_req *evt)
     ble_hs_unlock();
 
     /* Notify the app if it provided a key and the procedure failed. */
-    if (app_rc == 0 && rc != 0) {
+    if (store_rc == 0 && rc != 0) {
         ble_l2cap_sm_gap_event(proc, rc, 0);
     }
 
     /* The procedure is aborted if the app didn't provide a key or if there was
      * a failure.
      */
-    if (app_rc != 0 || rc != 0) {
+    if (store_rc != 0 || rc != 0) {
         ble_l2cap_sm_proc_free(proc);
     }
 
@@ -1928,8 +1934,10 @@ static int
 ble_l2cap_sm_rx_sec_req(uint16_t conn_handle, uint8_t op, struct os_mbuf **om)
 {
     struct ble_l2cap_sm_sec_req cmd;
-    struct ble_l2cap_sm_proc *proc;
+    struct ble_store_value_ltk value_ltk;
+    struct ble_store_key_ltk key_ltk;
     struct ble_hs_conn *conn;
+    int authreq_mitm;
     int rc;
 
     rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SM_SEC_REQ_SZ);
@@ -1939,39 +1947,57 @@ ble_l2cap_sm_rx_sec_req(uint16_t conn_handle, uint8_t op, struct os_mbuf **om)
 
     ble_l2cap_sm_sec_req_parse((*om)->om_data, (*om)->om_len, &cmd);
 
+    /* XXX: Reject if:
+     *     o authreq-bonded flag not set?
+     *     o authreq-reserved flags set?
+     */
+
     BLE_HS_LOG(DEBUG, "rxed sm sec req; authreq=%d\n", cmd.authreq);
 
     ble_hs_lock();
 
-    /* Only handle the security request if a procedure isn't already in
-     * progress for this connection.
-     */
-    proc = ble_l2cap_sm_proc_find(conn_handle, BLE_L2CAP_SM_PROC_STATE_NONE,
-                                  -1, NULL);
-    if (proc != NULL) {
-        rc = BLE_HS_EALREADY;
+    conn = ble_hs_conn_find(conn_handle);
+    if (conn == NULL) {
+        rc = BLE_HS_ENOTCONN;
+    } else if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
+        rc = BLE_HS_SM_US_ERR(BLE_L2CAP_SM_ERR_CMD_NOT_SUPP);
+        ble_l2cap_sm_pair_fail_tx(conn_handle, BLE_L2CAP_SM_ERR_CMD_NOT_SUPP);
     } else {
-        conn = ble_hs_conn_find(conn_handle);
-        if (conn == NULL) {
-            rc = BLE_HS_ENOTCONN;
-        } else if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
-            rc = BLE_HS_SM_US_ERR(BLE_L2CAP_SM_ERR_CMD_NOT_SUPP);
-            ble_l2cap_sm_pair_fail_tx(conn_handle,
-                                      BLE_L2CAP_SM_ERR_CMD_NOT_SUPP);
-        } else {
-            rc = 0;
-        }
+        rc = 0;
+
+        /* We will be querying the SM database for a key corresponding to the
+         * sender; remember the sender's address while the connection list is
+         * locked.
+         */
+        memset(&key_ltk, 0, sizeof key_ltk);
+        key_ltk.addr_type = conn->bhc_addr_type;
+        memcpy(key_ltk.addr, conn->bhc_addr, 6);
     }
 
     ble_hs_unlock();
 
     if (rc == 0) {
-        /* XXX: Ask app / someone if there is a persisted LTK such that:
-         *     o It corresponds to this peer.
-         *     o It meets the specified authreq criteria.
-         * For now, assume we don't have an appropriate LTK; initiate pairing.
-         */
-        rc = ble_l2cap_sm_pair_initiate(conn_handle);
+        /* Query database for an LTK corresonding to the sender. */
+        rc = ble_store_read_peer_ltk(&key_ltk, &value_ltk);
+        if (rc == 0) {
+            /* Found a key corresponding to this peer.  Make sure it meets the
+             * requested minimum authreq.
+             */
+            authreq_mitm = cmd.authreq & BLE_L2CAP_SM_PAIR_AUTHREQ_MITM;
+            if ((!authreq_mitm && value_ltk.authenticated) ||
+                (authreq_mitm && !value_ltk.authenticated)) {
+
+                rc = BLE_HS_EREJECT;
+            }
+        }
+
+        if (rc == 0) {
+            rc = ble_l2cap_sm_enc_initiate(conn_handle, value_ltk.key,
+                                           value_ltk.ediv, value_ltk.rand_num,
+                                           value_ltk.authenticated);
+        } else {
+            rc = ble_l2cap_sm_pair_initiate(conn_handle);
+        }
     }
 
     return rc;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b6fcb93/net/nimble/host/src/ble_store.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_store.c b/net/nimble/host/src/ble_store.c
index 267e8d3..580f145 100644
--- a/net/nimble/host/src/ble_store.c
+++ b/net/nimble/host/src/ble_store.c
@@ -66,6 +66,20 @@ ble_store_delete(int obj_type, union ble_store_key *key)
 }
 
 int
+ble_store_read_peer_ltk(struct ble_store_key_ltk *key_ltk,
+                        struct ble_store_value_ltk *value_ltk)
+{
+    union ble_store_value *store_value;
+    union ble_store_key *store_key;
+    int rc;
+
+    store_key = (void *)key_ltk;
+    store_value = (void *)value_ltk;
+    rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_LTK, store_key, store_value);
+    return rc;
+}
+
+int
 ble_store_read_cccd(struct ble_store_key_cccd *key,
                     struct ble_store_value_cccd *out_value)
 {
@@ -115,6 +129,12 @@ void
 ble_store_key_from_value_ltk(struct ble_store_key_ltk *out_key,
                              struct ble_store_value_ltk *value)
 {
+    out_key->addr_type = value->addr_type;
+    memcpy(out_key->addr, value->addr, sizeof out_key->addr);
+
     out_key->ediv = value->ediv;
+    out_key->ediv_present = 1;
+
     out_key->rand_num = value->rand_num;
+    out_key->rand_num_present = 1;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b6fcb93/net/nimble/host/src/test/ble_hs_test_util_store.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util_store.c b/net/nimble/host/src/test/ble_hs_test_util_store.c
index 51f6dde..2172ebb 100644
--- a/net/nimble/host/src/test/ble_hs_test_util_store.c
+++ b/net/nimble/host/src/test/ble_hs_test_util_store.c
@@ -86,15 +86,32 @@ ble_hs_test_util_store_read_ltk(struct ble_store_value_ltk *store,
                                 struct ble_store_key_ltk *key,
                                 struct ble_store_value_ltk *value)
 {
-    struct ble_store_value_ltk *ltk;
+    struct ble_store_value_ltk *cur;
     int i;
 
     for (i = 0; i < num_values; i++) {
-        ltk = store + i;
-        if (ltk->ediv == key->ediv && ltk->rand_num == key->rand_num) {
-            *value = *ltk;
-            return 0;
+        cur = store + i;
+
+        if (key->addr_type != BLE_STORE_PEER_ADDR_TYPE_NONE) {
+            if (cur->addr_type != key->addr_type) {
+                continue;
+            }
+
+            if (memcmp(cur->addr, key->addr, sizeof cur->addr) != 0) {
+                continue;
+            }
         }
+
+        if (key->ediv_present && cur->ediv != key->ediv) {
+            continue;
+        }
+
+        if (key->rand_num_present && cur->rand_num != key->rand_num) {
+            continue;
+        }
+
+        *value = *cur;
+        return 0;
     }
 
     return BLE_HS_ENOENT;
@@ -103,26 +120,26 @@ ble_hs_test_util_store_read_ltk(struct ble_store_value_ltk *store,
 static int
 ble_hs_test_util_store_find_cccd(struct ble_store_key_cccd *key)
 {
-    struct ble_store_value_cccd *cccd;
+    struct ble_store_value_cccd *cur;
     int skipped;
     int i;
 
     skipped = 0;
     for (i = 0; i < ble_hs_test_util_store_num_cccds; i++) {
-        cccd = ble_hs_test_util_store_cccds + i;
+        cur = ble_hs_test_util_store_cccds + i;
 
         if (key->peer_addr_type != BLE_STORE_PEER_ADDR_TYPE_NONE) {
-            if (cccd->peer_addr_type != key->peer_addr_type) {
+            if (cur->peer_addr_type != key->peer_addr_type) {
                 continue;
             }
 
-            if (memcmp(cccd->peer_addr, key->peer_addr, 6) != 0) {
+            if (memcmp(cur->peer_addr, key->peer_addr, 6) != 0) {
                 continue;
             }
         }
 
         if (key->chr_val_handle != 0) {
-            if (cccd->chr_val_handle != key->chr_val_handle) {
+            if (cur->chr_val_handle != key->chr_val_handle) {
                 continue;
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b6fcb93/net/nimble/host/src/test/ble_l2cap_sm_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_l2cap_sm_test.c b/net/nimble/host/src/test/ble_l2cap_sm_test.c
index c58396d..d955132 100644
--- a/net/nimble/host/src/test/ble_l2cap_sm_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_sm_test.c
@@ -1780,6 +1780,7 @@ TEST_CASE(ble_l2cap_sm_test_case_peer_sec_req_inval)
     ble_l2cap_sm_test_util_verify_tx_pair_fail(&fail);
 
     /*** Pairing already in progress; ignore security request. */
+    ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 1);
     rc = ble_l2cap_sm_pair_initiate(2);
     TEST_ASSERT_FATAL(rc == 0);
     ble_hs_test_util_tx_all();