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> 31eb492e01SAnderson Briglia #include <net/bluetooth/smp.h> 32d22ef0bcSAnderson Briglia 3317b02e62SMarcel Holtmann #define SMP_TIMEOUT msecs_to_jiffies(30000) 345d3de7dfSVinicius Costa Gomes 35d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16]) 36d22ef0bcSAnderson Briglia { 37d22ef0bcSAnderson Briglia int i; 38d22ef0bcSAnderson Briglia for (i = 0; i < 16; i++) 39d22ef0bcSAnderson Briglia dst[15 - i] = src[i]; 40d22ef0bcSAnderson Briglia } 41d22ef0bcSAnderson Briglia 42d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7]) 43d22ef0bcSAnderson Briglia { 44d22ef0bcSAnderson Briglia int i; 45d22ef0bcSAnderson Briglia for (i = 0; i < 7; i++) 46d22ef0bcSAnderson Briglia dst[6 - i] = src[i]; 47d22ef0bcSAnderson Briglia } 48d22ef0bcSAnderson Briglia 49d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) 50d22ef0bcSAnderson Briglia { 51d22ef0bcSAnderson Briglia struct blkcipher_desc desc; 52d22ef0bcSAnderson Briglia struct scatterlist sg; 53d22ef0bcSAnderson Briglia int err, iv_len; 54d22ef0bcSAnderson Briglia unsigned char iv[128]; 55d22ef0bcSAnderson Briglia 56d22ef0bcSAnderson Briglia if (tfm == NULL) { 57d22ef0bcSAnderson Briglia BT_ERR("tfm %p", tfm); 58d22ef0bcSAnderson Briglia return -EINVAL; 59d22ef0bcSAnderson Briglia } 60d22ef0bcSAnderson Briglia 61d22ef0bcSAnderson Briglia desc.tfm = tfm; 62d22ef0bcSAnderson Briglia desc.flags = 0; 63d22ef0bcSAnderson Briglia 64d22ef0bcSAnderson Briglia err = crypto_blkcipher_setkey(tfm, k, 16); 65d22ef0bcSAnderson Briglia if (err) { 66d22ef0bcSAnderson Briglia BT_ERR("cipher setkey failed: %d", err); 67d22ef0bcSAnderson Briglia return err; 68d22ef0bcSAnderson Briglia } 69d22ef0bcSAnderson Briglia 70d22ef0bcSAnderson Briglia sg_init_one(&sg, r, 16); 71d22ef0bcSAnderson Briglia 72d22ef0bcSAnderson Briglia iv_len = crypto_blkcipher_ivsize(tfm); 73d22ef0bcSAnderson Briglia if (iv_len) { 74d22ef0bcSAnderson Briglia memset(&iv, 0xff, iv_len); 75d22ef0bcSAnderson Briglia crypto_blkcipher_set_iv(tfm, iv, iv_len); 76d22ef0bcSAnderson Briglia } 77d22ef0bcSAnderson Briglia 78d22ef0bcSAnderson Briglia err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); 79d22ef0bcSAnderson Briglia if (err) 80d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error %d", err); 81d22ef0bcSAnderson Briglia 82d22ef0bcSAnderson Briglia return err; 83d22ef0bcSAnderson Briglia } 84d22ef0bcSAnderson Briglia 85d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], 86d22ef0bcSAnderson Briglia u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, 87d22ef0bcSAnderson Briglia u8 _rat, bdaddr_t *ra, u8 res[16]) 88d22ef0bcSAnderson Briglia { 89d22ef0bcSAnderson Briglia u8 p1[16], p2[16]; 90d22ef0bcSAnderson Briglia int err; 91d22ef0bcSAnderson Briglia 92d22ef0bcSAnderson Briglia memset(p1, 0, 16); 93d22ef0bcSAnderson Briglia 94d22ef0bcSAnderson Briglia /* p1 = pres || preq || _rat || _iat */ 95d22ef0bcSAnderson Briglia swap56(pres, p1); 96d22ef0bcSAnderson Briglia swap56(preq, p1 + 7); 97d22ef0bcSAnderson Briglia p1[14] = _rat; 98d22ef0bcSAnderson Briglia p1[15] = _iat; 99d22ef0bcSAnderson Briglia 100d22ef0bcSAnderson Briglia memset(p2, 0, 16); 101d22ef0bcSAnderson Briglia 102d22ef0bcSAnderson Briglia /* p2 = padding || ia || ra */ 103d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 4), ia); 104d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 10), ra); 105d22ef0bcSAnderson Briglia 106d22ef0bcSAnderson Briglia /* res = r XOR p1 */ 107d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); 108d22ef0bcSAnderson Briglia 109d22ef0bcSAnderson Briglia /* res = e(k, res) */ 110d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 111d22ef0bcSAnderson Briglia if (err) { 112d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 113d22ef0bcSAnderson Briglia return err; 114d22ef0bcSAnderson Briglia } 115d22ef0bcSAnderson Briglia 116d22ef0bcSAnderson Briglia /* res = res XOR p2 */ 117d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); 118d22ef0bcSAnderson Briglia 119d22ef0bcSAnderson Briglia /* res = e(k, res) */ 120d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 121d22ef0bcSAnderson Briglia if (err) 122d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 123d22ef0bcSAnderson Briglia 124d22ef0bcSAnderson Briglia return err; 125d22ef0bcSAnderson Briglia } 126d22ef0bcSAnderson Briglia 127d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], 128d22ef0bcSAnderson Briglia u8 r1[16], u8 r2[16], u8 _r[16]) 129d22ef0bcSAnderson Briglia { 130d22ef0bcSAnderson Briglia int err; 131d22ef0bcSAnderson Briglia 132d22ef0bcSAnderson Briglia /* Just least significant octets from r1 and r2 are considered */ 133d22ef0bcSAnderson Briglia memcpy(_r, r1 + 8, 8); 134d22ef0bcSAnderson Briglia memcpy(_r + 8, r2 + 8, 8); 135d22ef0bcSAnderson Briglia 136d22ef0bcSAnderson Briglia err = smp_e(tfm, k, _r); 137d22ef0bcSAnderson Briglia if (err) 138d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 139d22ef0bcSAnderson Briglia 140d22ef0bcSAnderson Briglia return err; 141d22ef0bcSAnderson Briglia } 142d22ef0bcSAnderson Briglia 143d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf) 144d22ef0bcSAnderson Briglia { 145d22ef0bcSAnderson Briglia get_random_bytes(buf, 16); 146d22ef0bcSAnderson Briglia 147d22ef0bcSAnderson Briglia return 0; 148d22ef0bcSAnderson Briglia } 149eb492e01SAnderson Briglia 150eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, 151eb492e01SAnderson Briglia u16 dlen, void *data) 152eb492e01SAnderson Briglia { 153eb492e01SAnderson Briglia struct sk_buff *skb; 154eb492e01SAnderson Briglia struct l2cap_hdr *lh; 155eb492e01SAnderson Briglia int len; 156eb492e01SAnderson Briglia 157eb492e01SAnderson Briglia len = L2CAP_HDR_SIZE + sizeof(code) + dlen; 158eb492e01SAnderson Briglia 159eb492e01SAnderson Briglia if (len > conn->mtu) 160eb492e01SAnderson Briglia return NULL; 161eb492e01SAnderson Briglia 162eb492e01SAnderson Briglia skb = bt_skb_alloc(len, GFP_ATOMIC); 163eb492e01SAnderson Briglia if (!skb) 164eb492e01SAnderson Briglia return NULL; 165eb492e01SAnderson Briglia 166eb492e01SAnderson Briglia lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 167eb492e01SAnderson Briglia lh->len = cpu_to_le16(sizeof(code) + dlen); 168d8aece2aSSyam Sidhardhan lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); 169eb492e01SAnderson Briglia 170eb492e01SAnderson Briglia memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); 171eb492e01SAnderson Briglia 172eb492e01SAnderson Briglia memcpy(skb_put(skb, dlen), data, dlen); 173eb492e01SAnderson Briglia 174eb492e01SAnderson Briglia return skb; 175eb492e01SAnderson Briglia } 176eb492e01SAnderson Briglia 177eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) 178eb492e01SAnderson Briglia { 179eb492e01SAnderson Briglia struct sk_buff *skb = smp_build_cmd(conn, code, len, data); 180eb492e01SAnderson Briglia 181eb492e01SAnderson Briglia BT_DBG("code 0x%2.2x", code); 182eb492e01SAnderson Briglia 183eb492e01SAnderson Briglia if (!skb) 184eb492e01SAnderson Briglia return; 185eb492e01SAnderson Briglia 18673d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 18773d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, 0); 188e2dcd113SVinicius Costa Gomes 1896c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 19017b02e62SMarcel Holtmann schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT); 191eb492e01SAnderson Briglia } 192eb492e01SAnderson Briglia 1932b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq) 1942b64d153SBrian Gix { 1952b64d153SBrian Gix if (authreq & SMP_AUTH_MITM) 1962b64d153SBrian Gix return BT_SECURITY_HIGH; 1972b64d153SBrian Gix else 1982b64d153SBrian Gix return BT_SECURITY_MEDIUM; 1992b64d153SBrian Gix } 2002b64d153SBrian Gix 2012b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level) 2022b64d153SBrian Gix { 2032b64d153SBrian Gix switch (sec_level) { 2042b64d153SBrian Gix case BT_SECURITY_HIGH: 2052b64d153SBrian Gix return SMP_AUTH_MITM | SMP_AUTH_BONDING; 2062b64d153SBrian Gix case BT_SECURITY_MEDIUM: 2072b64d153SBrian Gix return SMP_AUTH_BONDING; 2082b64d153SBrian Gix default: 2092b64d153SBrian Gix return SMP_AUTH_NONE; 2102b64d153SBrian Gix } 2112b64d153SBrian Gix } 2122b64d153SBrian Gix 213b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn, 21454790f73SVinicius Costa Gomes struct smp_cmd_pairing *req, 21554790f73SVinicius Costa Gomes struct smp_cmd_pairing *rsp, 21654790f73SVinicius Costa Gomes __u8 authreq) 217b8e66eacSVinicius Costa Gomes { 2182b64d153SBrian Gix u8 dist_keys = 0; 21954790f73SVinicius Costa Gomes 220a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { 221ca10b5eeSVinicius Costa Gomes dist_keys = SMP_DIST_ENC_KEY; 22254790f73SVinicius Costa Gomes authreq |= SMP_AUTH_BONDING; 2232b64d153SBrian Gix } else { 2242b64d153SBrian Gix authreq &= ~SMP_AUTH_BONDING; 22554790f73SVinicius Costa Gomes } 22654790f73SVinicius Costa Gomes 22754790f73SVinicius Costa Gomes if (rsp == NULL) { 22854790f73SVinicius Costa Gomes req->io_capability = conn->hcon->io_capability; 22954790f73SVinicius Costa Gomes req->oob_flag = SMP_OOB_NOT_PRESENT; 23054790f73SVinicius Costa Gomes req->max_key_size = SMP_MAX_ENC_KEY_SIZE; 2312b64d153SBrian Gix req->init_key_dist = 0; 23254790f73SVinicius Costa Gomes req->resp_key_dist = dist_keys; 23354790f73SVinicius Costa Gomes req->auth_req = authreq; 23454790f73SVinicius Costa Gomes return; 23554790f73SVinicius Costa Gomes } 23654790f73SVinicius Costa Gomes 23754790f73SVinicius Costa Gomes rsp->io_capability = conn->hcon->io_capability; 23854790f73SVinicius Costa Gomes rsp->oob_flag = SMP_OOB_NOT_PRESENT; 23954790f73SVinicius Costa Gomes rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; 2402b64d153SBrian Gix rsp->init_key_dist = 0; 24154790f73SVinicius Costa Gomes rsp->resp_key_dist = req->resp_key_dist & dist_keys; 24254790f73SVinicius Costa Gomes rsp->auth_req = authreq; 243b8e66eacSVinicius Costa Gomes } 244b8e66eacSVinicius Costa Gomes 2453158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) 2463158c50cSVinicius Costa Gomes { 2471c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 2481c1def09SVinicius Costa Gomes 2493158c50cSVinicius Costa Gomes if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || 2503158c50cSVinicius Costa Gomes (max_key_size < SMP_MIN_ENC_KEY_SIZE)) 2513158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 2523158c50cSVinicius Costa Gomes 253f7aa611aSVinicius Costa Gomes smp->enc_key_size = max_key_size; 2543158c50cSVinicius Costa Gomes 2553158c50cSVinicius Costa Gomes return 0; 2563158c50cSVinicius Costa Gomes } 2573158c50cSVinicius Costa Gomes 2584f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) 2594f957a76SBrian Gix { 260bab73cb6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 261bab73cb6SJohan Hedberg 2624f957a76SBrian Gix if (send) 2634f957a76SBrian Gix smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), 2644f957a76SBrian Gix &reason); 2654f957a76SBrian Gix 26651a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); 267bab73cb6SJohan Hedberg mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, 268bab73cb6SJohan Hedberg hcon->dst_type, reason); 269f1c09c07SVinicius Costa Gomes 2706c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 27161a0cfb0SAndre Guedes 27261a0cfb0SAndre Guedes if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 2734f957a76SBrian Gix smp_chan_destroy(conn); 2744f957a76SBrian Gix } 2754f957a76SBrian Gix 2762b64d153SBrian Gix #define JUST_WORKS 0x00 2772b64d153SBrian Gix #define JUST_CFM 0x01 2782b64d153SBrian Gix #define REQ_PASSKEY 0x02 2792b64d153SBrian Gix #define CFM_PASSKEY 0x03 2802b64d153SBrian Gix #define REQ_OOB 0x04 2812b64d153SBrian Gix #define OVERLAP 0xFF 2822b64d153SBrian Gix 2832b64d153SBrian Gix static const u8 gen_method[5][5] = { 2842b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2852b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2862b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 2872b64d153SBrian Gix { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, 2882b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, 2892b64d153SBrian Gix }; 2902b64d153SBrian Gix 2912b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, 2922b64d153SBrian Gix u8 local_io, u8 remote_io) 2932b64d153SBrian Gix { 2942b64d153SBrian Gix struct hci_conn *hcon = conn->hcon; 2952b64d153SBrian Gix struct smp_chan *smp = conn->smp_chan; 2962b64d153SBrian Gix u8 method; 2972b64d153SBrian Gix u32 passkey = 0; 2982b64d153SBrian Gix int ret = 0; 2992b64d153SBrian Gix 3002b64d153SBrian Gix /* Initialize key for JUST WORKS */ 3012b64d153SBrian Gix memset(smp->tk, 0, sizeof(smp->tk)); 3022b64d153SBrian Gix clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3032b64d153SBrian Gix 3042b64d153SBrian Gix BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); 3052b64d153SBrian Gix 3062b64d153SBrian Gix /* If neither side wants MITM, use JUST WORKS */ 3072b64d153SBrian Gix /* If either side has unknown io_caps, use JUST WORKS */ 3082b64d153SBrian Gix /* Otherwise, look up method from the table */ 3092b64d153SBrian Gix if (!(auth & SMP_AUTH_MITM) || 3102b64d153SBrian Gix local_io > SMP_IO_KEYBOARD_DISPLAY || 3112b64d153SBrian Gix remote_io > SMP_IO_KEYBOARD_DISPLAY) 3122b64d153SBrian Gix method = JUST_WORKS; 3132b64d153SBrian Gix else 314b3ff53ffSIdo Yariv method = gen_method[remote_io][local_io]; 3152b64d153SBrian Gix 3162b64d153SBrian Gix /* If not bonding, don't ask user to confirm a Zero TK */ 3172b64d153SBrian Gix if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) 3182b64d153SBrian Gix method = JUST_WORKS; 3192b64d153SBrian Gix 3202b64d153SBrian Gix /* If Just Works, Continue with Zero TK */ 3212b64d153SBrian Gix if (method == JUST_WORKS) { 3222b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3232b64d153SBrian Gix return 0; 3242b64d153SBrian Gix } 3252b64d153SBrian Gix 3262b64d153SBrian Gix /* Not Just Works/Confirm results in MITM Authentication */ 3272b64d153SBrian Gix if (method != JUST_CFM) 3282b64d153SBrian Gix set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags); 3292b64d153SBrian Gix 3302b64d153SBrian Gix /* If both devices have Keyoard-Display I/O, the master 3312b64d153SBrian Gix * Confirms and the slave Enters the passkey. 3322b64d153SBrian Gix */ 3332b64d153SBrian Gix if (method == OVERLAP) { 3342b64d153SBrian Gix if (hcon->link_mode & HCI_LM_MASTER) 3352b64d153SBrian Gix method = CFM_PASSKEY; 3362b64d153SBrian Gix else 3372b64d153SBrian Gix method = REQ_PASSKEY; 3382b64d153SBrian Gix } 3392b64d153SBrian Gix 3402b64d153SBrian Gix /* Generate random passkey. Not valid until confirmed. */ 3412b64d153SBrian Gix if (method == CFM_PASSKEY) { 3422b64d153SBrian Gix u8 key[16]; 3432b64d153SBrian Gix 3442b64d153SBrian Gix memset(key, 0, sizeof(key)); 3452b64d153SBrian Gix get_random_bytes(&passkey, sizeof(passkey)); 3462b64d153SBrian Gix passkey %= 1000000; 3472b64d153SBrian Gix put_unaligned_le32(passkey, key); 3482b64d153SBrian Gix swap128(key, smp->tk); 3492b64d153SBrian Gix BT_DBG("PassKey: %d", passkey); 3502b64d153SBrian Gix } 3512b64d153SBrian Gix 3522b64d153SBrian Gix hci_dev_lock(hcon->hdev); 3532b64d153SBrian Gix 3542b64d153SBrian Gix if (method == REQ_PASSKEY) 355272d90dfSJohan Hedberg ret = mgmt_user_passkey_request(hcon->hdev, conn->dst, 356272d90dfSJohan Hedberg hcon->type, hcon->dst_type); 3572b64d153SBrian Gix else 3582b64d153SBrian Gix ret = mgmt_user_confirm_request(hcon->hdev, conn->dst, 359272d90dfSJohan Hedberg hcon->type, hcon->dst_type, 3602b64d153SBrian Gix cpu_to_le32(passkey), 0); 3612b64d153SBrian Gix 3622b64d153SBrian Gix hci_dev_unlock(hcon->hdev); 3632b64d153SBrian Gix 3642b64d153SBrian Gix return ret; 3652b64d153SBrian Gix } 3662b64d153SBrian Gix 3678aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work) 3688aab4757SVinicius Costa Gomes { 3698aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, confirm); 3708aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 3718aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm; 3728aab4757SVinicius Costa Gomes struct smp_cmd_pairing_confirm cp; 3738aab4757SVinicius Costa Gomes int ret; 3748aab4757SVinicius Costa Gomes u8 res[16], reason; 3758aab4757SVinicius Costa Gomes 3768aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 3778aab4757SVinicius Costa Gomes 3788aab4757SVinicius Costa Gomes tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); 3798aab4757SVinicius Costa Gomes if (IS_ERR(tfm)) { 3808aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3818aab4757SVinicius Costa Gomes goto error; 3828aab4757SVinicius Costa Gomes } 3838aab4757SVinicius Costa Gomes 3848aab4757SVinicius Costa Gomes smp->tfm = tfm; 3858aab4757SVinicius Costa Gomes 3868aab4757SVinicius Costa Gomes if (conn->hcon->out) 3878aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, 38804124681SGustavo F. Padovan conn->src, conn->hcon->dst_type, conn->dst, res); 3898aab4757SVinicius Costa Gomes else 3908aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 3918aab4757SVinicius Costa Gomes conn->hcon->dst_type, conn->dst, 0, conn->src, 3928aab4757SVinicius Costa Gomes res); 3938aab4757SVinicius Costa Gomes if (ret) { 3948aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3958aab4757SVinicius Costa Gomes goto error; 3968aab4757SVinicius Costa Gomes } 3978aab4757SVinicius Costa Gomes 3982b64d153SBrian Gix clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 3992b64d153SBrian Gix 4008aab4757SVinicius Costa Gomes swap128(res, cp.confirm_val); 4018aab4757SVinicius Costa Gomes smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 4028aab4757SVinicius Costa Gomes 4038aab4757SVinicius Costa Gomes return; 4048aab4757SVinicius Costa Gomes 4058aab4757SVinicius Costa Gomes error: 4064f957a76SBrian Gix smp_failure(conn, reason, 1); 4078aab4757SVinicius Costa Gomes } 4088aab4757SVinicius Costa Gomes 4098aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work) 4108aab4757SVinicius Costa Gomes { 4118aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, random); 4128aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 4138aab4757SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 4148aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm = smp->tfm; 4158aab4757SVinicius Costa Gomes u8 reason, confirm[16], res[16], key[16]; 4168aab4757SVinicius Costa Gomes int ret; 4178aab4757SVinicius Costa Gomes 4188aab4757SVinicius Costa Gomes if (IS_ERR_OR_NULL(tfm)) { 4198aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4208aab4757SVinicius Costa Gomes goto error; 4218aab4757SVinicius Costa Gomes } 4228aab4757SVinicius Costa Gomes 4238aab4757SVinicius Costa Gomes BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 4248aab4757SVinicius Costa Gomes 4258aab4757SVinicius Costa Gomes if (hcon->out) 4268aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, 42704124681SGustavo F. Padovan conn->src, hcon->dst_type, conn->dst, res); 4288aab4757SVinicius Costa Gomes else 4298aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 43004124681SGustavo F. Padovan hcon->dst_type, conn->dst, 0, conn->src, res); 4318aab4757SVinicius Costa Gomes if (ret) { 4328aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4338aab4757SVinicius Costa Gomes goto error; 4348aab4757SVinicius Costa Gomes } 4358aab4757SVinicius Costa Gomes 4368aab4757SVinicius Costa Gomes swap128(res, confirm); 4378aab4757SVinicius Costa Gomes 4388aab4757SVinicius Costa Gomes if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { 4398aab4757SVinicius Costa Gomes BT_ERR("Pairing failed (confirmation values mismatch)"); 4408aab4757SVinicius Costa Gomes reason = SMP_CONFIRM_FAILED; 4418aab4757SVinicius Costa Gomes goto error; 4428aab4757SVinicius Costa Gomes } 4438aab4757SVinicius Costa Gomes 4448aab4757SVinicius Costa Gomes if (hcon->out) { 4458aab4757SVinicius Costa Gomes u8 stk[16], rand[8]; 4468aab4757SVinicius Costa Gomes __le16 ediv; 4478aab4757SVinicius Costa Gomes 4488aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4498aab4757SVinicius Costa Gomes ediv = 0; 4508aab4757SVinicius Costa Gomes 4518aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); 4528aab4757SVinicius Costa Gomes swap128(key, stk); 4538aab4757SVinicius Costa Gomes 454f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 455f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4568aab4757SVinicius Costa Gomes 45751a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) { 4588aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4598aab4757SVinicius Costa Gomes goto error; 4608aab4757SVinicius Costa Gomes } 4618aab4757SVinicius Costa Gomes 4628aab4757SVinicius Costa Gomes hci_le_start_enc(hcon, ediv, rand, stk); 463f7aa611aSVinicius Costa Gomes hcon->enc_key_size = smp->enc_key_size; 4648aab4757SVinicius Costa Gomes } else { 4658aab4757SVinicius Costa Gomes u8 stk[16], r[16], rand[8]; 4668aab4757SVinicius Costa Gomes __le16 ediv; 4678aab4757SVinicius Costa Gomes 4688aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4698aab4757SVinicius Costa Gomes ediv = 0; 4708aab4757SVinicius Costa Gomes 4718aab4757SVinicius Costa Gomes swap128(smp->prnd, r); 4728aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 4738aab4757SVinicius Costa Gomes 4748aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); 4758aab4757SVinicius Costa Gomes swap128(key, stk); 4768aab4757SVinicius Costa Gomes 477f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 478f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4798aab4757SVinicius Costa Gomes 480c9839a11SVinicius Costa Gomes hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type, 48104124681SGustavo F. Padovan HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, 48204124681SGustavo F. Padovan ediv, rand); 4838aab4757SVinicius Costa Gomes } 4848aab4757SVinicius Costa Gomes 4858aab4757SVinicius Costa Gomes return; 4868aab4757SVinicius Costa Gomes 4878aab4757SVinicius Costa Gomes error: 4884f957a76SBrian Gix smp_failure(conn, reason, 1); 4898aab4757SVinicius Costa Gomes } 4908aab4757SVinicius Costa Gomes 4918aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 4928aab4757SVinicius Costa Gomes { 4938aab4757SVinicius Costa Gomes struct smp_chan *smp; 4948aab4757SVinicius Costa Gomes 4958aab4757SVinicius Costa Gomes smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); 4968aab4757SVinicius Costa Gomes if (!smp) 4978aab4757SVinicius Costa Gomes return NULL; 4988aab4757SVinicius Costa Gomes 4998aab4757SVinicius Costa Gomes INIT_WORK(&smp->confirm, confirm_work); 5008aab4757SVinicius Costa Gomes INIT_WORK(&smp->random, random_work); 5018aab4757SVinicius Costa Gomes 5028aab4757SVinicius Costa Gomes smp->conn = conn; 5038aab4757SVinicius Costa Gomes conn->smp_chan = smp; 5042b64d153SBrian Gix conn->hcon->smp_conn = conn; 5058aab4757SVinicius Costa Gomes 5068aab4757SVinicius Costa Gomes hci_conn_hold(conn->hcon); 5078aab4757SVinicius Costa Gomes 5088aab4757SVinicius Costa Gomes return smp; 5098aab4757SVinicius Costa Gomes } 5108aab4757SVinicius Costa Gomes 5118aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn) 5128aab4757SVinicius Costa Gomes { 513c8eb9690SBrian Gix struct smp_chan *smp = conn->smp_chan; 514c8eb9690SBrian Gix 515f1c09c07SVinicius Costa Gomes BUG_ON(!smp); 516c8eb9690SBrian Gix 517c8eb9690SBrian Gix if (smp->tfm) 518c8eb9690SBrian Gix crypto_free_blkcipher(smp->tfm); 519c8eb9690SBrian Gix 520c8eb9690SBrian Gix kfree(smp); 521c8eb9690SBrian Gix conn->smp_chan = NULL; 5222b64d153SBrian Gix conn->hcon->smp_conn = NULL; 5238aab4757SVinicius Costa Gomes hci_conn_put(conn->hcon); 5248aab4757SVinicius Costa Gomes } 5258aab4757SVinicius Costa Gomes 5262b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) 5272b64d153SBrian Gix { 5282b64d153SBrian Gix struct l2cap_conn *conn = hcon->smp_conn; 5292b64d153SBrian Gix struct smp_chan *smp; 5302b64d153SBrian Gix u32 value; 5312b64d153SBrian Gix u8 key[16]; 5322b64d153SBrian Gix 5332b64d153SBrian Gix BT_DBG(""); 5342b64d153SBrian Gix 5352b64d153SBrian Gix if (!conn) 5362b64d153SBrian Gix return -ENOTCONN; 5372b64d153SBrian Gix 5382b64d153SBrian Gix smp = conn->smp_chan; 5392b64d153SBrian Gix 5402b64d153SBrian Gix switch (mgmt_op) { 5412b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_REPLY: 5422b64d153SBrian Gix value = le32_to_cpu(passkey); 5432b64d153SBrian Gix memset(key, 0, sizeof(key)); 5442b64d153SBrian Gix BT_DBG("PassKey: %d", value); 5452b64d153SBrian Gix put_unaligned_le32(value, key); 5462b64d153SBrian Gix swap128(key, smp->tk); 5472b64d153SBrian Gix /* Fall Through */ 5482b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_REPLY: 5492b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 5502b64d153SBrian Gix break; 5512b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_NEG_REPLY: 5522b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_NEG_REPLY: 5532b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5542b64d153SBrian Gix return 0; 5552b64d153SBrian Gix default: 5562b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5572b64d153SBrian Gix return -EOPNOTSUPP; 5582b64d153SBrian Gix } 5592b64d153SBrian Gix 5602b64d153SBrian Gix /* If it is our turn to send Pairing Confirm, do so now */ 5612b64d153SBrian Gix if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags)) 5622b64d153SBrian Gix queue_work(hcon->hdev->workqueue, &smp->confirm); 5632b64d153SBrian Gix 5642b64d153SBrian Gix return 0; 5652b64d153SBrian Gix } 5662b64d153SBrian Gix 567da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 56888ba43b6SAnderson Briglia { 5693158c50cSVinicius Costa Gomes struct smp_cmd_pairing rsp, *req = (void *) skb->data; 5708aab4757SVinicius Costa Gomes struct smp_chan *smp; 5713158c50cSVinicius Costa Gomes u8 key_size; 5722b64d153SBrian Gix u8 auth = SMP_AUTH_NONE; 5738aab4757SVinicius Costa Gomes int ret; 57488ba43b6SAnderson Briglia 57588ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 57688ba43b6SAnderson Briglia 5772b64d153SBrian Gix if (conn->hcon->link_mode & HCI_LM_MASTER) 5782b64d153SBrian Gix return SMP_CMD_NOTSUPP; 5792b64d153SBrian Gix 58051a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 5818aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 582d08fd0e7SAndrei Emeltchenko else 5838aab4757SVinicius Costa Gomes smp = conn->smp_chan; 584d26a2345SVinicius Costa Gomes 585d08fd0e7SAndrei Emeltchenko if (!smp) 586d08fd0e7SAndrei Emeltchenko return SMP_UNSPECIFIED; 587d08fd0e7SAndrei Emeltchenko 5881c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5891c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], req, sizeof(*req)); 5903158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*req)); 59188ba43b6SAnderson Briglia 5922b64d153SBrian Gix /* We didn't start the pairing, so match remote */ 5932b64d153SBrian Gix if (req->auth_req & SMP_AUTH_BONDING) 5942b64d153SBrian Gix auth = req->auth_req; 595da85e5e5SVinicius Costa Gomes 596fdde0a26SIdo Yariv conn->hcon->pending_sec_level = authreq_to_seclevel(auth); 597fdde0a26SIdo Yariv 5982b64d153SBrian Gix build_pairing_cmd(conn, req, &rsp, auth); 5993158c50cSVinicius Costa Gomes 6003158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp.max_key_size); 6013158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6023158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 60388ba43b6SAnderson Briglia 6048aab4757SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6058aab4757SVinicius Costa Gomes if (ret) 6068aab4757SVinicius Costa Gomes return SMP_UNSPECIFIED; 6078aab4757SVinicius Costa Gomes 6081c1def09SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6091c1def09SVinicius Costa Gomes memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 610f01ead31SAnderson Briglia 6113158c50cSVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 612da85e5e5SVinicius Costa Gomes 6132b64d153SBrian Gix /* Request setup of TK */ 6142b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); 6152b64d153SBrian Gix if (ret) 6162b64d153SBrian Gix return SMP_UNSPECIFIED; 6172b64d153SBrian Gix 618da85e5e5SVinicius Costa Gomes return 0; 61988ba43b6SAnderson Briglia } 62088ba43b6SAnderson Briglia 621da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 62288ba43b6SAnderson Briglia { 6233158c50cSVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 6241c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6258aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6262b64d153SBrian Gix u8 key_size, auth = SMP_AUTH_NONE; 6277d24ddccSAnderson Briglia int ret; 62888ba43b6SAnderson Briglia 62988ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 63088ba43b6SAnderson Briglia 6312b64d153SBrian Gix if (!(conn->hcon->link_mode & HCI_LM_MASTER)) 6322b64d153SBrian Gix return SMP_CMD_NOTSUPP; 6332b64d153SBrian Gix 6343158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*rsp)); 635da85e5e5SVinicius Costa Gomes 6361c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 6373158c50cSVinicius Costa Gomes 6383158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp->max_key_size); 6393158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6403158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 6413158c50cSVinicius Costa Gomes 6421c1def09SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6437d24ddccSAnderson Briglia if (ret) 644da85e5e5SVinicius Costa Gomes return SMP_UNSPECIFIED; 6457d24ddccSAnderson Briglia 6468aab4757SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6478aab4757SVinicius Costa Gomes memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 6487d24ddccSAnderson Briglia 6492b64d153SBrian Gix if ((req->auth_req & SMP_AUTH_BONDING) && 6502b64d153SBrian Gix (rsp->auth_req & SMP_AUTH_BONDING)) 6512b64d153SBrian Gix auth = SMP_AUTH_BONDING; 6522b64d153SBrian Gix 6532b64d153SBrian Gix auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; 6542b64d153SBrian Gix 655476585ecSJohan Hedberg ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); 6562b64d153SBrian Gix if (ret) 6572b64d153SBrian Gix return SMP_UNSPECIFIED; 6582b64d153SBrian Gix 6592b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 6602b64d153SBrian Gix 6612b64d153SBrian Gix /* Can't compose response until we have been confirmed */ 6622b64d153SBrian Gix if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) 6632b64d153SBrian Gix return 0; 6642b64d153SBrian Gix 6658aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 666da85e5e5SVinicius Costa Gomes 667da85e5e5SVinicius Costa Gomes return 0; 66888ba43b6SAnderson Briglia } 66988ba43b6SAnderson Briglia 670da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 67188ba43b6SAnderson Briglia { 6721c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6738aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6747d24ddccSAnderson Briglia 67588ba43b6SAnderson Briglia BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 67688ba43b6SAnderson Briglia 6771c1def09SVinicius Costa Gomes memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 6781c1def09SVinicius Costa Gomes skb_pull(skb, sizeof(smp->pcnf)); 6797d24ddccSAnderson Briglia 68088ba43b6SAnderson Briglia if (conn->hcon->out) { 6817d24ddccSAnderson Briglia u8 random[16]; 68288ba43b6SAnderson Briglia 6831c1def09SVinicius Costa Gomes swap128(smp->prnd, random); 68488ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 6857d24ddccSAnderson Briglia random); 6862b64d153SBrian Gix } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { 6878aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 6882b64d153SBrian Gix } else { 6892b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 69088ba43b6SAnderson Briglia } 691da85e5e5SVinicius Costa Gomes 692da85e5e5SVinicius Costa Gomes return 0; 69388ba43b6SAnderson Briglia } 69488ba43b6SAnderson Briglia 695da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 69688ba43b6SAnderson Briglia { 6971c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6988aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6997d24ddccSAnderson Briglia 7008aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 7017d24ddccSAnderson Briglia 7028aab4757SVinicius Costa Gomes swap128(skb->data, smp->rrnd); 7038aab4757SVinicius Costa Gomes skb_pull(skb, sizeof(smp->rrnd)); 70488ba43b6SAnderson Briglia 7058aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->random); 706da85e5e5SVinicius Costa Gomes 707da85e5e5SVinicius Costa Gomes return 0; 70888ba43b6SAnderson Briglia } 70988ba43b6SAnderson Briglia 7104dab7864SJohan Hedberg static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) 711988c5997SVinicius Costa Gomes { 712c9839a11SVinicius Costa Gomes struct smp_ltk *key; 713988c5997SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 714988c5997SVinicius Costa Gomes 715c9839a11SVinicius Costa Gomes key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type); 716988c5997SVinicius Costa Gomes if (!key) 717988c5997SVinicius Costa Gomes return 0; 718988c5997SVinicius Costa Gomes 7194dab7864SJohan Hedberg if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) 7204dab7864SJohan Hedberg return 0; 7214dab7864SJohan Hedberg 72251a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) 723988c5997SVinicius Costa Gomes return 1; 724988c5997SVinicius Costa Gomes 725c9839a11SVinicius Costa Gomes hci_le_start_enc(hcon, key->ediv, key->rand, key->val); 726c9839a11SVinicius Costa Gomes hcon->enc_key_size = key->enc_size; 727988c5997SVinicius Costa Gomes 728988c5997SVinicius Costa Gomes return 1; 729988c5997SVinicius Costa Gomes 730988c5997SVinicius Costa Gomes } 731da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) 73288ba43b6SAnderson Briglia { 73388ba43b6SAnderson Briglia struct smp_cmd_security_req *rp = (void *) skb->data; 73488ba43b6SAnderson Briglia struct smp_cmd_pairing cp; 735f1cb9af5SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 7368aab4757SVinicius Costa Gomes struct smp_chan *smp; 73788ba43b6SAnderson Briglia 73888ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 73988ba43b6SAnderson Briglia 7402b64d153SBrian Gix hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); 741feb45eb5SVinicius Costa Gomes 7424dab7864SJohan Hedberg if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) 743988c5997SVinicius Costa Gomes return 0; 744988c5997SVinicius Costa Gomes 74551a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 746da85e5e5SVinicius Costa Gomes return 0; 747f1cb9af5SVinicius Costa Gomes 7488aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 749d26a2345SVinicius Costa Gomes 75088ba43b6SAnderson Briglia skb_pull(skb, sizeof(*rp)); 75188ba43b6SAnderson Briglia 752da85e5e5SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 75354790f73SVinicius Costa Gomes build_pairing_cmd(conn, &cp, NULL, rp->auth_req); 75488ba43b6SAnderson Briglia 7551c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 7561c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 757f01ead31SAnderson Briglia 75888ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 759f1cb9af5SVinicius Costa Gomes 760da85e5e5SVinicius Costa Gomes return 0; 76188ba43b6SAnderson Briglia } 76288ba43b6SAnderson Briglia 763cc110922SVinicius Costa Gomes int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) 764eb492e01SAnderson Briglia { 765cc110922SVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 7661c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7672b64d153SBrian Gix __u8 authreq; 768eb492e01SAnderson Briglia 7693a0259bbSVinicius Costa Gomes BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); 7703a0259bbSVinicius Costa Gomes 7712e65c9d2SAndre Guedes if (!lmp_host_le_capable(hcon->hdev)) 7722e65c9d2SAndre Guedes return 1; 7732e65c9d2SAndre Guedes 774f1cb9af5SVinicius Costa Gomes if (sec_level == BT_SECURITY_LOW) 775eb492e01SAnderson Briglia return 1; 776f1cb9af5SVinicius Costa Gomes 777f1cb9af5SVinicius Costa Gomes if (hcon->sec_level >= sec_level) 778f1cb9af5SVinicius Costa Gomes return 1; 779f1cb9af5SVinicius Costa Gomes 780988c5997SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) 7814dab7864SJohan Hedberg if (smp_ltk_encrypt(conn, sec_level)) 782d26a2345SVinicius Costa Gomes goto done; 783d26a2345SVinicius Costa Gomes 78451a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 785d26a2345SVinicius Costa Gomes return 0; 786d26a2345SVinicius Costa Gomes 7878aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 7882b64d153SBrian Gix if (!smp) 7892b64d153SBrian Gix return 1; 7902b64d153SBrian Gix 7912b64d153SBrian Gix authreq = seclevel_to_authreq(sec_level); 792d26a2345SVinicius Costa Gomes 793d26a2345SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) { 794d26a2345SVinicius Costa Gomes struct smp_cmd_pairing cp; 795f01ead31SAnderson Briglia 7962b64d153SBrian Gix build_pairing_cmd(conn, &cp, NULL, authreq); 7971c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 7981c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 799f01ead31SAnderson Briglia 800eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 801eb492e01SAnderson Briglia } else { 802eb492e01SAnderson Briglia struct smp_cmd_security_req cp; 8032b64d153SBrian Gix cp.auth_req = authreq; 804eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 805eb492e01SAnderson Briglia } 806eb492e01SAnderson Briglia 80702bc7455SVinicius Costa Gomes done: 808f1cb9af5SVinicius Costa Gomes hcon->pending_sec_level = sec_level; 809f1cb9af5SVinicius Costa Gomes 810eb492e01SAnderson Briglia return 0; 811eb492e01SAnderson Briglia } 812eb492e01SAnderson Briglia 8137034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) 8147034b911SVinicius Costa Gomes { 81516b90839SVinicius Costa Gomes struct smp_cmd_encrypt_info *rp = (void *) skb->data; 8161c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 81716b90839SVinicius Costa Gomes 81816b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 81916b90839SVinicius Costa Gomes 8201c1def09SVinicius Costa Gomes memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); 82116b90839SVinicius Costa Gomes 8227034b911SVinicius Costa Gomes return 0; 8237034b911SVinicius Costa Gomes } 8247034b911SVinicius Costa Gomes 8257034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) 8267034b911SVinicius Costa Gomes { 82716b90839SVinicius Costa Gomes struct smp_cmd_master_ident *rp = (void *) skb->data; 8281c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 829c9839a11SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 830c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 831c9839a11SVinicius Costa Gomes u8 authenticated; 8327034b911SVinicius Costa Gomes 83316b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 83416b90839SVinicius Costa Gomes 835c9839a11SVinicius Costa Gomes hci_dev_lock(hdev); 836c9839a11SVinicius Costa Gomes authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); 837c9839a11SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, 83804124681SGustavo F. Padovan HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, 83904124681SGustavo F. Padovan rp->ediv, rp->rand); 8407034b911SVinicius Costa Gomes smp_distribute_keys(conn, 1); 841c9839a11SVinicius Costa Gomes hci_dev_unlock(hdev); 8427034b911SVinicius Costa Gomes 8437034b911SVinicius Costa Gomes return 0; 8447034b911SVinicius Costa Gomes } 8457034b911SVinicius Costa Gomes 846eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 847eb492e01SAnderson Briglia { 848eb492e01SAnderson Briglia __u8 code = skb->data[0]; 849eb492e01SAnderson Briglia __u8 reason; 850eb492e01SAnderson Briglia int err = 0; 851eb492e01SAnderson Briglia 8522e65c9d2SAndre Guedes if (!lmp_host_le_capable(conn->hcon->hdev)) { 8532e65c9d2SAndre Guedes err = -ENOTSUPP; 8542e65c9d2SAndre Guedes reason = SMP_PAIRING_NOTSUPP; 8552e65c9d2SAndre Guedes goto done; 8562e65c9d2SAndre Guedes } 8572e65c9d2SAndre Guedes 858eb492e01SAnderson Briglia skb_pull(skb, sizeof(code)); 859eb492e01SAnderson Briglia 860eb492e01SAnderson Briglia switch (code) { 861eb492e01SAnderson Briglia case SMP_CMD_PAIRING_REQ: 862da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_req(conn, skb); 863eb492e01SAnderson Briglia break; 864eb492e01SAnderson Briglia 865eb492e01SAnderson Briglia case SMP_CMD_PAIRING_FAIL: 8664f957a76SBrian Gix smp_failure(conn, skb->data[0], 0); 867da85e5e5SVinicius Costa Gomes reason = 0; 868da85e5e5SVinicius Costa Gomes err = -EPERM; 869eb492e01SAnderson Briglia break; 870eb492e01SAnderson Briglia 871eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RSP: 872da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_rsp(conn, skb); 87388ba43b6SAnderson Briglia break; 87488ba43b6SAnderson Briglia 87588ba43b6SAnderson Briglia case SMP_CMD_SECURITY_REQ: 876da85e5e5SVinicius Costa Gomes reason = smp_cmd_security_req(conn, skb); 87788ba43b6SAnderson Briglia break; 87888ba43b6SAnderson Briglia 879eb492e01SAnderson Briglia case SMP_CMD_PAIRING_CONFIRM: 880da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_confirm(conn, skb); 88188ba43b6SAnderson Briglia break; 88288ba43b6SAnderson Briglia 883eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RANDOM: 884da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_random(conn, skb); 88588ba43b6SAnderson Briglia break; 88688ba43b6SAnderson Briglia 887eb492e01SAnderson Briglia case SMP_CMD_ENCRYPT_INFO: 8887034b911SVinicius Costa Gomes reason = smp_cmd_encrypt_info(conn, skb); 8897034b911SVinicius Costa Gomes break; 8907034b911SVinicius Costa Gomes 891eb492e01SAnderson Briglia case SMP_CMD_MASTER_IDENT: 8927034b911SVinicius Costa Gomes reason = smp_cmd_master_ident(conn, skb); 8937034b911SVinicius Costa Gomes break; 8947034b911SVinicius Costa Gomes 895eb492e01SAnderson Briglia case SMP_CMD_IDENT_INFO: 896eb492e01SAnderson Briglia case SMP_CMD_IDENT_ADDR_INFO: 897eb492e01SAnderson Briglia case SMP_CMD_SIGN_INFO: 8987034b911SVinicius Costa Gomes /* Just ignored */ 8997034b911SVinicius Costa Gomes reason = 0; 9007034b911SVinicius Costa Gomes break; 9017034b911SVinicius Costa Gomes 902eb492e01SAnderson Briglia default: 903eb492e01SAnderson Briglia BT_DBG("Unknown command code 0x%2.2x", code); 904eb492e01SAnderson Briglia 905eb492e01SAnderson Briglia reason = SMP_CMD_NOTSUPP; 9063a0259bbSVinicius Costa Gomes err = -EOPNOTSUPP; 9073a0259bbSVinicius Costa Gomes goto done; 9083a0259bbSVinicius Costa Gomes } 9093a0259bbSVinicius Costa Gomes 9103a0259bbSVinicius Costa Gomes done: 9113a0259bbSVinicius Costa Gomes if (reason) 9124f957a76SBrian Gix smp_failure(conn, reason, 1); 913eb492e01SAnderson Briglia 914eb492e01SAnderson Briglia kfree_skb(skb); 915eb492e01SAnderson Briglia return err; 916eb492e01SAnderson Briglia } 9177034b911SVinicius Costa Gomes 9187034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) 9197034b911SVinicius Costa Gomes { 9207034b911SVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp; 9211c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 9227034b911SVinicius Costa Gomes __u8 *keydist; 9237034b911SVinicius Costa Gomes 9247034b911SVinicius Costa Gomes BT_DBG("conn %p force %d", conn, force); 9257034b911SVinicius Costa Gomes 92651a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 927d26a2345SVinicius Costa Gomes return 0; 928d26a2345SVinicius Costa Gomes 9291c1def09SVinicius Costa Gomes rsp = (void *) &smp->prsp[1]; 9307034b911SVinicius Costa Gomes 9317034b911SVinicius Costa Gomes /* The responder sends its keys first */ 9327034b911SVinicius Costa Gomes if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) 9337034b911SVinicius Costa Gomes return 0; 9347034b911SVinicius Costa Gomes 9351c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 9367034b911SVinicius Costa Gomes 9377034b911SVinicius Costa Gomes if (conn->hcon->out) { 9387034b911SVinicius Costa Gomes keydist = &rsp->init_key_dist; 9397034b911SVinicius Costa Gomes *keydist &= req->init_key_dist; 9407034b911SVinicius Costa Gomes } else { 9417034b911SVinicius Costa Gomes keydist = &rsp->resp_key_dist; 9427034b911SVinicius Costa Gomes *keydist &= req->resp_key_dist; 9437034b911SVinicius Costa Gomes } 9447034b911SVinicius Costa Gomes 9457034b911SVinicius Costa Gomes 9467034b911SVinicius Costa Gomes BT_DBG("keydist 0x%x", *keydist); 9477034b911SVinicius Costa Gomes 9487034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ENC_KEY) { 9497034b911SVinicius Costa Gomes struct smp_cmd_encrypt_info enc; 9507034b911SVinicius Costa Gomes struct smp_cmd_master_ident ident; 951c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 952c9839a11SVinicius Costa Gomes u8 authenticated; 9537034b911SVinicius Costa Gomes __le16 ediv; 9547034b911SVinicius Costa Gomes 9557034b911SVinicius Costa Gomes get_random_bytes(enc.ltk, sizeof(enc.ltk)); 9567034b911SVinicius Costa Gomes get_random_bytes(&ediv, sizeof(ediv)); 9577034b911SVinicius Costa Gomes get_random_bytes(ident.rand, sizeof(ident.rand)); 9587034b911SVinicius Costa Gomes 9597034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 9607034b911SVinicius Costa Gomes 961c9839a11SVinicius Costa Gomes authenticated = hcon->sec_level == BT_SECURITY_HIGH; 962c9839a11SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, 963c9839a11SVinicius Costa Gomes HCI_SMP_LTK_SLAVE, 1, authenticated, 96404124681SGustavo F. Padovan enc.ltk, smp->enc_key_size, ediv, ident.rand); 96516b90839SVinicius Costa Gomes 96658115373SAndrei Emeltchenko ident.ediv = ediv; 9677034b911SVinicius Costa Gomes 9687034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); 9697034b911SVinicius Costa Gomes 9707034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ENC_KEY; 9717034b911SVinicius Costa Gomes } 9727034b911SVinicius Costa Gomes 9737034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ID_KEY) { 9747034b911SVinicius Costa Gomes struct smp_cmd_ident_addr_info addrinfo; 9757034b911SVinicius Costa Gomes struct smp_cmd_ident_info idinfo; 9767034b911SVinicius Costa Gomes 9777034b911SVinicius Costa Gomes /* Send a dummy key */ 9787034b911SVinicius Costa Gomes get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); 9797034b911SVinicius Costa Gomes 9807034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 9817034b911SVinicius Costa Gomes 9827034b911SVinicius Costa Gomes /* Just public address */ 9837034b911SVinicius Costa Gomes memset(&addrinfo, 0, sizeof(addrinfo)); 9847034b911SVinicius Costa Gomes bacpy(&addrinfo.bdaddr, conn->src); 9857034b911SVinicius Costa Gomes 9867034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 9877034b911SVinicius Costa Gomes &addrinfo); 9887034b911SVinicius Costa Gomes 9897034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ID_KEY; 9907034b911SVinicius Costa Gomes } 9917034b911SVinicius Costa Gomes 9927034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_SIGN) { 9937034b911SVinicius Costa Gomes struct smp_cmd_sign_info sign; 9947034b911SVinicius Costa Gomes 9957034b911SVinicius Costa Gomes /* Send a dummy key */ 9967034b911SVinicius Costa Gomes get_random_bytes(sign.csrk, sizeof(sign.csrk)); 9977034b911SVinicius Costa Gomes 9987034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 9997034b911SVinicius Costa Gomes 10007034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_SIGN; 10017034b911SVinicius Costa Gomes } 10027034b911SVinicius Costa Gomes 1003d26a2345SVinicius Costa Gomes if (conn->hcon->out || force) { 100451a8efd7SJohan Hedberg clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); 10056c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 10068aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1007d26a2345SVinicius Costa Gomes } 1008d26a2345SVinicius Costa Gomes 10097034b911SVinicius Costa Gomes return 0; 10107034b911SVinicius Costa Gomes } 1011