|
@@ -366,6 +366,56 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void smp_chan_destroy(struct l2cap_conn *conn)
|
|
|
+{
|
|
|
+ struct l2cap_chan *chan = conn->smp;
|
|
|
+ struct smp_chan *smp = chan->data;
|
|
|
+ bool complete;
|
|
|
+
|
|
|
+ BUG_ON(!smp);
|
|
|
+
|
|
|
+ cancel_delayed_work_sync(&smp->security_timer);
|
|
|
+ /* In case the timeout freed the SMP context */
|
|
|
+ if (!chan->data)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (work_pending(&smp->distribute_work)) {
|
|
|
+ cancel_work_sync(&smp->distribute_work);
|
|
|
+ if (!chan->data)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
|
|
|
+ mgmt_smp_complete(conn->hcon, complete);
|
|
|
+
|
|
|
+ kfree(smp->csrk);
|
|
|
+ kfree(smp->slave_csrk);
|
|
|
+
|
|
|
+ crypto_free_blkcipher(smp->tfm_aes);
|
|
|
+
|
|
|
+ /* If pairing failed clean up any keys we might have */
|
|
|
+ if (!complete) {
|
|
|
+ if (smp->ltk) {
|
|
|
+ list_del(&smp->ltk->list);
|
|
|
+ kfree(smp->ltk);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (smp->slave_ltk) {
|
|
|
+ list_del(&smp->slave_ltk->list);
|
|
|
+ kfree(smp->slave_ltk);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (smp->remote_irk) {
|
|
|
+ list_del(&smp->remote_irk->list);
|
|
|
+ kfree(smp->remote_irk);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ chan->data = NULL;
|
|
|
+ kfree(smp);
|
|
|
+ hci_conn_drop(conn->hcon);
|
|
|
+}
|
|
|
+
|
|
|
static void smp_failure(struct l2cap_conn *conn, u8 reason)
|
|
|
{
|
|
|
struct hci_conn *hcon = conn->hcon;
|
|
@@ -812,56 +862,6 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
|
|
|
return smp;
|
|
|
}
|
|
|
|
|
|
-void smp_chan_destroy(struct l2cap_conn *conn)
|
|
|
-{
|
|
|
- struct l2cap_chan *chan = conn->smp;
|
|
|
- struct smp_chan *smp = chan->data;
|
|
|
- bool complete;
|
|
|
-
|
|
|
- BUG_ON(!smp);
|
|
|
-
|
|
|
- cancel_delayed_work_sync(&smp->security_timer);
|
|
|
- /* In case the timeout freed the SMP context */
|
|
|
- if (!chan->data)
|
|
|
- return;
|
|
|
-
|
|
|
- if (work_pending(&smp->distribute_work)) {
|
|
|
- cancel_work_sync(&smp->distribute_work);
|
|
|
- if (!chan->data)
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
|
|
|
- mgmt_smp_complete(conn->hcon, complete);
|
|
|
-
|
|
|
- kfree(smp->csrk);
|
|
|
- kfree(smp->slave_csrk);
|
|
|
-
|
|
|
- crypto_free_blkcipher(smp->tfm_aes);
|
|
|
-
|
|
|
- /* If pairing failed clean up any keys we might have */
|
|
|
- if (!complete) {
|
|
|
- if (smp->ltk) {
|
|
|
- list_del(&smp->ltk->list);
|
|
|
- kfree(smp->ltk);
|
|
|
- }
|
|
|
-
|
|
|
- if (smp->slave_ltk) {
|
|
|
- list_del(&smp->slave_ltk->list);
|
|
|
- kfree(smp->slave_ltk);
|
|
|
- }
|
|
|
-
|
|
|
- if (smp->remote_irk) {
|
|
|
- list_del(&smp->remote_irk->list);
|
|
|
- kfree(smp->remote_irk);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- chan->data = NULL;
|
|
|
- kfree(smp);
|
|
|
- hci_conn_drop(conn->hcon);
|
|
|
-}
|
|
|
-
|
|
|
int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
|
|
|
{
|
|
|
struct l2cap_conn *conn = hcon->l2cap_data;
|