BLE Host - Handle sec-req via db lookup.

Prior to this change, the master would always react to a security
request by initiating pairing.  Now, the master checks the key database
for an appropriate LTK.  If a key is found, the master initiates the
encryption procedure.  Else, the master initiates pairing.


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

Branch: refs/heads/develop
Commit: c7d3c0c0f847a14fe01e63381bfc23c6869ed6e4
Parents: 7b6fcb9
Author: Christopher Collins <[email protected]>
Authored: Wed May 25 11:22:56 2016 -0700
Committer: Christopher Collins <[email protected]>
Committed: Wed May 25 12:16:46 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_store.h        |  14 +-
 net/nimble/host/src/ble_gatts.c                 |   2 +-
 net/nimble/host/src/ble_l2cap_sm.c              |   4 +-
 net/nimble/host/src/ble_store.c                 |  36 +++
 net/nimble/host/src/test/ble_hs_test_util.h     |   1 +
 .../host/src/test/ble_hs_test_util_store.c      |   4 +-
 net/nimble/host/src/test/ble_l2cap_sm_test.c    | 222 +++++++++++++------
 7 files changed, 207 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c7d3c0c0/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 08bcb9e..5af5b99 100644
--- a/net/nimble/host/include/host/ble_store.h
+++ b/net/nimble/host/include/host/ble_store.h
@@ -22,17 +22,20 @@
 
 #include <inttypes.h>
 
+/* XXX: Rethink our/peer distinction.  Might make sense to unify keys such that
+ * each entry contains both peers' addresses.
+ */
 #define BLE_STORE_OBJ_TYPE_OUR_LTK      1
 #define BLE_STORE_OBJ_TYPE_PEER_LTK     2
 #define BLE_STORE_OBJ_TYPE_CCCD         3
 
-#define BLE_STORE_PEER_ADDR_TYPE_NONE   0xff
+#define BLE_STORE_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.
+     * peer_addr_type=BLE_STORE_ADDR_TYPE_NONE means don't key off peer.
      */
     uint8_t addr[6];
     uint8_t addr_type;
@@ -61,7 +64,7 @@ struct ble_store_value_ltk {
 struct ble_store_key_cccd {
     /**
      * Key by peer identity address;
-     * peer_addr_type=BLE_STORE_PEER_ADDR_TYPE_NONE means don't key off peer.
+     * peer_addr_type=BLE_STORE_ADDR_TYPE_NONE means don't key off peer.
      */
     uint8_t peer_addr[6];
     uint8_t peer_addr_type;
@@ -106,8 +109,13 @@ 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_our_ltk(struct ble_store_key_ltk *key_ltk,
+                           struct ble_store_value_ltk *value_ltk);
+int ble_store_write_our_ltk(struct ble_store_value_ltk *value_ltk);
 int ble_store_read_peer_ltk(struct ble_store_key_ltk *key_ltk,
                             struct ble_store_value_ltk *value_ltk);
+int ble_store_write_peer_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/c7d3c0c0/net/nimble/host/src/ble_gatts.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatts.c b/net/nimble/host/src/ble_gatts.c
index 2d53519..3f73e01 100644
--- a/net/nimble/host/src/ble_gatts.c
+++ b/net/nimble/host/src/ble_gatts.c
@@ -1270,7 +1270,7 @@ ble_gatts_chr_updated(uint16_t chr_val_handle)
     /*** Persist updated flag for unconnected and not-yet-bonded devices. */
 
     /* Retrieve each record corresponding to the modified characteristic. */
-    cccd_key.peer_addr_type = BLE_STORE_PEER_ADDR_TYPE_NONE,
+    cccd_key.peer_addr_type = BLE_STORE_ADDR_TYPE_NONE,
     cccd_key.chr_val_handle = chr_val_handle,
     cccd_key.idx = 0;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c7d3c0c0/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 e9d5230..73a7209 100644
--- a/net/nimble/host/src/ble_l2cap_sm.c
+++ b/net/nimble/host/src/ble_l2cap_sm.c
@@ -1771,6 +1771,7 @@ ble_l2cap_sm_lt_key_req_ltk_handle(struct 
hci_le_lt_key_req *evt)
     /* 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.addr_type = BLE_STORE_ADDR_TYPE_NONE;
     store_key.ltk.ediv = evt->encrypted_diversifier;
     store_key.ltk.ediv_present = 1;
     store_key.ltk.rand_num = evt->random_number;
@@ -1838,6 +1839,7 @@ ble_l2cap_sm_rx_lt_key_req(struct hci_le_lt_key_req *evt)
          * that security establishment is in progress and execute the procedure
          * after the mutex gets unlocked.
          */
+        /* XXX: Ensure we are the master. */
         bonding = 1;
         proc = ble_l2cap_sm_proc_alloc();
         if (proc != NULL) {
@@ -1978,7 +1980,7 @@ ble_l2cap_sm_rx_sec_req(uint16_t conn_handle, uint8_t op, 
struct os_mbuf **om)
 
     if (rc == 0) {
         /* Query database for an LTK corresonding to the sender. */
-        rc = ble_store_read_peer_ltk(&key_ltk, &value_ltk);
+        rc = ble_store_read_our_ltk(&key_ltk, &value_ltk);
         if (rc == 0) {
             /* Found a key corresponding to this peer.  Make sure it meets the
              * requested minimum authreq.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c7d3c0c0/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 580f145..553f7e9 100644
--- a/net/nimble/host/src/ble_store.c
+++ b/net/nimble/host/src/ble_store.c
@@ -66,6 +66,31 @@ ble_store_delete(int obj_type, union ble_store_key *key)
 }
 
 int
+ble_store_read_our_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_OUR_LTK, store_key, store_value);
+    return rc;
+}
+
+int
+ble_store_write_our_ltk(struct ble_store_value_ltk *value_ltk)
+{
+    union ble_store_value *store_value;
+    int rc;
+
+    store_value = (void *)value_ltk;
+    rc = ble_store_write(BLE_STORE_OBJ_TYPE_OUR_LTK, store_value);
+    return rc;
+}
+
+int
 ble_store_read_peer_ltk(struct ble_store_key_ltk *key_ltk,
                         struct ble_store_value_ltk *value_ltk)
 {
@@ -80,6 +105,17 @@ ble_store_read_peer_ltk(struct ble_store_key_ltk *key_ltk,
 }
 
 int
+ble_store_write_peer_ltk(struct ble_store_value_ltk *value_ltk)
+{
+    union ble_store_value *store_value;
+    int rc;
+
+    store_value = (void *)value_ltk;
+    rc = ble_store_write(BLE_STORE_OBJ_TYPE_PEER_LTK, store_value);
+    return rc;
+}
+
+int
 ble_store_read_cccd(struct ble_store_key_cccd *key,
                     struct ble_store_value_cccd *out_value)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c7d3c0c0/net/nimble/host/src/test/ble_hs_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.h 
b/net/nimble/host/src/test/ble_hs_test_util.h
index 35e7e62..60b4819 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.h
+++ b/net/nimble/host/src/test/ble_hs_test_util.h
@@ -23,6 +23,7 @@
 #include <inttypes.h>
 #include "host/ble_gap.h"
 #include "ble_hs_priv.h"
+#include "ble_hs_test_util_store.h"
 struct ble_hs_conn;
 struct ble_l2cap_chan;
 struct hci_disconn_complete;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c7d3c0c0/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 2172ebb..76608c1 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
@@ -92,7 +92,7 @@ ble_hs_test_util_store_read_ltk(struct ble_store_value_ltk 
*store,
     for (i = 0; i < num_values; i++) {
         cur = store + i;
 
-        if (key->addr_type != BLE_STORE_PEER_ADDR_TYPE_NONE) {
+        if (key->addr_type != BLE_STORE_ADDR_TYPE_NONE) {
             if (cur->addr_type != key->addr_type) {
                 continue;
             }
@@ -128,7 +128,7 @@ ble_hs_test_util_store_find_cccd(struct ble_store_key_cccd 
*key)
     for (i = 0; i < ble_hs_test_util_store_num_cccds; i++) {
         cur = ble_hs_test_util_store_cccds + i;
 
-        if (key->peer_addr_type != BLE_STORE_PEER_ADDR_TYPE_NONE) {
+        if (key->peer_addr_type != BLE_STORE_ADDR_TYPE_NONE) {
             if (cur->peer_addr_type != key->peer_addr_type) {
                 continue;
             }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c7d3c0c0/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 d955132..b5a956e 100644
--- a/net/nimble/host/src/test/ble_l2cap_sm_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_sm_test.c
@@ -34,15 +34,13 @@ int ble_l2cap_sm_test_gap_status;
 struct ble_gap_sec_state ble_l2cap_sm_test_sec_state;
 
 int ble_l2cap_sm_test_store_obj_type;
-uint16_t ble_l2cap_sm_test_saved_ediv;
-uint64_t ble_l2cap_sm_test_saved_rand;
-uint8_t ble_l2cap_sm_test_saved_ltk[16];
-int ble_l2cap_sm_test_saved_authenticated;
-int ble_l2cap_sm_test_saved_present;
+union ble_store_key ble_l2cap_sm_test_store_key;
+union ble_store_value ble_l2cap_sm_test_store_value;
 
 static ble_store_read_fn ble_l2cap_sm_test_util_store_read;
 static ble_store_write_fn ble_l2cap_sm_test_util_store_write;
 
+
 /*****************************************************************************
  * $util                                                                     *
  *****************************************************************************/
@@ -85,17 +83,36 @@ struct ble_l2cap_sm_test_pair_params {
         .hdh_len = (len)                                \
     })
 
+static int
+ble_l2cap_sm_test_util_store_read(int obj_type, union ble_store_key *key,
+                                  union ble_store_value *val)
+{
+    ble_l2cap_sm_test_store_obj_type = obj_type;
+    ble_l2cap_sm_test_store_key = *key;
+
+    return ble_hs_test_util_store_read(obj_type, key, val);
+}
+
+static int
+ble_l2cap_sm_test_util_store_write(int obj_type, union ble_store_value *val)
+{
+    ble_l2cap_sm_test_store_obj_type = obj_type;
+    ble_l2cap_sm_test_store_value = *val;
+
+    return ble_hs_test_util_store_write(obj_type, val);
+}
+
 static void
 ble_l2cap_sm_test_util_init(void)
 {
     ble_hs_test_util_init();
+    ble_hs_test_util_store_init(10, 10, 10);
     ble_hs_cfg.store_read_cb = ble_l2cap_sm_test_util_store_read;
     ble_hs_cfg.store_write_cb = ble_l2cap_sm_test_util_store_write;
 
     ble_l2cap_sm_test_store_obj_type = -1;
     ble_l2cap_sm_test_gap_event = -1;
     ble_l2cap_sm_test_gap_status = -1;
-    ble_l2cap_sm_test_saved_present = 0;
 
     memset(&ble_l2cap_sm_test_sec_state, 0xff,
            sizeof ble_l2cap_sm_test_sec_state);
@@ -136,49 +153,6 @@ ble_l2cap_sm_test_util_conn_cb(int event, struct 
ble_gap_conn_ctxt *ctxt,
     return rc;
 }
 
-static int
-ble_l2cap_sm_test_util_store_read(int obj_type, union ble_store_key *key,
-                                  union ble_store_value *dst)
-{
-    ble_l2cap_sm_test_store_obj_type = obj_type;
-
-    switch (obj_type) {
-    case BLE_STORE_OBJ_TYPE_OUR_LTK:
-        ble_l2cap_sm_test_saved_ediv = key->ltk.ediv;
-        ble_l2cap_sm_test_saved_rand = key->ltk.rand_num;
-
-        if (!ble_l2cap_sm_test_saved_present) {
-            return BLE_HS_ENOENT;
-        }
-
-        memcpy(dst->ltk.key, ble_l2cap_sm_test_saved_ltk, sizeof dst->ltk.key);
-        dst->ltk.authenticated = ble_l2cap_sm_test_saved_authenticated;
-        return 0;
-
-    default:
-        return BLE_HS_ENOTSUP;
-    }
-}
-
-static int
-ble_l2cap_sm_test_util_store_write(int obj_type, union ble_store_value *val)
-{
-    ble_l2cap_sm_test_store_obj_type = obj_type;
-
-    switch (obj_type) {
-    case BLE_STORE_OBJ_TYPE_OUR_LTK:
-        ble_l2cap_sm_test_saved_ediv = val->ltk.ediv;
-        ble_l2cap_sm_test_saved_rand = val->ltk.rand_num;
-        memcpy(ble_l2cap_sm_test_saved_ltk, val->ltk.key, sizeof val->ltk.key);
-        ble_l2cap_sm_test_saved_authenticated = val->ltk.authenticated;
-        ble_l2cap_sm_test_saved_present = 1;
-        return 0;
-
-    default:
-        return BLE_HS_ENOTSUP;
-    }
-}
-
 static void
 ble_l2cap_sm_test_util_rx_pair_cmd(uint16_t conn_handle, uint8_t op,
                                    struct ble_l2cap_sm_pair_cmd *cmd,
@@ -1140,22 +1114,15 @@ ble_l2cap_sm_test_util_peer_bonding_good(int 
send_enc_req, uint8_t *ltk,
                                          int authenticated,
                                          uint16_t ediv, uint64_t rand_num)
 {
-    struct ble_l2cap_sm_test_ltk_info ltk_info;
+    struct ble_store_value_ltk value_ltk;
     struct ble_hs_conn *conn;
     int rc;
 
     ble_l2cap_sm_test_util_init();
 
-    memcpy(ltk_info.ltk, ltk, sizeof ltk_info.ltk);
-    ltk_info.authenticated = authenticated;
-
-    memcpy(ble_l2cap_sm_test_saved_ltk, ltk, 16);
-    ble_l2cap_sm_test_saved_authenticated = authenticated;
-    ble_l2cap_sm_test_saved_present = 1;
-
     ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,4,5,6}),
                                  ble_l2cap_sm_test_util_conn_cb,
-                                 &ltk_info);
+                                 NULL);
 
     /* This test inspects and modifies the connection object without locking
      * the host mutex.  It is not OK for real code to do this, but this test
@@ -1164,11 +1131,24 @@ ble_l2cap_sm_test_util_peer_bonding_good(int 
send_enc_req, uint8_t *ltk,
     ble_hs_lock();
     conn = ble_hs_conn_find(2);
     TEST_ASSERT_FATAL(conn != NULL);
+    conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
     ble_hs_unlock();
 
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0);
 
+    /* Populate the SM database with an LTK for this peer. */
+    value_ltk.addr_type = conn->bhc_addr_type;
+    memcpy(value_ltk.addr, conn->bhc_addr, sizeof value_ltk.addr);
+    value_ltk.ediv = ediv;
+    value_ltk.rand_num = rand_num;
+    memcpy(value_ltk.key, ltk, sizeof value_ltk.key);
+    value_ltk.authenticated = authenticated;
+    value_ltk.sc = 0;
+
+    rc = ble_store_write_our_ltk(&value_ltk);
+    TEST_ASSERT_FATAL(rc == 0);
+
     if (send_enc_req) {
         rc = ble_l2cap_sm_slave_initiate(2);
         TEST_ASSERT(rc == 0);
@@ -1183,16 +1163,18 @@ ble_l2cap_sm_test_util_peer_bonding_good(int 
send_enc_req, uint8_t *ltk,
     /* Ensure the LTK request event got sent to the application. */
     TEST_ASSERT(ble_l2cap_sm_test_store_obj_type ==
                 BLE_STORE_OBJ_TYPE_OUR_LTK);
-    TEST_ASSERT(ble_l2cap_sm_test_saved_ediv == ediv);
-    TEST_ASSERT(ble_l2cap_sm_test_saved_rand == rand_num);
-    TEST_ASSERT(memcmp(ble_l2cap_sm_test_saved_ltk, ltk_info.ltk, 16) == 0);
-    TEST_ASSERT(ble_l2cap_sm_test_saved_authenticated ==
-                ltk_info.authenticated);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.addr_type ==
+                BLE_STORE_ADDR_TYPE_NONE);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.ediv_present);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.ediv == ediv);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.rand_num_present);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.rand_num == rand_num);
+
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1);
 
     /* Ensure we sent the expected long term key request reply command. */
-    ble_l2cap_sm_test_util_verify_tx_lt_key_req_reply(2, ltk_info.ltk);
+    ble_l2cap_sm_test_util_verify_tx_lt_key_req_reply(2, value_ltk.key);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1);
 
@@ -1207,12 +1189,12 @@ ble_l2cap_sm_test_util_peer_bonding_good(int 
send_enc_req, uint8_t *ltk,
     TEST_ASSERT(ble_l2cap_sm_test_gap_status == 0);
     TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled);
     TEST_ASSERT(ble_l2cap_sm_test_sec_state.authenticated ==
-                ltk_info.authenticated);
+                authenticated);
 
     /* Verify that connection has correct security state. */
     TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled);
     TEST_ASSERT(ble_l2cap_sm_test_sec_state.authenticated ==
-                ltk_info.authenticated);
+                authenticated);
 }
 
 static void
@@ -1246,8 +1228,11 @@ ble_l2cap_sm_test_util_peer_bonding_bad(uint16_t ediv, 
uint64_t rand_num)
     /* Ensure the LTK request event got sent to the application. */
     TEST_ASSERT(ble_l2cap_sm_test_store_obj_type ==
                 BLE_STORE_OBJ_TYPE_OUR_LTK);
-    TEST_ASSERT(ble_l2cap_sm_test_saved_ediv == ediv);
-    TEST_ASSERT(ble_l2cap_sm_test_saved_rand == rand_num);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.ediv_present);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.ediv == ediv);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.rand_num_present);
+    TEST_ASSERT(ble_l2cap_sm_test_store_key.ltk.rand_num == rand_num);
+
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
 
     /* Ensure we sent the expected long term key request neg reply command. */
@@ -1861,6 +1846,105 @@ TEST_CASE(ble_l2cap_sm_test_case_peer_sec_req_pair)
 }
 
 /**
+ * @param send_enc_req          Whether this procedure is initiated by a slave
+ *                                  security request;
+ *                                  1: Peer sends a security request at start.
+ *                                  0: No security request; we initiate.
+ */
+static void
+ble_l2cap_sm_test_util_us_bonding_good(int send_enc_req, uint8_t *ltk,
+                                       int authenticated,
+                                       uint16_t ediv, uint64_t rand_num)
+{
+    struct ble_l2cap_sm_sec_req sec_req;
+    struct ble_store_value_ltk value_ltk;
+    struct ble_hs_conn *conn;
+    int rc;
+
+    ble_l2cap_sm_test_util_init();
+
+    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,4,5,6}),
+                                 ble_l2cap_sm_test_util_conn_cb,
+                                 NULL);
+
+    /* This test inspects and modifies the connection object without locking
+     * the host mutex.  It is not OK for real code to do this, but this test
+     * can assume the connection list is unchanging.
+     */
+    ble_hs_lock();
+    conn = ble_hs_conn_find(2);
+    TEST_ASSERT_FATAL(conn != NULL);
+    ble_hs_unlock();
+
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0);
+
+    /* Populate the SM database with an LTK for this peer. */
+    value_ltk.addr_type = conn->bhc_addr_type;
+    memcpy(value_ltk.addr, conn->bhc_addr, sizeof value_ltk.addr);
+    value_ltk.ediv = ediv;
+    value_ltk.rand_num = rand_num;
+    memcpy(value_ltk.key, ltk, sizeof value_ltk.key);
+    value_ltk.authenticated = authenticated;
+    value_ltk.sc = 0;
+
+    rc = ble_store_write_our_ltk(&value_ltk);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    if (send_enc_req) {
+        sec_req.authreq = 0;
+        sec_req.authreq |= BLE_L2CAP_SM_PAIR_AUTHREQ_BOND;
+        if (authenticated) {
+            sec_req.authreq |= BLE_L2CAP_SM_PAIR_AUTHREQ_MITM;
+        }
+        ble_hs_test_util_set_ack(
+            host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT),
+            0);
+        ble_l2cap_sm_test_util_rx_sec_req(2, &sec_req, 0);
+    }
+
+    /* Ensure we sent the expected start encryption command. */
+    ble_hs_test_util_tx_all();
+    ble_l2cap_sm_test_util_verify_tx_start_enc(2, rand_num, ediv, ltk);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1);
+
+    /* Receive an encryption changed event. */
+    ble_l2cap_sm_test_util_rx_enc_change(2, 0, 1);
+
+    /* Pairing should now be complete. */
+    TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0);
+
+    /* Verify that security callback was executed. */
+    TEST_ASSERT(ble_l2cap_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+    TEST_ASSERT(ble_l2cap_sm_test_gap_status == 0);
+    TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled);
+    TEST_ASSERT(ble_l2cap_sm_test_sec_state.authenticated ==
+                authenticated);
+
+    /* Verify that connection has correct security state. */
+    TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled);
+    TEST_ASSERT(ble_l2cap_sm_test_sec_state.authenticated ==
+                authenticated);
+}
+
+/**
+ * Master: us.
+ * Peer sends a security request.
+ * We respond by initiating the encryption procedure.
+ */
+TEST_CASE(ble_l2cap_sm_test_case_peer_sec_req_enc)
+{
+    /* Unauthenticated. */
+    ble_l2cap_sm_test_util_us_bonding_good(
+        1,
+        ((uint8_t[16]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }),
+        0,
+        0x1234,
+        0x5678);
+}
+
+/**
  * Master: peer.
  * We send a security request.
  * We accept pairing request sent in response.
@@ -1965,7 +2049,7 @@ TEST_SUITE(ble_l2cap_sm_test_suite)
     ble_l2cap_sm_test_case_conn_broken();
     ble_l2cap_sm_test_case_peer_sec_req_inval();
     ble_l2cap_sm_test_case_peer_sec_req_pair();
-    /* XXX: ble_l2cap_sm_test_case_peer_sec_req_enc(); */
+    ble_l2cap_sm_test_case_peer_sec_req_enc();
     ble_l2cap_sm_test_case_us_sec_req_pair();
     ble_l2cap_sm_test_case_us_sec_req_enc();
 }

Reply via email to