Bluetooth: Fix SMP debug key handling

We need to keep debug keys around at least until the point that they are
used - otherwise e.g. slave role behavior wouldn't work as there'd be no
key to be looked up. The correct behavior should therefore be to return
any stored keys but when we clean up the SMP context to remove the key
from the hdev list if keeping debug keys around hasn't been requestsed.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Johan Hedberg 2014-12-03 12:43:39 +02:00 committed by Marcel Holtmann
parent 06edf8deb5
commit 923e24143e
2 changed files with 14 additions and 11 deletions

View File

@ -3246,15 +3246,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr)) if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
continue; continue;
if (smp_ltk_is_sc(k)) { if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
if (k->type == SMP_LTK_P256_DEBUG &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
continue;
rcu_read_unlock();
return k;
}
if (ltk_role(k->type) == role) {
rcu_read_unlock(); rcu_read_unlock();
return k; return k;
} }

View File

@ -670,6 +670,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
{ {
struct l2cap_chan *chan = conn->smp; struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data; struct smp_chan *smp = chan->data;
struct hci_conn *hcon = conn->hcon;
bool complete; bool complete;
BUG_ON(!smp); BUG_ON(!smp);
@ -677,7 +678,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
cancel_delayed_work_sync(&smp->security_timer); cancel_delayed_work_sync(&smp->security_timer);
complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags); complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
mgmt_smp_complete(conn->hcon, complete); mgmt_smp_complete(hcon, complete);
kfree(smp->csrk); kfree(smp->csrk);
kfree(smp->slave_csrk); kfree(smp->slave_csrk);
@ -686,6 +687,16 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
crypto_free_blkcipher(smp->tfm_aes); crypto_free_blkcipher(smp->tfm_aes);
crypto_free_hash(smp->tfm_cmac); crypto_free_hash(smp->tfm_cmac);
/* Ensure that we don't leave any debug key around if debug key
* support hasn't been explicitly enabled.
*/
if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hcon->hdev->dev_flags)) {
list_del_rcu(&smp->ltk->list);
kfree_rcu(smp->ltk, rcu);
smp->ltk = NULL;
}
/* If pairing failed clean up any keys we might have */ /* If pairing failed clean up any keys we might have */
if (!complete) { if (!complete) {
if (smp->ltk) { if (smp->ltk) {
@ -706,7 +717,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
chan->data = NULL; chan->data = NULL;
kfree(smp); kfree(smp);
hci_conn_drop(conn->hcon); hci_conn_drop(hcon);
} }
static void smp_failure(struct l2cap_conn *conn, u8 reason) static void smp_failure(struct l2cap_conn *conn, u8 reason)