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/04/09 03:22:00 UTC

incubator-mynewt-core git commit: ble host - fix LTK generation bugs

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 03679c9ea -> c8d9ce1c2


ble host - fix LTK generation bugs

There were three bugs:

* The LTK was getting byte-swapped twice before being passed to the
controller.  (should be little endian; was big endian).

* The initiator was never actually generating a key; it was sending
garbage to the controller!

* The slave was generating the key too late in the process.  As a
consequence, some inputs into the s1 function had been rendered invalid
by overlaid data (they are in a union).


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

Branch: refs/heads/develop
Commit: c8d9ce1c288bb80a4ab038722798da816533ce0a
Parents: 03679c9
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Apr 8 18:14:11 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Apr 8 18:19:32 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/src/ble_hs_misc.c            |  7 +++
 net/nimble/host/src/ble_l2cap.c              |  3 ++
 net/nimble/host/src/ble_l2cap_sm.c           | 32 +++++++-----
 net/nimble/host/src/ble_l2cap_sm_alg.c       | 62 +++++++++++++----------
 net/nimble/host/src/ble_l2cap_sm_cmd.c       |  6 +++
 net/nimble/host/src/host_hci_cmd.c           | 16 +++++-
 net/nimble/host/src/test/ble_l2cap_sm_test.c | 34 +++++--------
 7 files changed, 98 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/net/nimble/host/src/ble_hs_misc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_misc.c b/net/nimble/host/src/ble_hs_misc.c
index a02e456..8335196 100644
--- a/net/nimble/host/src/ble_hs_misc.c
+++ b/net/nimble/host/src/ble_hs_misc.c
@@ -88,6 +88,7 @@ struct os_mbuf *
 ble_hs_misc_pkthdr(void)
 {
     struct os_mbuf *om;
+    int rc;
 
     om = os_msys_get_pkthdr(0, 0);
     if (om == NULL) {
@@ -95,6 +96,12 @@ ble_hs_misc_pkthdr(void)
     }
 
     /* Make room in the buffer for various headers.  XXX Check this number. */
+    if (om->om_omp->omp_databuf_len < 8) {
+        rc = os_mbuf_free_chain(om);
+        BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+        return NULL;
+    }
+
     om->om_data += 8;
 
     return om;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/net/nimble/host/src/ble_l2cap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap.c b/net/nimble/host/src/ble_l2cap.c
index c7a29af..40bf225 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -308,6 +308,9 @@ ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
         goto err;
     }
 
+    BLE_HS_LOG(DEBUG, "ble_l2cap_tx(): ");
+    ble_hs_misc_log_mbuf(om);
+    BLE_HS_LOG(DEBUG, "\n");
     rc = host_hci_data_tx(conn, om);
     om = NULL;
     if (rc != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/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 15d654e..8ff79e0 100644
--- a/net/nimble/host/src/ble_l2cap_sm.c
+++ b/net/nimble/host/src/ble_l2cap_sm.c
@@ -713,6 +713,7 @@ static int
 ble_l2cap_sm_random_kick(struct ble_l2cap_sm_proc *proc)
 {
     struct ble_l2cap_sm_pair_random cmd;
+    uint8_t key[16];
     int rc;
 
     memcpy(cmd.value, proc->phase_1_2.rand_our, 16);
@@ -723,6 +724,15 @@ ble_l2cap_sm_random_kick(struct ble_l2cap_sm_proc *proc)
     }
 
     if (!(proc->flags & BLE_L2CAP_SM_PROC_F_INITIATOR)) {
+        /* Generate the key. */
+        rc = ble_l2cap_sm_alg_s1(proc->phase_1_2.tk, proc->phase_1_2.rand_our,
+                                 proc->phase_1_2.rand_their, key);
+        if (rc != 0) {
+            ble_l2cap_sm_gap_event(proc, rc, 0);
+            return rc;
+        }
+        memcpy(proc->hci.key, key, sizeof key);
+
         proc->hci.handle = BLE_HCI_SCHED_HANDLE_NONE;
         proc->fsm_proc.op = BLE_L2CAP_SM_PROC_OP_LTK;
     }
@@ -737,6 +747,7 @@ ble_l2cap_sm_random_handle(struct ble_l2cap_sm_proc *proc,
     uint8_t preq[BLE_L2CAP_SM_HDR_SZ + BLE_L2CAP_SM_PAIR_CMD_SZ];
     uint8_t pres[BLE_L2CAP_SM_HDR_SZ + BLE_L2CAP_SM_PAIR_CMD_SZ];
     uint8_t confirm_val[16];
+    uint8_t key[16];
     uint8_t k[16];
     uint8_t ia[6];
     uint8_t ra[6];
@@ -768,6 +779,14 @@ ble_l2cap_sm_random_handle(struct ble_l2cap_sm_proc *proc,
     memcpy(proc->phase_1_2.rand_their, cmd->value, 16);
 
     if (proc->flags & BLE_L2CAP_SM_PROC_F_INITIATOR) {
+        /* Generate the key. */
+        rc = ble_l2cap_sm_alg_s1(proc->phase_1_2.tk, proc->phase_1_2.rand_our,
+                                 proc->phase_1_2.rand_their, key);
+        if (rc != 0) {
+            ble_l2cap_sm_gap_event(proc, rc, 0);
+            return rc;
+        }
+        memcpy(proc->hci.key, key, sizeof key);
         proc->fsm_proc.op = BLE_L2CAP_SM_PROC_OP_START_ENCRYPT;
     }
     ble_l2cap_sm_proc_set_pending(proc);
@@ -853,20 +872,7 @@ static int
 ble_l2cap_sm_lt_key_req_handle(struct ble_l2cap_sm_proc *proc,
                                struct hci_le_lt_key_req *evt)
 {
-    uint8_t key[16];
-    int rc;
-
-    /* Generate the key. */
-    rc = ble_l2cap_sm_alg_s1(proc->phase_1_2.tk, proc->phase_1_2.rand_our,
-                             proc->phase_1_2.rand_their, key);
-    if (rc != 0) {
-        ble_l2cap_sm_gap_event(proc, rc, 0);
-        return rc;
-    }
-
     ble_l2cap_sm_proc_set_pending(proc);
-    memcpy(proc->hci.key, key, sizeof key);
-
     return 0;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/net/nimble/host/src/ble_l2cap_sm_alg.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sm_alg.c b/net/nimble/host/src/ble_l2cap_sm_alg.c
index 59ee6c5..61a9825 100644
--- a/net/nimble/host/src/ble_l2cap_sm_alg.c
+++ b/net/nimble/host/src/ble_l2cap_sm_alg.c
@@ -46,17 +46,11 @@ ble_l2cap_sm_alg_encrypt(uint8_t *key, uint8_t *plaintext, uint8_t *enc_data)
     uint8_t tmp[16];
     int rc;
 
-    BLE_HS_LOG(DEBUG, "ble_l2cap_sm_alg_encrypt; key=");
-    ble_hs_misc_log_flat_buf(key, 16);
-    BLE_HS_LOG(DEBUG, " plaintext=");
-    ble_hs_misc_log_flat_buf(plaintext, 16);
-
     swap_buf(tmp, key, 16);
 
     rc = mbedtls_aes_setkey_enc(&ble_l2cap_sm_alg_ctxt, tmp, 128);
     if (rc != 0) {
-        rc = BLE_HS_EUNKNOWN;
-        goto done;
+        return BLE_HS_EUNKNOWN;
     }
 
     swap_buf(tmp, plaintext, 16);
@@ -64,25 +58,19 @@ ble_l2cap_sm_alg_encrypt(uint8_t *key, uint8_t *plaintext, uint8_t *enc_data)
     rc = mbedtls_aes_crypt_ecb(&ble_l2cap_sm_alg_ctxt, MBEDTLS_AES_ENCRYPT,
                                tmp, enc_data);
     if (rc != 0) {
-        rc = BLE_HS_EUNKNOWN;
-        goto done;
+        return BLE_HS_EUNKNOWN;
     }
 
     swap_in_place(enc_data, 16);
 
-    BLE_HS_LOG(DEBUG, " enc_data=");
-    ble_hs_misc_log_flat_buf(enc_data, 16);
-
-    rc = 0;
-
-done:
-    BLE_HS_LOG(DEBUG, "\n");
-    return rc;
+    return 0;
 }
 
 int
 ble_l2cap_sm_alg_s1(uint8_t *k, uint8_t *r1, uint8_t *r2, uint8_t *out)
 {
+    int rc;
+
     /* The most significant 64-bits of r1 are discarded to generate
      * r1' and the most significant 64-bits of r2 are discarded to
      * generate r2'.
@@ -95,7 +83,22 @@ ble_l2cap_sm_alg_s1(uint8_t *k, uint8_t *r1, uint8_t *r2, uint8_t *out)
     memcpy(out + 8, r1, 8);
 
     /* s1(k, r1 , r2) = e(k, r') */
-    return ble_l2cap_sm_alg_encrypt(k, out, out);
+    rc = ble_l2cap_sm_alg_encrypt(k, out, out);
+    if (rc != 0) {
+        return rc;
+    }
+
+    BLE_HS_LOG(DEBUG, "ble_l2cap_sm_alg_s1()\n    k=");
+    ble_hs_misc_log_flat_buf(k, 16);
+    BLE_HS_LOG(DEBUG, "\n    r1=");
+    ble_hs_misc_log_flat_buf(r1, 16);
+    BLE_HS_LOG(DEBUG, "\n    r2=");
+    ble_hs_misc_log_flat_buf(r2, 16);
+    BLE_HS_LOG(DEBUG, "\n    out=");
+    ble_hs_misc_log_flat_buf(out, 16);
+    BLE_HS_LOG(DEBUG, "\n");
+
+    return 0;
 }
 
 int
@@ -108,18 +111,18 @@ ble_l2cap_sm_alg_c1(uint8_t *k, uint8_t *r,
     uint8_t p1[16], p2[16];
     int rc;
 
-    BLE_HS_LOG(DEBUG, "ble_l2cap_sm_alg_c1; k=");
+    BLE_HS_LOG(DEBUG, "ble_l2cap_sm_alg_c1()\n    k=");
     ble_hs_misc_log_flat_buf(k, 16);
-    BLE_HS_LOG(DEBUG, " r=");
+    BLE_HS_LOG(DEBUG, "\n    r=");
     ble_hs_misc_log_flat_buf(r, 16);
-    BLE_HS_LOG(DEBUG, " iat=%d rat=%d", iat, rat);
-    BLE_HS_LOG(DEBUG, " ia=");
+    BLE_HS_LOG(DEBUG, "\n    iat=%d rat=%d", iat, rat);
+    BLE_HS_LOG(DEBUG, "\n    ia=");
     ble_hs_misc_log_flat_buf(ia, 6);
-    BLE_HS_LOG(DEBUG, " ra=");
+    BLE_HS_LOG(DEBUG, "\n    ra=");
     ble_hs_misc_log_flat_buf(ra, 6);
-    BLE_HS_LOG(DEBUG, " preq=");
+    BLE_HS_LOG(DEBUG, "\n    preq=");
     ble_hs_misc_log_flat_buf(preq, 7);
-    BLE_HS_LOG(DEBUG, " pres=");
+    BLE_HS_LOG(DEBUG, "\n    pres=");
     ble_hs_misc_log_flat_buf(pres, 7);
 
     /* pres, preq, rat and iat are concatenated to generate p1 */
@@ -128,7 +131,7 @@ ble_l2cap_sm_alg_c1(uint8_t *k, uint8_t *r,
     memcpy(p1 + 2, preq, 7);
     memcpy(p1 + 9, pres, 7);
 
-    BLE_HS_LOG(DEBUG, " p1=");
+    BLE_HS_LOG(DEBUG, "\n    p1=");
     ble_hs_misc_log_flat_buf(p1, sizeof p1);
 
     /* c1 = e(k, e(k, r XOR p1) XOR p2) */
@@ -147,7 +150,7 @@ ble_l2cap_sm_alg_c1(uint8_t *k, uint8_t *r,
     memcpy(p2 + 6, ia, 6);
     memset(p2 + 12, 0, 4);
 
-    BLE_HS_LOG(DEBUG, " p2=");
+    BLE_HS_LOG(DEBUG, "\n    p2=");
     ble_hs_misc_log_flat_buf(p2, sizeof p2);
 
     ble_l2cap_sm_alg_xor_128(out_enc_data, p2, out_enc_data);
@@ -158,10 +161,13 @@ ble_l2cap_sm_alg_c1(uint8_t *k, uint8_t *r,
         goto done;
     }
 
+    BLE_HS_LOG(DEBUG, "\n    out_enc_data=");
+    ble_hs_misc_log_flat_buf(out_enc_data, 16);
+
     rc = 0;
 
 done:
-    BLE_HS_LOG(DEBUG, "\n");
+    BLE_HS_LOG(DEBUG, "\n    rc=%d\n", rc);
     return rc;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/net/nimble/host/src/ble_l2cap_sm_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sm_cmd.c b/net/nimble/host/src/ble_l2cap_sm_cmd.c
index a83ce72..dac8558 100644
--- a/net/nimble/host/src/ble_l2cap_sm_cmd.c
+++ b/net/nimble/host/src/ble_l2cap_sm_cmd.c
@@ -40,6 +40,9 @@ ble_l2cap_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
     rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
                                          &conn, &chan);
     if (rc == 0) {
+        BLE_HS_LOG(DEBUG, "ble_l2cap_sm_tx(): ");
+        ble_hs_misc_log_mbuf(txom);
+        BLE_HS_LOG(DEBUG, "\n");
         rc = ble_l2cap_tx(conn, chan, txom);
     }
 
@@ -170,6 +173,9 @@ ble_l2cap_sm_pair_confirm_tx(uint16_t conn_handle,
 
     ble_l2cap_sm_pair_confirm_write(txom->om_data, txom->om_len, cmd);
 
+    BLE_HS_LOG(DEBUG, "ble_l2cap_sm_pair_confirm_tx(): ");
+    ble_hs_misc_log_mbuf(txom);
+    BLE_HS_LOG(DEBUG, "\n");
     rc = ble_l2cap_sm_tx(conn_handle, txom);
     txom = NULL;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/net/nimble/host/src/host_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c
index a4a4b81..bb4f8d4 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -741,6 +741,20 @@ host_hci_cmd_le_conn_update(struct hci_conn_update *hcu)
     return rc;
 }
 
+/**
+ * Sends the long-term key (LTK) to the controller.
+ *
+ * Note: This function expects the 128-bit key to be in little-endian byte
+ * order.
+ *
+ * OGF = 0x08 (LE)
+ * OCF = 0x001a
+ *
+ * @param key
+ * @param pt
+ *
+ * @return int
+ */
 int
 host_hci_cmd_le_lt_key_req_reply(struct hci_lt_key_req_reply *hkr)
 {
@@ -878,7 +892,7 @@ host_hci_cmd_le_start_encrypt(struct hci_start_encrypt *cmd)
     htole16(buf + 0, cmd->connection_handle);
     htole64(buf + 2, cmd->random_number);
     htole16(buf + 10, cmd->encrypted_diversifier);
-    swap_buf(buf + 12, cmd->long_term_key, 16);
+    memcpy(buf + 12, cmd->long_term_key, sizeof cmd->long_term_key);
 
     return host_hci_le_cmd_send(BLE_HCI_OCF_LE_START_ENCRYPT, sizeof buf, buf);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c8d9ce1c/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 f29675c..722f12f 100644
--- a/net/nimble/host/src/test/ble_l2cap_sm_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_sm_test.c
@@ -660,12 +660,6 @@ ble_l2cap_sm_test_util_us_lgcy_good(
     ble_l2cap_sm_dbg_set_next_ediv(ediv);
     ble_l2cap_sm_dbg_set_next_start_rand(r);
 
-    ble_hs_cfg.sm_bonding = 1;
-    ble_hs_cfg.sm_mitm = 1;
-    ble_hs_cfg.sm_io_cap = 4;
-    ble_hs_cfg.sm_our_key_dist = 0x07;
-    ble_hs_cfg.sm_their_key_dist = 0x07;
-
     conn = ble_hs_test_util_create_conn(2, rsp_addr,
                                         ble_l2cap_sm_test_util_conn_cb,
                                         NULL);
@@ -746,15 +740,15 @@ ble_l2cap_sm_test_util_us_lgcy_good(
 TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good)
 {
     ble_l2cap_sm_test_util_us_lgcy_good(
-        ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}),
-        ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}),
+        ((uint8_t[]){0x06, 0x05, 0x04, 0x03, 0x02, 0x01}),
+        ((uint8_t[]){0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a}),
         ((struct ble_l2cap_sm_pair_cmd[1]) { {
-            .io_cap = 0x04,
+            .io_cap = 3,
             .oob_data_flag = 0,
-            .authreq = 0x05,
+            .authreq = 0,
             .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
+            .init_key_dist = 0,
+            .resp_key_dist = 0,
         } }),
         ((struct ble_l2cap_sm_pair_cmd[1]) { {
             .io_cap = 3,
@@ -766,20 +760,20 @@ TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good)
         } }),
         ((struct ble_l2cap_sm_pair_confirm[1]) { {
             .value = {
-                0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d,
-                0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0,
+                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
+                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
             },
         } }),
         ((struct ble_l2cap_sm_pair_confirm[1]) { {
             .value = {
-                0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19,
-                0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0
+                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
+                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
             },
         } }),
         ((struct ble_l2cap_sm_pair_random[1]) { {
             .value = {
-                0x2b, 0x3b, 0x69, 0xe4, 0xef, 0xab, 0xcc, 0x48,
-                0x78, 0x20, 0x1a, 0x54, 0x7a, 0x91, 0x5d, 0xfb,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
             },
         } }),
         ((struct ble_l2cap_sm_pair_random[1]) { {
@@ -791,8 +785,8 @@ TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good)
         BLE_L2CAP_SM_PAIR_ALG_JW,
         NULL,
         ((uint8_t[16]) {
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
-            0x00, 0x03, 0x07, 0x07, 0x10, 0x05, 0x00, 0x04,
+            0x2e, 0x2b, 0x34, 0xca, 0x59, 0xfa, 0x4c, 0x88,
+            0x3b, 0x2c, 0x8a, 0xef, 0xd4, 0x4b, 0xe9, 0x66,
         }),
         0,
         0