]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Bluetooth: Re-encrypt link after receiving an LTK
authorJohan Hedberg <johan.hedberg@intel.com>
Fri, 28 Feb 2014 16:10:02 +0000 (18:10 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 28 Feb 2014 16:17:46 +0000 (08:17 -0800)
It's not strictly speaking required to re-encrypt a link once we receive
an LTK since the connection is already encrypted with the STK. However,
re-encrypting with the LTK allows us to verify that we've received an
LTK that actually works.

This patch updates the SMP code to request encrypting with the LTK in
case we're in master role and waits until the key refresh complete event
before notifying user space of the distributed keys.

A new flag is also added for the SMP context to ensure that we
re-encryption only once in case of multiple calls to smp_distribute_keys.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/smp.c
net/bluetooth/smp.h

index 4f4ff36f5f34c539808fb027a78b3e8b17236b5e..e119d76f87a702551e499d3828855f9e52bb1572 100644 (file)
@@ -1178,6 +1178,7 @@ int smp_distribute_keys(struct l2cap_conn *conn)
        struct smp_chan *smp = conn->smp_chan;
        struct hci_conn *hcon = conn->hcon;
        struct hci_dev *hdev = hcon->hdev;
+       bool ltk_encrypt;
        __u8 *keydist;
 
        BT_DBG("conn %p", conn);
@@ -1269,12 +1270,33 @@ int smp_distribute_keys(struct l2cap_conn *conn)
        if ((smp->remote_key_dist & 0x07))
                return 0;
 
-       clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
-       cancel_delayed_work_sync(&conn->security_timer);
-       set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
-       smp_notify_keys(conn);
+       /* Check if we should try to re-encrypt the link with the LTK.
+        * SMP_FLAG_LTK_ENCRYPT flag is used to track whether we've
+        * already tried this (in which case we shouldn't try again).
+        *
+        * The request will trigger an encryption key refresh event
+        * which will cause a call to auth_cfm and eventually lead to
+        * l2cap_core.c calling this smp_distribute_keys function again
+        * and thereby completing the process.
+        */
+       if (smp->ltk)
+               ltk_encrypt = !test_and_set_bit(SMP_FLAG_LTK_ENCRYPT,
+                                               &smp->smp_flags);
+       else
+               ltk_encrypt = false;
 
-       smp_chan_destroy(conn);
+       /* Re-encrypt the link with LTK if possible */
+       if (ltk_encrypt && hcon->out) {
+               struct smp_ltk *ltk = smp->ltk;
+               hci_le_start_enc(hcon, ltk->ediv, ltk->rand, ltk->val);
+               hcon->enc_key_size = ltk->enc_size;
+       } else {
+               clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
+               cancel_delayed_work_sync(&conn->security_timer);
+               set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
+               smp_notify_keys(conn);
+               smp_chan_destroy(conn);
+       }
 
        return 0;
 }
index a11d4281542c27669eb9971b8f7f1bd4fb2ea727..676395f9370258b0bbb5b35b9b570655c7280042 100644 (file)
@@ -118,7 +118,8 @@ struct smp_cmd_security_req {
 #define SMP_FLAG_TK_VALID      1
 #define SMP_FLAG_CFM_PENDING   2
 #define SMP_FLAG_MITM_AUTH     3
-#define SMP_FLAG_COMPLETE      4
+#define SMP_FLAG_LTK_ENCRYPT   4
+#define SMP_FLAG_COMPLETE      5
 
 struct smp_chan {
        struct l2cap_conn *conn;