summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/smp.c32
-rw-r--r--net/bluetooth/smp.h3
2 files changed, 29 insertions, 6 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 4f4ff36f5f34..e119d76f87a7 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -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;
}
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index a11d4281542c..676395f93702 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -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;