1eb492e01SAnderson Briglia /* 2eb492e01SAnderson Briglia BlueZ - Bluetooth protocol stack for Linux 3eb492e01SAnderson Briglia Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4eb492e01SAnderson Briglia 5eb492e01SAnderson Briglia This program is free software; you can redistribute it and/or modify 6eb492e01SAnderson Briglia it under the terms of the GNU General Public License version 2 as 7eb492e01SAnderson Briglia published by the Free Software Foundation; 8eb492e01SAnderson Briglia 9eb492e01SAnderson Briglia THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10eb492e01SAnderson Briglia OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11eb492e01SAnderson Briglia FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 12eb492e01SAnderson Briglia IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 13eb492e01SAnderson Briglia CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 14eb492e01SAnderson Briglia WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15eb492e01SAnderson Briglia ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16eb492e01SAnderson Briglia OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17eb492e01SAnderson Briglia 18eb492e01SAnderson Briglia ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 19eb492e01SAnderson Briglia COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 20eb492e01SAnderson Briglia SOFTWARE IS DISCLAIMED. 21eb492e01SAnderson Briglia */ 22eb492e01SAnderson Briglia 238c520a59SGustavo Padovan #include <linux/crypto.h> 248c520a59SGustavo Padovan #include <linux/scatterlist.h> 258c520a59SGustavo Padovan #include <crypto/b128ops.h> 268c520a59SGustavo Padovan 27eb492e01SAnderson Briglia #include <net/bluetooth/bluetooth.h> 28eb492e01SAnderson Briglia #include <net/bluetooth/hci_core.h> 29eb492e01SAnderson Briglia #include <net/bluetooth/l2cap.h> 302b64d153SBrian Gix #include <net/bluetooth/mgmt.h> 31ac4b7236SMarcel Holtmann 32ac4b7236SMarcel Holtmann #include "smp.h" 33d22ef0bcSAnderson Briglia 3417b02e62SMarcel Holtmann #define SMP_TIMEOUT msecs_to_jiffies(30000) 355d3de7dfSVinicius Costa Gomes 36065a13e2SJohan Hedberg #define AUTH_REQ_MASK 0x07 37065a13e2SJohan Hedberg 38d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16]) 39d22ef0bcSAnderson Briglia { 40d22ef0bcSAnderson Briglia int i; 41d22ef0bcSAnderson Briglia for (i = 0; i < 16; i++) 42d22ef0bcSAnderson Briglia dst[15 - i] = src[i]; 43d22ef0bcSAnderson Briglia } 44d22ef0bcSAnderson Briglia 45d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7]) 46d22ef0bcSAnderson Briglia { 47d22ef0bcSAnderson Briglia int i; 48d22ef0bcSAnderson Briglia for (i = 0; i < 7; i++) 49d22ef0bcSAnderson Briglia dst[6 - i] = src[i]; 50d22ef0bcSAnderson Briglia } 51d22ef0bcSAnderson Briglia 52d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) 53d22ef0bcSAnderson Briglia { 54d22ef0bcSAnderson Briglia struct blkcipher_desc desc; 55d22ef0bcSAnderson Briglia struct scatterlist sg; 56d22ef0bcSAnderson Briglia int err, iv_len; 57d22ef0bcSAnderson Briglia unsigned char iv[128]; 58d22ef0bcSAnderson Briglia 59d22ef0bcSAnderson Briglia if (tfm == NULL) { 60d22ef0bcSAnderson Briglia BT_ERR("tfm %p", tfm); 61d22ef0bcSAnderson Briglia return -EINVAL; 62d22ef0bcSAnderson Briglia } 63d22ef0bcSAnderson Briglia 64d22ef0bcSAnderson Briglia desc.tfm = tfm; 65d22ef0bcSAnderson Briglia desc.flags = 0; 66d22ef0bcSAnderson Briglia 67d22ef0bcSAnderson Briglia err = crypto_blkcipher_setkey(tfm, k, 16); 68d22ef0bcSAnderson Briglia if (err) { 69d22ef0bcSAnderson Briglia BT_ERR("cipher setkey failed: %d", err); 70d22ef0bcSAnderson Briglia return err; 71d22ef0bcSAnderson Briglia } 72d22ef0bcSAnderson Briglia 73d22ef0bcSAnderson Briglia sg_init_one(&sg, r, 16); 74d22ef0bcSAnderson Briglia 75d22ef0bcSAnderson Briglia iv_len = crypto_blkcipher_ivsize(tfm); 76d22ef0bcSAnderson Briglia if (iv_len) { 77d22ef0bcSAnderson Briglia memset(&iv, 0xff, iv_len); 78d22ef0bcSAnderson Briglia crypto_blkcipher_set_iv(tfm, iv, iv_len); 79d22ef0bcSAnderson Briglia } 80d22ef0bcSAnderson Briglia 81d22ef0bcSAnderson Briglia err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); 82d22ef0bcSAnderson Briglia if (err) 83d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error %d", err); 84d22ef0bcSAnderson Briglia 85d22ef0bcSAnderson Briglia return err; 86d22ef0bcSAnderson Briglia } 87d22ef0bcSAnderson Briglia 88d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], 89d22ef0bcSAnderson Briglia u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, 90d22ef0bcSAnderson Briglia u8 _rat, bdaddr_t *ra, u8 res[16]) 91d22ef0bcSAnderson Briglia { 92d22ef0bcSAnderson Briglia u8 p1[16], p2[16]; 93d22ef0bcSAnderson Briglia int err; 94d22ef0bcSAnderson Briglia 95d22ef0bcSAnderson Briglia memset(p1, 0, 16); 96d22ef0bcSAnderson Briglia 97d22ef0bcSAnderson Briglia /* p1 = pres || preq || _rat || _iat */ 98d22ef0bcSAnderson Briglia swap56(pres, p1); 99d22ef0bcSAnderson Briglia swap56(preq, p1 + 7); 100d22ef0bcSAnderson Briglia p1[14] = _rat; 101d22ef0bcSAnderson Briglia p1[15] = _iat; 102d22ef0bcSAnderson Briglia 103d22ef0bcSAnderson Briglia memset(p2, 0, 16); 104d22ef0bcSAnderson Briglia 105d22ef0bcSAnderson Briglia /* p2 = padding || ia || ra */ 106d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 4), ia); 107d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 10), ra); 108d22ef0bcSAnderson Briglia 109d22ef0bcSAnderson Briglia /* res = r XOR p1 */ 110d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); 111d22ef0bcSAnderson Briglia 112d22ef0bcSAnderson Briglia /* res = e(k, res) */ 113d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 114d22ef0bcSAnderson Briglia if (err) { 115d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 116d22ef0bcSAnderson Briglia return err; 117d22ef0bcSAnderson Briglia } 118d22ef0bcSAnderson Briglia 119d22ef0bcSAnderson Briglia /* res = res XOR p2 */ 120d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); 121d22ef0bcSAnderson Briglia 122d22ef0bcSAnderson Briglia /* res = e(k, res) */ 123d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 124d22ef0bcSAnderson Briglia if (err) 125d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 126d22ef0bcSAnderson Briglia 127d22ef0bcSAnderson Briglia return err; 128d22ef0bcSAnderson Briglia } 129d22ef0bcSAnderson Briglia 130f1560463SMarcel Holtmann static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], 131f1560463SMarcel Holtmann u8 r2[16], u8 _r[16]) 132d22ef0bcSAnderson Briglia { 133d22ef0bcSAnderson Briglia int err; 134d22ef0bcSAnderson Briglia 135d22ef0bcSAnderson Briglia /* Just least significant octets from r1 and r2 are considered */ 136d22ef0bcSAnderson Briglia memcpy(_r, r1 + 8, 8); 137d22ef0bcSAnderson Briglia memcpy(_r + 8, r2 + 8, 8); 138d22ef0bcSAnderson Briglia 139d22ef0bcSAnderson Briglia err = smp_e(tfm, k, _r); 140d22ef0bcSAnderson Briglia if (err) 141d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 142d22ef0bcSAnderson Briglia 143d22ef0bcSAnderson Briglia return err; 144d22ef0bcSAnderson Briglia } 145d22ef0bcSAnderson Briglia 146d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf) 147d22ef0bcSAnderson Briglia { 148d22ef0bcSAnderson Briglia get_random_bytes(buf, 16); 149d22ef0bcSAnderson Briglia 150d22ef0bcSAnderson Briglia return 0; 151d22ef0bcSAnderson Briglia } 152eb492e01SAnderson Briglia 153eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, 154eb492e01SAnderson Briglia u16 dlen, void *data) 155eb492e01SAnderson Briglia { 156eb492e01SAnderson Briglia struct sk_buff *skb; 157eb492e01SAnderson Briglia struct l2cap_hdr *lh; 158eb492e01SAnderson Briglia int len; 159eb492e01SAnderson Briglia 160eb492e01SAnderson Briglia len = L2CAP_HDR_SIZE + sizeof(code) + dlen; 161eb492e01SAnderson Briglia 162eb492e01SAnderson Briglia if (len > conn->mtu) 163eb492e01SAnderson Briglia return NULL; 164eb492e01SAnderson Briglia 165eb492e01SAnderson Briglia skb = bt_skb_alloc(len, GFP_ATOMIC); 166eb492e01SAnderson Briglia if (!skb) 167eb492e01SAnderson Briglia return NULL; 168eb492e01SAnderson Briglia 169eb492e01SAnderson Briglia lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 170eb492e01SAnderson Briglia lh->len = cpu_to_le16(sizeof(code) + dlen); 171d8aece2aSSyam Sidhardhan lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); 172eb492e01SAnderson Briglia 173eb492e01SAnderson Briglia memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); 174eb492e01SAnderson Briglia 175eb492e01SAnderson Briglia memcpy(skb_put(skb, dlen), data, dlen); 176eb492e01SAnderson Briglia 177eb492e01SAnderson Briglia return skb; 178eb492e01SAnderson Briglia } 179eb492e01SAnderson Briglia 180eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) 181eb492e01SAnderson Briglia { 182eb492e01SAnderson Briglia struct sk_buff *skb = smp_build_cmd(conn, code, len, data); 183eb492e01SAnderson Briglia 184eb492e01SAnderson Briglia BT_DBG("code 0x%2.2x", code); 185eb492e01SAnderson Briglia 186eb492e01SAnderson Briglia if (!skb) 187eb492e01SAnderson Briglia return; 188eb492e01SAnderson Briglia 18973d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 19073d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, 0); 191e2dcd113SVinicius Costa Gomes 1926c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 19317b02e62SMarcel Holtmann schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT); 194eb492e01SAnderson Briglia } 195eb492e01SAnderson Briglia 1962b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq) 1972b64d153SBrian Gix { 1982b64d153SBrian Gix if (authreq & SMP_AUTH_MITM) 1992b64d153SBrian Gix return BT_SECURITY_HIGH; 2002b64d153SBrian Gix else 2012b64d153SBrian Gix return BT_SECURITY_MEDIUM; 2022b64d153SBrian Gix } 2032b64d153SBrian Gix 2042b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level) 2052b64d153SBrian Gix { 2062b64d153SBrian Gix switch (sec_level) { 2072b64d153SBrian Gix case BT_SECURITY_HIGH: 2082b64d153SBrian Gix return SMP_AUTH_MITM | SMP_AUTH_BONDING; 2092b64d153SBrian Gix case BT_SECURITY_MEDIUM: 2102b64d153SBrian Gix return SMP_AUTH_BONDING; 2112b64d153SBrian Gix default: 2122b64d153SBrian Gix return SMP_AUTH_NONE; 2132b64d153SBrian Gix } 2142b64d153SBrian Gix } 2152b64d153SBrian Gix 216b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn, 21754790f73SVinicius Costa Gomes struct smp_cmd_pairing *req, 218f1560463SMarcel Holtmann struct smp_cmd_pairing *rsp, __u8 authreq) 219b8e66eacSVinicius Costa Gomes { 2202b64d153SBrian Gix u8 dist_keys = 0; 22154790f73SVinicius Costa Gomes 222a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { 223ca10b5eeSVinicius Costa Gomes dist_keys = SMP_DIST_ENC_KEY; 22454790f73SVinicius Costa Gomes authreq |= SMP_AUTH_BONDING; 2252b64d153SBrian Gix } else { 2262b64d153SBrian Gix authreq &= ~SMP_AUTH_BONDING; 22754790f73SVinicius Costa Gomes } 22854790f73SVinicius Costa Gomes 22954790f73SVinicius Costa Gomes if (rsp == NULL) { 23054790f73SVinicius Costa Gomes req->io_capability = conn->hcon->io_capability; 23154790f73SVinicius Costa Gomes req->oob_flag = SMP_OOB_NOT_PRESENT; 23254790f73SVinicius Costa Gomes req->max_key_size = SMP_MAX_ENC_KEY_SIZE; 2332b64d153SBrian Gix req->init_key_dist = 0; 23454790f73SVinicius Costa Gomes req->resp_key_dist = dist_keys; 235065a13e2SJohan Hedberg req->auth_req = (authreq & AUTH_REQ_MASK); 23654790f73SVinicius Costa Gomes return; 23754790f73SVinicius Costa Gomes } 23854790f73SVinicius Costa Gomes 23954790f73SVinicius Costa Gomes rsp->io_capability = conn->hcon->io_capability; 24054790f73SVinicius Costa Gomes rsp->oob_flag = SMP_OOB_NOT_PRESENT; 24154790f73SVinicius Costa Gomes rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; 2422b64d153SBrian Gix rsp->init_key_dist = 0; 24354790f73SVinicius Costa Gomes rsp->resp_key_dist = req->resp_key_dist & dist_keys; 244065a13e2SJohan Hedberg rsp->auth_req = (authreq & AUTH_REQ_MASK); 245b8e66eacSVinicius Costa Gomes } 246b8e66eacSVinicius Costa Gomes 2473158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) 2483158c50cSVinicius Costa Gomes { 2491c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 2501c1def09SVinicius Costa Gomes 2513158c50cSVinicius Costa Gomes if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || 2523158c50cSVinicius Costa Gomes (max_key_size < SMP_MIN_ENC_KEY_SIZE)) 2533158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 2543158c50cSVinicius Costa Gomes 255f7aa611aSVinicius Costa Gomes smp->enc_key_size = max_key_size; 2563158c50cSVinicius Costa Gomes 2573158c50cSVinicius Costa Gomes return 0; 2583158c50cSVinicius Costa Gomes } 2593158c50cSVinicius Costa Gomes 2604f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) 2614f957a76SBrian Gix { 262bab73cb6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 263bab73cb6SJohan Hedberg 2644f957a76SBrian Gix if (send) 2654f957a76SBrian Gix smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), 2664f957a76SBrian Gix &reason); 2674f957a76SBrian Gix 268ce39fb4eSMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags); 269ce39fb4eSMarcel Holtmann mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, 270ce39fb4eSMarcel Holtmann HCI_ERROR_AUTH_FAILURE); 271f1c09c07SVinicius Costa Gomes 2726c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 27361a0cfb0SAndre Guedes 274ce39fb4eSMarcel Holtmann if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 2754f957a76SBrian Gix smp_chan_destroy(conn); 2764f957a76SBrian Gix } 2774f957a76SBrian Gix 2782b64d153SBrian Gix #define JUST_WORKS 0x00 2792b64d153SBrian Gix #define JUST_CFM 0x01 2802b64d153SBrian Gix #define REQ_PASSKEY 0x02 2812b64d153SBrian Gix #define CFM_PASSKEY 0x03 2822b64d153SBrian Gix #define REQ_OOB 0x04 2832b64d153SBrian Gix #define OVERLAP 0xFF 2842b64d153SBrian Gix 2852b64d153SBrian Gix static const u8 gen_method[5][5] = { 2862b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2872b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2882b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 2892b64d153SBrian Gix { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, 2902b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, 2912b64d153SBrian Gix }; 2922b64d153SBrian Gix 2932b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, 2942b64d153SBrian Gix u8 local_io, u8 remote_io) 2952b64d153SBrian Gix { 2962b64d153SBrian Gix struct hci_conn *hcon = conn->hcon; 2972b64d153SBrian Gix struct smp_chan *smp = conn->smp_chan; 2982b64d153SBrian Gix u8 method; 2992b64d153SBrian Gix u32 passkey = 0; 3002b64d153SBrian Gix int ret = 0; 3012b64d153SBrian Gix 3022b64d153SBrian Gix /* Initialize key for JUST WORKS */ 3032b64d153SBrian Gix memset(smp->tk, 0, sizeof(smp->tk)); 3042b64d153SBrian Gix clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3052b64d153SBrian Gix 3062b64d153SBrian Gix BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); 3072b64d153SBrian Gix 3082b64d153SBrian Gix /* If neither side wants MITM, use JUST WORKS */ 3092b64d153SBrian Gix /* If either side has unknown io_caps, use JUST WORKS */ 3102b64d153SBrian Gix /* Otherwise, look up method from the table */ 3112b64d153SBrian Gix if (!(auth & SMP_AUTH_MITM) || 3122b64d153SBrian Gix local_io > SMP_IO_KEYBOARD_DISPLAY || 3132b64d153SBrian Gix remote_io > SMP_IO_KEYBOARD_DISPLAY) 3142b64d153SBrian Gix method = JUST_WORKS; 3152b64d153SBrian Gix else 316b3ff53ffSIdo Yariv method = gen_method[remote_io][local_io]; 3172b64d153SBrian Gix 3182b64d153SBrian Gix /* If not bonding, don't ask user to confirm a Zero TK */ 3192b64d153SBrian Gix if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) 3202b64d153SBrian Gix method = JUST_WORKS; 3212b64d153SBrian Gix 3222b64d153SBrian Gix /* If Just Works, Continue with Zero TK */ 3232b64d153SBrian Gix if (method == JUST_WORKS) { 3242b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3252b64d153SBrian Gix return 0; 3262b64d153SBrian Gix } 3272b64d153SBrian Gix 3282b64d153SBrian Gix /* Not Just Works/Confirm results in MITM Authentication */ 3292b64d153SBrian Gix if (method != JUST_CFM) 3302b64d153SBrian Gix set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags); 3312b64d153SBrian Gix 3322b64d153SBrian Gix /* If both devices have Keyoard-Display I/O, the master 3332b64d153SBrian Gix * Confirms and the slave Enters the passkey. 3342b64d153SBrian Gix */ 3352b64d153SBrian Gix if (method == OVERLAP) { 3362b64d153SBrian Gix if (hcon->link_mode & HCI_LM_MASTER) 3372b64d153SBrian Gix method = CFM_PASSKEY; 3382b64d153SBrian Gix else 3392b64d153SBrian Gix method = REQ_PASSKEY; 3402b64d153SBrian Gix } 3412b64d153SBrian Gix 3422b64d153SBrian Gix /* Generate random passkey. Not valid until confirmed. */ 3432b64d153SBrian Gix if (method == CFM_PASSKEY) { 3442b64d153SBrian Gix u8 key[16]; 3452b64d153SBrian Gix 3462b64d153SBrian Gix memset(key, 0, sizeof(key)); 3472b64d153SBrian Gix get_random_bytes(&passkey, sizeof(passkey)); 3482b64d153SBrian Gix passkey %= 1000000; 3492b64d153SBrian Gix put_unaligned_le32(passkey, key); 3502b64d153SBrian Gix swap128(key, smp->tk); 3512b64d153SBrian Gix BT_DBG("PassKey: %d", passkey); 3522b64d153SBrian Gix } 3532b64d153SBrian Gix 3542b64d153SBrian Gix hci_dev_lock(hcon->hdev); 3552b64d153SBrian Gix 3562b64d153SBrian Gix if (method == REQ_PASSKEY) 357ce39fb4eSMarcel Holtmann ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, 358272d90dfSJohan Hedberg hcon->type, hcon->dst_type); 3592b64d153SBrian Gix else 360ce39fb4eSMarcel Holtmann ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, 361272d90dfSJohan Hedberg hcon->type, hcon->dst_type, 3622b64d153SBrian Gix cpu_to_le32(passkey), 0); 3632b64d153SBrian Gix 3642b64d153SBrian Gix hci_dev_unlock(hcon->hdev); 3652b64d153SBrian Gix 3662b64d153SBrian Gix return ret; 3672b64d153SBrian Gix } 3682b64d153SBrian Gix 3698aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work) 3708aab4757SVinicius Costa Gomes { 3718aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, confirm); 3728aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 3738aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm; 3748aab4757SVinicius Costa Gomes struct smp_cmd_pairing_confirm cp; 3758aab4757SVinicius Costa Gomes int ret; 3768aab4757SVinicius Costa Gomes u8 res[16], reason; 3778aab4757SVinicius Costa Gomes 3788aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 3798aab4757SVinicius Costa Gomes 3808aab4757SVinicius Costa Gomes tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); 3818aab4757SVinicius Costa Gomes if (IS_ERR(tfm)) { 3828aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3838aab4757SVinicius Costa Gomes goto error; 3848aab4757SVinicius Costa Gomes } 3858aab4757SVinicius Costa Gomes 3868aab4757SVinicius Costa Gomes smp->tfm = tfm; 3878aab4757SVinicius Costa Gomes 3888aab4757SVinicius Costa Gomes if (conn->hcon->out) 389c8462ca6SMarcel Holtmann ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 390c8462ca6SMarcel Holtmann conn->hcon->src_type, &conn->hcon->src, 391c8462ca6SMarcel Holtmann conn->hcon->dst_type, &conn->hcon->dst, res); 3928aab4757SVinicius Costa Gomes else 3938aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 394c8462ca6SMarcel Holtmann conn->hcon->dst_type, &conn->hcon->dst, 395c8462ca6SMarcel Holtmann conn->hcon->src_type, &conn->hcon->src, res); 3968aab4757SVinicius Costa Gomes if (ret) { 3978aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3988aab4757SVinicius Costa Gomes goto error; 3998aab4757SVinicius Costa Gomes } 4008aab4757SVinicius Costa Gomes 4012b64d153SBrian Gix clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 4022b64d153SBrian Gix 4038aab4757SVinicius Costa Gomes swap128(res, cp.confirm_val); 4048aab4757SVinicius Costa Gomes smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 4058aab4757SVinicius Costa Gomes 4068aab4757SVinicius Costa Gomes return; 4078aab4757SVinicius Costa Gomes 4088aab4757SVinicius Costa Gomes error: 4094f957a76SBrian Gix smp_failure(conn, reason, 1); 4108aab4757SVinicius Costa Gomes } 4118aab4757SVinicius Costa Gomes 4128aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work) 4138aab4757SVinicius Costa Gomes { 4148aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, random); 4158aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 4168aab4757SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 4178aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm = smp->tfm; 4188aab4757SVinicius Costa Gomes u8 reason, confirm[16], res[16], key[16]; 4198aab4757SVinicius Costa Gomes int ret; 4208aab4757SVinicius Costa Gomes 4218aab4757SVinicius Costa Gomes if (IS_ERR_OR_NULL(tfm)) { 4228aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4238aab4757SVinicius Costa Gomes goto error; 4248aab4757SVinicius Costa Gomes } 4258aab4757SVinicius Costa Gomes 4268aab4757SVinicius Costa Gomes BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 4278aab4757SVinicius Costa Gomes 4288aab4757SVinicius Costa Gomes if (hcon->out) 429c8462ca6SMarcel Holtmann ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 430c8462ca6SMarcel Holtmann hcon->src_type, &hcon->src, 431c8462ca6SMarcel Holtmann hcon->dst_type, &hcon->dst, res); 4328aab4757SVinicius Costa Gomes else 4338aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 434c8462ca6SMarcel Holtmann hcon->dst_type, &hcon->dst, 435c8462ca6SMarcel Holtmann hcon->src_type, &hcon->src, res); 4368aab4757SVinicius Costa Gomes if (ret) { 4378aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4388aab4757SVinicius Costa Gomes goto error; 4398aab4757SVinicius Costa Gomes } 4408aab4757SVinicius Costa Gomes 4418aab4757SVinicius Costa Gomes swap128(res, confirm); 4428aab4757SVinicius Costa Gomes 4438aab4757SVinicius Costa Gomes if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { 4448aab4757SVinicius Costa Gomes BT_ERR("Pairing failed (confirmation values mismatch)"); 4458aab4757SVinicius Costa Gomes reason = SMP_CONFIRM_FAILED; 4468aab4757SVinicius Costa Gomes goto error; 4478aab4757SVinicius Costa Gomes } 4488aab4757SVinicius Costa Gomes 4498aab4757SVinicius Costa Gomes if (hcon->out) { 4508aab4757SVinicius Costa Gomes u8 stk[16], rand[8]; 4518aab4757SVinicius Costa Gomes __le16 ediv; 4528aab4757SVinicius Costa Gomes 4538aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4548aab4757SVinicius Costa Gomes ediv = 0; 4558aab4757SVinicius Costa Gomes 4568aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); 4578aab4757SVinicius Costa Gomes swap128(key, stk); 4588aab4757SVinicius Costa Gomes 459f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 460f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4618aab4757SVinicius Costa Gomes 46251a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) { 4638aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4648aab4757SVinicius Costa Gomes goto error; 4658aab4757SVinicius Costa Gomes } 4668aab4757SVinicius Costa Gomes 4678aab4757SVinicius Costa Gomes hci_le_start_enc(hcon, ediv, rand, stk); 468f7aa611aSVinicius Costa Gomes hcon->enc_key_size = smp->enc_key_size; 4698aab4757SVinicius Costa Gomes } else { 4708aab4757SVinicius Costa Gomes u8 stk[16], r[16], rand[8]; 4718aab4757SVinicius Costa Gomes __le16 ediv; 4728aab4757SVinicius Costa Gomes 4738aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4748aab4757SVinicius Costa Gomes ediv = 0; 4758aab4757SVinicius Costa Gomes 4768aab4757SVinicius Costa Gomes swap128(smp->prnd, r); 4778aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 4788aab4757SVinicius Costa Gomes 4798aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); 4808aab4757SVinicius Costa Gomes swap128(key, stk); 4818aab4757SVinicius Costa Gomes 482f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 483f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4848aab4757SVinicius Costa Gomes 485ce39fb4eSMarcel Holtmann hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, 48604124681SGustavo F. Padovan HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, 48704124681SGustavo F. Padovan ediv, rand); 4888aab4757SVinicius Costa Gomes } 4898aab4757SVinicius Costa Gomes 4908aab4757SVinicius Costa Gomes return; 4918aab4757SVinicius Costa Gomes 4928aab4757SVinicius Costa Gomes error: 4934f957a76SBrian Gix smp_failure(conn, reason, 1); 4948aab4757SVinicius Costa Gomes } 4958aab4757SVinicius Costa Gomes 4968aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 4978aab4757SVinicius Costa Gomes { 4988aab4757SVinicius Costa Gomes struct smp_chan *smp; 4998aab4757SVinicius Costa Gomes 500f1560463SMarcel Holtmann smp = kzalloc(sizeof(*smp), GFP_ATOMIC); 5018aab4757SVinicius Costa Gomes if (!smp) 5028aab4757SVinicius Costa Gomes return NULL; 5038aab4757SVinicius Costa Gomes 5048aab4757SVinicius Costa Gomes INIT_WORK(&smp->confirm, confirm_work); 5058aab4757SVinicius Costa Gomes INIT_WORK(&smp->random, random_work); 5068aab4757SVinicius Costa Gomes 5078aab4757SVinicius Costa Gomes smp->conn = conn; 5088aab4757SVinicius Costa Gomes conn->smp_chan = smp; 5092b64d153SBrian Gix conn->hcon->smp_conn = conn; 5108aab4757SVinicius Costa Gomes 5118aab4757SVinicius Costa Gomes hci_conn_hold(conn->hcon); 5128aab4757SVinicius Costa Gomes 5138aab4757SVinicius Costa Gomes return smp; 5148aab4757SVinicius Costa Gomes } 5158aab4757SVinicius Costa Gomes 5168aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn) 5178aab4757SVinicius Costa Gomes { 518c8eb9690SBrian Gix struct smp_chan *smp = conn->smp_chan; 519c8eb9690SBrian Gix 520f1c09c07SVinicius Costa Gomes BUG_ON(!smp); 521c8eb9690SBrian Gix 522c8eb9690SBrian Gix if (smp->tfm) 523c8eb9690SBrian Gix crypto_free_blkcipher(smp->tfm); 524c8eb9690SBrian Gix 525c8eb9690SBrian Gix kfree(smp); 526c8eb9690SBrian Gix conn->smp_chan = NULL; 5272b64d153SBrian Gix conn->hcon->smp_conn = NULL; 52876a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 5298aab4757SVinicius Costa Gomes } 5308aab4757SVinicius Costa Gomes 5312b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) 5322b64d153SBrian Gix { 5332b64d153SBrian Gix struct l2cap_conn *conn = hcon->smp_conn; 5342b64d153SBrian Gix struct smp_chan *smp; 5352b64d153SBrian Gix u32 value; 5362b64d153SBrian Gix u8 key[16]; 5372b64d153SBrian Gix 5382b64d153SBrian Gix BT_DBG(""); 5392b64d153SBrian Gix 5402b64d153SBrian Gix if (!conn) 5412b64d153SBrian Gix return -ENOTCONN; 5422b64d153SBrian Gix 5432b64d153SBrian Gix smp = conn->smp_chan; 5442b64d153SBrian Gix 5452b64d153SBrian Gix switch (mgmt_op) { 5462b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_REPLY: 5472b64d153SBrian Gix value = le32_to_cpu(passkey); 5482b64d153SBrian Gix memset(key, 0, sizeof(key)); 5492b64d153SBrian Gix BT_DBG("PassKey: %d", value); 5502b64d153SBrian Gix put_unaligned_le32(value, key); 5512b64d153SBrian Gix swap128(key, smp->tk); 5522b64d153SBrian Gix /* Fall Through */ 5532b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_REPLY: 5542b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 5552b64d153SBrian Gix break; 5562b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_NEG_REPLY: 5572b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_NEG_REPLY: 5582b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5592b64d153SBrian Gix return 0; 5602b64d153SBrian Gix default: 5612b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5622b64d153SBrian Gix return -EOPNOTSUPP; 5632b64d153SBrian Gix } 5642b64d153SBrian Gix 5652b64d153SBrian Gix /* If it is our turn to send Pairing Confirm, do so now */ 5662b64d153SBrian Gix if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags)) 5672b64d153SBrian Gix queue_work(hcon->hdev->workqueue, &smp->confirm); 5682b64d153SBrian Gix 5692b64d153SBrian Gix return 0; 5702b64d153SBrian Gix } 5712b64d153SBrian Gix 572da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 57388ba43b6SAnderson Briglia { 5743158c50cSVinicius Costa Gomes struct smp_cmd_pairing rsp, *req = (void *) skb->data; 5758aab4757SVinicius Costa Gomes struct smp_chan *smp; 5763158c50cSVinicius Costa Gomes u8 key_size; 5772b64d153SBrian Gix u8 auth = SMP_AUTH_NONE; 5788aab4757SVinicius Costa Gomes int ret; 57988ba43b6SAnderson Briglia 58088ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 58188ba43b6SAnderson Briglia 5822b64d153SBrian Gix if (conn->hcon->link_mode & HCI_LM_MASTER) 5832b64d153SBrian Gix return SMP_CMD_NOTSUPP; 5842b64d153SBrian Gix 58551a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 5868aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 587d08fd0e7SAndrei Emeltchenko else 5888aab4757SVinicius Costa Gomes smp = conn->smp_chan; 589d26a2345SVinicius Costa Gomes 590d08fd0e7SAndrei Emeltchenko if (!smp) 591d08fd0e7SAndrei Emeltchenko return SMP_UNSPECIFIED; 592d08fd0e7SAndrei Emeltchenko 5931c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5941c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], req, sizeof(*req)); 5953158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*req)); 59688ba43b6SAnderson Briglia 5972b64d153SBrian Gix /* We didn't start the pairing, so match remote */ 5982b64d153SBrian Gix if (req->auth_req & SMP_AUTH_BONDING) 5992b64d153SBrian Gix auth = req->auth_req; 600da85e5e5SVinicius Costa Gomes 601fdde0a26SIdo Yariv conn->hcon->pending_sec_level = authreq_to_seclevel(auth); 602fdde0a26SIdo Yariv 6032b64d153SBrian Gix build_pairing_cmd(conn, req, &rsp, auth); 6043158c50cSVinicius Costa Gomes 6053158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp.max_key_size); 6063158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6073158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 60888ba43b6SAnderson Briglia 6098aab4757SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6108aab4757SVinicius Costa Gomes if (ret) 6118aab4757SVinicius Costa Gomes return SMP_UNSPECIFIED; 6128aab4757SVinicius Costa Gomes 6131c1def09SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6141c1def09SVinicius Costa Gomes memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 615f01ead31SAnderson Briglia 6163158c50cSVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 617da85e5e5SVinicius Costa Gomes 6182b64d153SBrian Gix /* Request setup of TK */ 6192b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); 6202b64d153SBrian Gix if (ret) 6212b64d153SBrian Gix return SMP_UNSPECIFIED; 6222b64d153SBrian Gix 623da85e5e5SVinicius Costa Gomes return 0; 62488ba43b6SAnderson Briglia } 62588ba43b6SAnderson Briglia 626da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 62788ba43b6SAnderson Briglia { 6283158c50cSVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 6291c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6308aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6312b64d153SBrian Gix u8 key_size, auth = SMP_AUTH_NONE; 6327d24ddccSAnderson Briglia int ret; 63388ba43b6SAnderson Briglia 63488ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 63588ba43b6SAnderson Briglia 6362b64d153SBrian Gix if (!(conn->hcon->link_mode & HCI_LM_MASTER)) 6372b64d153SBrian Gix return SMP_CMD_NOTSUPP; 6382b64d153SBrian Gix 6393158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*rsp)); 640da85e5e5SVinicius Costa Gomes 6411c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 6423158c50cSVinicius Costa Gomes 6433158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp->max_key_size); 6443158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6453158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 6463158c50cSVinicius Costa Gomes 6471c1def09SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6487d24ddccSAnderson Briglia if (ret) 649da85e5e5SVinicius Costa Gomes return SMP_UNSPECIFIED; 6507d24ddccSAnderson Briglia 6518aab4757SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6528aab4757SVinicius Costa Gomes memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 6537d24ddccSAnderson Briglia 6542b64d153SBrian Gix if ((req->auth_req & SMP_AUTH_BONDING) && 6552b64d153SBrian Gix (rsp->auth_req & SMP_AUTH_BONDING)) 6562b64d153SBrian Gix auth = SMP_AUTH_BONDING; 6572b64d153SBrian Gix 6582b64d153SBrian Gix auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; 6592b64d153SBrian Gix 660476585ecSJohan Hedberg ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); 6612b64d153SBrian Gix if (ret) 6622b64d153SBrian Gix return SMP_UNSPECIFIED; 6632b64d153SBrian Gix 6642b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 6652b64d153SBrian Gix 6662b64d153SBrian Gix /* Can't compose response until we have been confirmed */ 6672b64d153SBrian Gix if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) 6682b64d153SBrian Gix return 0; 6692b64d153SBrian Gix 6708aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 671da85e5e5SVinicius Costa Gomes 672da85e5e5SVinicius Costa Gomes return 0; 67388ba43b6SAnderson Briglia } 67488ba43b6SAnderson Briglia 675da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 67688ba43b6SAnderson Briglia { 6771c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6788aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6797d24ddccSAnderson Briglia 68088ba43b6SAnderson Briglia BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 68188ba43b6SAnderson Briglia 6821c1def09SVinicius Costa Gomes memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 6831c1def09SVinicius Costa Gomes skb_pull(skb, sizeof(smp->pcnf)); 6847d24ddccSAnderson Briglia 68588ba43b6SAnderson Briglia if (conn->hcon->out) { 6867d24ddccSAnderson Briglia u8 random[16]; 68788ba43b6SAnderson Briglia 6881c1def09SVinicius Costa Gomes swap128(smp->prnd, random); 68988ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 6907d24ddccSAnderson Briglia random); 6912b64d153SBrian Gix } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { 6928aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 6932b64d153SBrian Gix } else { 6942b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 69588ba43b6SAnderson Briglia } 696da85e5e5SVinicius Costa Gomes 697da85e5e5SVinicius Costa Gomes return 0; 69888ba43b6SAnderson Briglia } 69988ba43b6SAnderson Briglia 700da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 70188ba43b6SAnderson Briglia { 7021c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7038aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 7047d24ddccSAnderson Briglia 7058aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 7067d24ddccSAnderson Briglia 7078aab4757SVinicius Costa Gomes swap128(skb->data, smp->rrnd); 7088aab4757SVinicius Costa Gomes skb_pull(skb, sizeof(smp->rrnd)); 70988ba43b6SAnderson Briglia 7108aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->random); 711da85e5e5SVinicius Costa Gomes 712da85e5e5SVinicius Costa Gomes return 0; 71388ba43b6SAnderson Briglia } 71488ba43b6SAnderson Briglia 7154dab7864SJohan Hedberg static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) 716988c5997SVinicius Costa Gomes { 717c9839a11SVinicius Costa Gomes struct smp_ltk *key; 718988c5997SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 719988c5997SVinicius Costa Gomes 720ce39fb4eSMarcel Holtmann key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type); 721988c5997SVinicius Costa Gomes if (!key) 722988c5997SVinicius Costa Gomes return 0; 723988c5997SVinicius Costa Gomes 7244dab7864SJohan Hedberg if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) 7254dab7864SJohan Hedberg return 0; 7264dab7864SJohan Hedberg 72751a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) 728988c5997SVinicius Costa Gomes return 1; 729988c5997SVinicius Costa Gomes 730c9839a11SVinicius Costa Gomes hci_le_start_enc(hcon, key->ediv, key->rand, key->val); 731c9839a11SVinicius Costa Gomes hcon->enc_key_size = key->enc_size; 732988c5997SVinicius Costa Gomes 733988c5997SVinicius Costa Gomes return 1; 734988c5997SVinicius Costa Gomes } 735f1560463SMarcel Holtmann 736da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) 73788ba43b6SAnderson Briglia { 73888ba43b6SAnderson Briglia struct smp_cmd_security_req *rp = (void *) skb->data; 73988ba43b6SAnderson Briglia struct smp_cmd_pairing cp; 740f1cb9af5SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 7418aab4757SVinicius Costa Gomes struct smp_chan *smp; 74288ba43b6SAnderson Briglia 74388ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 74488ba43b6SAnderson Briglia 7452b64d153SBrian Gix hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); 746feb45eb5SVinicius Costa Gomes 7474dab7864SJohan Hedberg if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) 748988c5997SVinicius Costa Gomes return 0; 749988c5997SVinicius Costa Gomes 75051a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 751da85e5e5SVinicius Costa Gomes return 0; 752f1cb9af5SVinicius Costa Gomes 7538aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 754d26a2345SVinicius Costa Gomes 75588ba43b6SAnderson Briglia skb_pull(skb, sizeof(*rp)); 75688ba43b6SAnderson Briglia 757da85e5e5SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 75854790f73SVinicius Costa Gomes build_pairing_cmd(conn, &cp, NULL, rp->auth_req); 75988ba43b6SAnderson Briglia 7601c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 7611c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 762f01ead31SAnderson Briglia 76388ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 764f1cb9af5SVinicius Costa Gomes 765da85e5e5SVinicius Costa Gomes return 0; 76688ba43b6SAnderson Briglia } 76788ba43b6SAnderson Briglia 768cc110922SVinicius Costa Gomes int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) 769eb492e01SAnderson Briglia { 770cc110922SVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 7711c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7722b64d153SBrian Gix __u8 authreq; 773eb492e01SAnderson Briglia 7743a0259bbSVinicius Costa Gomes BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); 7753a0259bbSVinicius Costa Gomes 776757aee0fSJohan Hedberg if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) 7772e65c9d2SAndre Guedes return 1; 7782e65c9d2SAndre Guedes 779f1cb9af5SVinicius Costa Gomes if (sec_level == BT_SECURITY_LOW) 780eb492e01SAnderson Briglia return 1; 781f1cb9af5SVinicius Costa Gomes 782f1cb9af5SVinicius Costa Gomes if (hcon->sec_level >= sec_level) 783f1cb9af5SVinicius Costa Gomes return 1; 784f1cb9af5SVinicius Costa Gomes 785988c5997SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) 7864dab7864SJohan Hedberg if (smp_ltk_encrypt(conn, sec_level)) 787d26a2345SVinicius Costa Gomes goto done; 788d26a2345SVinicius Costa Gomes 78951a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 790d26a2345SVinicius Costa Gomes return 0; 791d26a2345SVinicius Costa Gomes 7928aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 7932b64d153SBrian Gix if (!smp) 7942b64d153SBrian Gix return 1; 7952b64d153SBrian Gix 7962b64d153SBrian Gix authreq = seclevel_to_authreq(sec_level); 797d26a2345SVinicius Costa Gomes 798d26a2345SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) { 799d26a2345SVinicius Costa Gomes struct smp_cmd_pairing cp; 800f01ead31SAnderson Briglia 8012b64d153SBrian Gix build_pairing_cmd(conn, &cp, NULL, authreq); 8021c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 8031c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 804f01ead31SAnderson Briglia 805eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 806eb492e01SAnderson Briglia } else { 807eb492e01SAnderson Briglia struct smp_cmd_security_req cp; 8082b64d153SBrian Gix cp.auth_req = authreq; 809eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 810eb492e01SAnderson Briglia } 811eb492e01SAnderson Briglia 81202bc7455SVinicius Costa Gomes done: 813f1cb9af5SVinicius Costa Gomes hcon->pending_sec_level = sec_level; 814f1cb9af5SVinicius Costa Gomes 815eb492e01SAnderson Briglia return 0; 816eb492e01SAnderson Briglia } 817eb492e01SAnderson Briglia 8187034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) 8197034b911SVinicius Costa Gomes { 82016b90839SVinicius Costa Gomes struct smp_cmd_encrypt_info *rp = (void *) skb->data; 8211c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 82216b90839SVinicius Costa Gomes 82316b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 82416b90839SVinicius Costa Gomes 8251c1def09SVinicius Costa Gomes memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); 82616b90839SVinicius Costa Gomes 8277034b911SVinicius Costa Gomes return 0; 8287034b911SVinicius Costa Gomes } 8297034b911SVinicius Costa Gomes 8307034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) 8317034b911SVinicius Costa Gomes { 83216b90839SVinicius Costa Gomes struct smp_cmd_master_ident *rp = (void *) skb->data; 8331c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 834c9839a11SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 835c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 836c9839a11SVinicius Costa Gomes u8 authenticated; 8377034b911SVinicius Costa Gomes 83816b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 83916b90839SVinicius Costa Gomes 840c9839a11SVinicius Costa Gomes hci_dev_lock(hdev); 841ce39fb4eSMarcel Holtmann authenticated = (hcon->sec_level == BT_SECURITY_HIGH); 842ce39fb4eSMarcel Holtmann hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1, 843ce39fb4eSMarcel Holtmann authenticated, smp->tk, smp->enc_key_size, 84404124681SGustavo F. Padovan rp->ediv, rp->rand); 8457034b911SVinicius Costa Gomes smp_distribute_keys(conn, 1); 846c9839a11SVinicius Costa Gomes hci_dev_unlock(hdev); 8477034b911SVinicius Costa Gomes 8487034b911SVinicius Costa Gomes return 0; 8497034b911SVinicius Costa Gomes } 8507034b911SVinicius Costa Gomes 851eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 852eb492e01SAnderson Briglia { 8537b9899dbSMarcel Holtmann struct hci_conn *hcon = conn->hcon; 85492381f5cSMarcel Holtmann __u8 code, reason; 855eb492e01SAnderson Briglia int err = 0; 856eb492e01SAnderson Briglia 8577b9899dbSMarcel Holtmann if (hcon->type != LE_LINK) { 8587b9899dbSMarcel Holtmann kfree_skb(skb); 8593432711fSJohan Hedberg return 0; 8607b9899dbSMarcel Holtmann } 8617b9899dbSMarcel Holtmann 86292381f5cSMarcel Holtmann if (skb->len < 1) { 86392381f5cSMarcel Holtmann kfree_skb(skb); 86492381f5cSMarcel Holtmann return -EILSEQ; 86592381f5cSMarcel Holtmann } 86692381f5cSMarcel Holtmann 86706ae3314SMarcel Holtmann if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { 8682e65c9d2SAndre Guedes err = -ENOTSUPP; 8692e65c9d2SAndre Guedes reason = SMP_PAIRING_NOTSUPP; 8702e65c9d2SAndre Guedes goto done; 8712e65c9d2SAndre Guedes } 8722e65c9d2SAndre Guedes 87392381f5cSMarcel Holtmann code = skb->data[0]; 874eb492e01SAnderson Briglia skb_pull(skb, sizeof(code)); 875eb492e01SAnderson Briglia 8768cf9fa12SJohan Hedberg /* 8778cf9fa12SJohan Hedberg * The SMP context must be initialized for all other PDUs except 8788cf9fa12SJohan Hedberg * pairing and security requests. If we get any other PDU when 8798cf9fa12SJohan Hedberg * not initialized simply disconnect (done if this function 8808cf9fa12SJohan Hedberg * returns an error). 8818cf9fa12SJohan Hedberg */ 8828cf9fa12SJohan Hedberg if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ && 8838cf9fa12SJohan Hedberg !conn->smp_chan) { 8848cf9fa12SJohan Hedberg BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); 8858cf9fa12SJohan Hedberg kfree_skb(skb); 8868cf9fa12SJohan Hedberg return -ENOTSUPP; 8878cf9fa12SJohan Hedberg } 8888cf9fa12SJohan Hedberg 889eb492e01SAnderson Briglia switch (code) { 890eb492e01SAnderson Briglia case SMP_CMD_PAIRING_REQ: 891da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_req(conn, skb); 892eb492e01SAnderson Briglia break; 893eb492e01SAnderson Briglia 894eb492e01SAnderson Briglia case SMP_CMD_PAIRING_FAIL: 8954f957a76SBrian Gix smp_failure(conn, skb->data[0], 0); 896da85e5e5SVinicius Costa Gomes reason = 0; 897da85e5e5SVinicius Costa Gomes err = -EPERM; 898eb492e01SAnderson Briglia break; 899eb492e01SAnderson Briglia 900eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RSP: 901da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_rsp(conn, skb); 90288ba43b6SAnderson Briglia break; 90388ba43b6SAnderson Briglia 90488ba43b6SAnderson Briglia case SMP_CMD_SECURITY_REQ: 905da85e5e5SVinicius Costa Gomes reason = smp_cmd_security_req(conn, skb); 90688ba43b6SAnderson Briglia break; 90788ba43b6SAnderson Briglia 908eb492e01SAnderson Briglia case SMP_CMD_PAIRING_CONFIRM: 909da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_confirm(conn, skb); 91088ba43b6SAnderson Briglia break; 91188ba43b6SAnderson Briglia 912eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RANDOM: 913da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_random(conn, skb); 91488ba43b6SAnderson Briglia break; 91588ba43b6SAnderson Briglia 916eb492e01SAnderson Briglia case SMP_CMD_ENCRYPT_INFO: 9177034b911SVinicius Costa Gomes reason = smp_cmd_encrypt_info(conn, skb); 9187034b911SVinicius Costa Gomes break; 9197034b911SVinicius Costa Gomes 920eb492e01SAnderson Briglia case SMP_CMD_MASTER_IDENT: 9217034b911SVinicius Costa Gomes reason = smp_cmd_master_ident(conn, skb); 9227034b911SVinicius Costa Gomes break; 9237034b911SVinicius Costa Gomes 924eb492e01SAnderson Briglia case SMP_CMD_IDENT_INFO: 925eb492e01SAnderson Briglia case SMP_CMD_IDENT_ADDR_INFO: 926eb492e01SAnderson Briglia case SMP_CMD_SIGN_INFO: 9277034b911SVinicius Costa Gomes /* Just ignored */ 9287034b911SVinicius Costa Gomes reason = 0; 9297034b911SVinicius Costa Gomes break; 9307034b911SVinicius Costa Gomes 931eb492e01SAnderson Briglia default: 932eb492e01SAnderson Briglia BT_DBG("Unknown command code 0x%2.2x", code); 933eb492e01SAnderson Briglia 934eb492e01SAnderson Briglia reason = SMP_CMD_NOTSUPP; 9353a0259bbSVinicius Costa Gomes err = -EOPNOTSUPP; 9363a0259bbSVinicius Costa Gomes goto done; 9373a0259bbSVinicius Costa Gomes } 9383a0259bbSVinicius Costa Gomes 9393a0259bbSVinicius Costa Gomes done: 9403a0259bbSVinicius Costa Gomes if (reason) 9414f957a76SBrian Gix smp_failure(conn, reason, 1); 942eb492e01SAnderson Briglia 943eb492e01SAnderson Briglia kfree_skb(skb); 944eb492e01SAnderson Briglia return err; 945eb492e01SAnderson Briglia } 9467034b911SVinicius Costa Gomes 9477034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) 9487034b911SVinicius Costa Gomes { 9497034b911SVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp; 9501c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 9517034b911SVinicius Costa Gomes __u8 *keydist; 9527034b911SVinicius Costa Gomes 9537034b911SVinicius Costa Gomes BT_DBG("conn %p force %d", conn, force); 9547034b911SVinicius Costa Gomes 95551a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 956d26a2345SVinicius Costa Gomes return 0; 957d26a2345SVinicius Costa Gomes 9581c1def09SVinicius Costa Gomes rsp = (void *) &smp->prsp[1]; 9597034b911SVinicius Costa Gomes 9607034b911SVinicius Costa Gomes /* The responder sends its keys first */ 9617034b911SVinicius Costa Gomes if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) 9627034b911SVinicius Costa Gomes return 0; 9637034b911SVinicius Costa Gomes 9641c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 9657034b911SVinicius Costa Gomes 9667034b911SVinicius Costa Gomes if (conn->hcon->out) { 9677034b911SVinicius Costa Gomes keydist = &rsp->init_key_dist; 9687034b911SVinicius Costa Gomes *keydist &= req->init_key_dist; 9697034b911SVinicius Costa Gomes } else { 9707034b911SVinicius Costa Gomes keydist = &rsp->resp_key_dist; 9717034b911SVinicius Costa Gomes *keydist &= req->resp_key_dist; 9727034b911SVinicius Costa Gomes } 9737034b911SVinicius Costa Gomes 9747034b911SVinicius Costa Gomes 9757034b911SVinicius Costa Gomes BT_DBG("keydist 0x%x", *keydist); 9767034b911SVinicius Costa Gomes 9777034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ENC_KEY) { 9787034b911SVinicius Costa Gomes struct smp_cmd_encrypt_info enc; 9797034b911SVinicius Costa Gomes struct smp_cmd_master_ident ident; 980c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 981c9839a11SVinicius Costa Gomes u8 authenticated; 9827034b911SVinicius Costa Gomes __le16 ediv; 9837034b911SVinicius Costa Gomes 9847034b911SVinicius Costa Gomes get_random_bytes(enc.ltk, sizeof(enc.ltk)); 9857034b911SVinicius Costa Gomes get_random_bytes(&ediv, sizeof(ediv)); 9867034b911SVinicius Costa Gomes get_random_bytes(ident.rand, sizeof(ident.rand)); 9877034b911SVinicius Costa Gomes 9887034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 9897034b911SVinicius Costa Gomes 990c9839a11SVinicius Costa Gomes authenticated = hcon->sec_level == BT_SECURITY_HIGH; 991ce39fb4eSMarcel Holtmann hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, 992c9839a11SVinicius Costa Gomes HCI_SMP_LTK_SLAVE, 1, authenticated, 99304124681SGustavo F. Padovan enc.ltk, smp->enc_key_size, ediv, ident.rand); 99416b90839SVinicius Costa Gomes 99558115373SAndrei Emeltchenko ident.ediv = ediv; 9967034b911SVinicius Costa Gomes 9977034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); 9987034b911SVinicius Costa Gomes 9997034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ENC_KEY; 10007034b911SVinicius Costa Gomes } 10017034b911SVinicius Costa Gomes 10027034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ID_KEY) { 10037034b911SVinicius Costa Gomes struct smp_cmd_ident_addr_info addrinfo; 10047034b911SVinicius Costa Gomes struct smp_cmd_ident_info idinfo; 10057034b911SVinicius Costa Gomes 10067034b911SVinicius Costa Gomes /* Send a dummy key */ 10077034b911SVinicius Costa Gomes get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); 10087034b911SVinicius Costa Gomes 10097034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 10107034b911SVinicius Costa Gomes 10117034b911SVinicius Costa Gomes /* Just public address */ 10127034b911SVinicius Costa Gomes memset(&addrinfo, 0, sizeof(addrinfo)); 10132b36a562SMarcel Holtmann bacpy(&addrinfo.bdaddr, &conn->hcon->src); 10147034b911SVinicius Costa Gomes 10157034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 10167034b911SVinicius Costa Gomes &addrinfo); 10177034b911SVinicius Costa Gomes 10187034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ID_KEY; 10197034b911SVinicius Costa Gomes } 10207034b911SVinicius Costa Gomes 10217034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_SIGN) { 10227034b911SVinicius Costa Gomes struct smp_cmd_sign_info sign; 10237034b911SVinicius Costa Gomes 10247034b911SVinicius Costa Gomes /* Send a dummy key */ 10257034b911SVinicius Costa Gomes get_random_bytes(sign.csrk, sizeof(sign.csrk)); 10267034b911SVinicius Costa Gomes 10277034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 10287034b911SVinicius Costa Gomes 10297034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_SIGN; 10307034b911SVinicius Costa Gomes } 10317034b911SVinicius Costa Gomes 1032d26a2345SVinicius Costa Gomes if (conn->hcon->out || force) { 103351a8efd7SJohan Hedberg clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); 10346c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 10358aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1036d26a2345SVinicius Costa Gomes } 1037d26a2345SVinicius Costa Gomes 10387034b911SVinicius Costa Gomes return 0; 10397034b911SVinicius Costa Gomes } 1040