diff options
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 32 |
1 files changed, 27 insertions, 5 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; } |