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 35065a13e2SJohan Hedberg #define AUTH_REQ_MASK 0x07 36065a13e2SJohan Hedberg 37d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16]) 38d22ef0bcSAnderson Briglia { 39d22ef0bcSAnderson Briglia int i; 40d22ef0bcSAnderson Briglia for (i = 0; i < 16; i++) 41d22ef0bcSAnderson Briglia dst[15 - i] = src[i]; 42d22ef0bcSAnderson Briglia } 43d22ef0bcSAnderson Briglia 44d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7]) 45d22ef0bcSAnderson Briglia { 46d22ef0bcSAnderson Briglia int i; 47d22ef0bcSAnderson Briglia for (i = 0; i < 7; i++) 48d22ef0bcSAnderson Briglia dst[6 - i] = src[i]; 49d22ef0bcSAnderson Briglia } 50d22ef0bcSAnderson Briglia 51d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) 52d22ef0bcSAnderson Briglia { 53d22ef0bcSAnderson Briglia struct blkcipher_desc desc; 54d22ef0bcSAnderson Briglia struct scatterlist sg; 55d22ef0bcSAnderson Briglia int err, iv_len; 56d22ef0bcSAnderson Briglia unsigned char iv[128]; 57d22ef0bcSAnderson Briglia 58d22ef0bcSAnderson Briglia if (tfm == NULL) { 59d22ef0bcSAnderson Briglia BT_ERR("tfm %p", tfm); 60d22ef0bcSAnderson Briglia return -EINVAL; 61d22ef0bcSAnderson Briglia } 62d22ef0bcSAnderson Briglia 63d22ef0bcSAnderson Briglia desc.tfm = tfm; 64d22ef0bcSAnderson Briglia desc.flags = 0; 65d22ef0bcSAnderson Briglia 66d22ef0bcSAnderson Briglia err = crypto_blkcipher_setkey(tfm, k, 16); 67d22ef0bcSAnderson Briglia if (err) { 68d22ef0bcSAnderson Briglia BT_ERR("cipher setkey failed: %d", err); 69d22ef0bcSAnderson Briglia return err; 70d22ef0bcSAnderson Briglia } 71d22ef0bcSAnderson Briglia 72d22ef0bcSAnderson Briglia sg_init_one(&sg, r, 16); 73d22ef0bcSAnderson Briglia 74d22ef0bcSAnderson Briglia iv_len = crypto_blkcipher_ivsize(tfm); 75d22ef0bcSAnderson Briglia if (iv_len) { 76d22ef0bcSAnderson Briglia memset(&iv, 0xff, iv_len); 77d22ef0bcSAnderson Briglia crypto_blkcipher_set_iv(tfm, iv, iv_len); 78d22ef0bcSAnderson Briglia } 79d22ef0bcSAnderson Briglia 80d22ef0bcSAnderson Briglia err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); 81d22ef0bcSAnderson Briglia if (err) 82d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error %d", err); 83d22ef0bcSAnderson Briglia 84d22ef0bcSAnderson Briglia return err; 85d22ef0bcSAnderson Briglia } 86d22ef0bcSAnderson Briglia 87d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], 88d22ef0bcSAnderson Briglia u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, 89d22ef0bcSAnderson Briglia u8 _rat, bdaddr_t *ra, u8 res[16]) 90d22ef0bcSAnderson Briglia { 91d22ef0bcSAnderson Briglia u8 p1[16], p2[16]; 92d22ef0bcSAnderson Briglia int err; 93d22ef0bcSAnderson Briglia 94d22ef0bcSAnderson Briglia memset(p1, 0, 16); 95d22ef0bcSAnderson Briglia 96d22ef0bcSAnderson Briglia /* p1 = pres || preq || _rat || _iat */ 97d22ef0bcSAnderson Briglia swap56(pres, p1); 98d22ef0bcSAnderson Briglia swap56(preq, p1 + 7); 99d22ef0bcSAnderson Briglia p1[14] = _rat; 100d22ef0bcSAnderson Briglia p1[15] = _iat; 101d22ef0bcSAnderson Briglia 102d22ef0bcSAnderson Briglia memset(p2, 0, 16); 103d22ef0bcSAnderson Briglia 104d22ef0bcSAnderson Briglia /* p2 = padding || ia || ra */ 105d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 4), ia); 106d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 10), ra); 107d22ef0bcSAnderson Briglia 108d22ef0bcSAnderson Briglia /* res = r XOR p1 */ 109d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); 110d22ef0bcSAnderson Briglia 111d22ef0bcSAnderson Briglia /* res = e(k, res) */ 112d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 113d22ef0bcSAnderson Briglia if (err) { 114d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 115d22ef0bcSAnderson Briglia return err; 116d22ef0bcSAnderson Briglia } 117d22ef0bcSAnderson Briglia 118d22ef0bcSAnderson Briglia /* res = res XOR p2 */ 119d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); 120d22ef0bcSAnderson Briglia 121d22ef0bcSAnderson Briglia /* res = e(k, res) */ 122d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 123d22ef0bcSAnderson Briglia if (err) 124d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 125d22ef0bcSAnderson Briglia 126d22ef0bcSAnderson Briglia return err; 127d22ef0bcSAnderson Briglia } 128d22ef0bcSAnderson Briglia 129d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], 130d22ef0bcSAnderson Briglia u8 r1[16], u8 r2[16], u8 _r[16]) 131d22ef0bcSAnderson Briglia { 132d22ef0bcSAnderson Briglia int err; 133d22ef0bcSAnderson Briglia 134d22ef0bcSAnderson Briglia /* Just least significant octets from r1 and r2 are considered */ 135d22ef0bcSAnderson Briglia memcpy(_r, r1 + 8, 8); 136d22ef0bcSAnderson Briglia memcpy(_r + 8, r2 + 8, 8); 137d22ef0bcSAnderson Briglia 138d22ef0bcSAnderson Briglia err = smp_e(tfm, k, _r); 139d22ef0bcSAnderson Briglia if (err) 140d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 141d22ef0bcSAnderson Briglia 142d22ef0bcSAnderson Briglia return err; 143d22ef0bcSAnderson Briglia } 144d22ef0bcSAnderson Briglia 145d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf) 146d22ef0bcSAnderson Briglia { 147d22ef0bcSAnderson Briglia get_random_bytes(buf, 16); 148d22ef0bcSAnderson Briglia 149d22ef0bcSAnderson Briglia return 0; 150d22ef0bcSAnderson Briglia } 151eb492e01SAnderson Briglia 152eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, 153eb492e01SAnderson Briglia u16 dlen, void *data) 154eb492e01SAnderson Briglia { 155eb492e01SAnderson Briglia struct sk_buff *skb; 156eb492e01SAnderson Briglia struct l2cap_hdr *lh; 157eb492e01SAnderson Briglia int len; 158eb492e01SAnderson Briglia 159eb492e01SAnderson Briglia len = L2CAP_HDR_SIZE + sizeof(code) + dlen; 160eb492e01SAnderson Briglia 161eb492e01SAnderson Briglia if (len > conn->mtu) 162eb492e01SAnderson Briglia return NULL; 163eb492e01SAnderson Briglia 164eb492e01SAnderson Briglia skb = bt_skb_alloc(len, GFP_ATOMIC); 165eb492e01SAnderson Briglia if (!skb) 166eb492e01SAnderson Briglia return NULL; 167eb492e01SAnderson Briglia 168eb492e01SAnderson Briglia lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 169eb492e01SAnderson Briglia lh->len = cpu_to_le16(sizeof(code) + dlen); 170d8aece2aSSyam Sidhardhan lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); 171eb492e01SAnderson Briglia 172eb492e01SAnderson Briglia memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); 173eb492e01SAnderson Briglia 174eb492e01SAnderson Briglia memcpy(skb_put(skb, dlen), data, dlen); 175eb492e01SAnderson Briglia 176eb492e01SAnderson Briglia return skb; 177eb492e01SAnderson Briglia } 178eb492e01SAnderson Briglia 179eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) 180eb492e01SAnderson Briglia { 181eb492e01SAnderson Briglia struct sk_buff *skb = smp_build_cmd(conn, code, len, data); 182eb492e01SAnderson Briglia 183eb492e01SAnderson Briglia BT_DBG("code 0x%2.2x", code); 184eb492e01SAnderson Briglia 185eb492e01SAnderson Briglia if (!skb) 186eb492e01SAnderson Briglia return; 187eb492e01SAnderson Briglia 18873d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 18973d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, 0); 190e2dcd113SVinicius Costa Gomes 1916c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 19217b02e62SMarcel Holtmann schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT); 193eb492e01SAnderson Briglia } 194eb492e01SAnderson Briglia 1952b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq) 1962b64d153SBrian Gix { 1972b64d153SBrian Gix if (authreq & SMP_AUTH_MITM) 1982b64d153SBrian Gix return BT_SECURITY_HIGH; 1992b64d153SBrian Gix else 2002b64d153SBrian Gix return BT_SECURITY_MEDIUM; 2012b64d153SBrian Gix } 2022b64d153SBrian Gix 2032b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level) 2042b64d153SBrian Gix { 2052b64d153SBrian Gix switch (sec_level) { 2062b64d153SBrian Gix case BT_SECURITY_HIGH: 2072b64d153SBrian Gix return SMP_AUTH_MITM | SMP_AUTH_BONDING; 2082b64d153SBrian Gix case BT_SECURITY_MEDIUM: 2092b64d153SBrian Gix return SMP_AUTH_BONDING; 2102b64d153SBrian Gix default: 2112b64d153SBrian Gix return SMP_AUTH_NONE; 2122b64d153SBrian Gix } 2132b64d153SBrian Gix } 2142b64d153SBrian Gix 215b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn, 21654790f73SVinicius Costa Gomes struct smp_cmd_pairing *req, 21754790f73SVinicius Costa Gomes struct smp_cmd_pairing *rsp, 21854790f73SVinicius Costa Gomes __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 26851a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); 269bab73cb6SJohan Hedberg mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, 270896ea28eSPaulo Sérgio hcon->dst_type, HCI_ERROR_AUTH_FAILURE); 271f1c09c07SVinicius Costa Gomes 2726c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 27361a0cfb0SAndre Guedes 27461a0cfb0SAndre Guedes if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->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) 357272d90dfSJohan Hedberg ret = mgmt_user_passkey_request(hcon->hdev, conn->dst, 358272d90dfSJohan Hedberg hcon->type, hcon->dst_type); 3592b64d153SBrian Gix else 3602b64d153SBrian Gix ret = mgmt_user_confirm_request(hcon->hdev, conn->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) 3898aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, 39004124681SGustavo F. Padovan conn->src, conn->hcon->dst_type, conn->dst, res); 3918aab4757SVinicius Costa Gomes else 3928aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 3938aab4757SVinicius Costa Gomes conn->hcon->dst_type, conn->dst, 0, conn->src, 3948aab4757SVinicius Costa Gomes res); 3958aab4757SVinicius Costa Gomes if (ret) { 3968aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3978aab4757SVinicius Costa Gomes goto error; 3988aab4757SVinicius Costa Gomes } 3998aab4757SVinicius Costa Gomes 4002b64d153SBrian Gix clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 4012b64d153SBrian Gix 4028aab4757SVinicius Costa Gomes swap128(res, cp.confirm_val); 4038aab4757SVinicius Costa Gomes smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 4048aab4757SVinicius Costa Gomes 4058aab4757SVinicius Costa Gomes return; 4068aab4757SVinicius Costa Gomes 4078aab4757SVinicius Costa Gomes error: 4084f957a76SBrian Gix smp_failure(conn, reason, 1); 4098aab4757SVinicius Costa Gomes } 4108aab4757SVinicius Costa Gomes 4118aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work) 4128aab4757SVinicius Costa Gomes { 4138aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, random); 4148aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 4158aab4757SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 4168aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm = smp->tfm; 4178aab4757SVinicius Costa Gomes u8 reason, confirm[16], res[16], key[16]; 4188aab4757SVinicius Costa Gomes int ret; 4198aab4757SVinicius Costa Gomes 4208aab4757SVinicius Costa Gomes if (IS_ERR_OR_NULL(tfm)) { 4218aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4228aab4757SVinicius Costa Gomes goto error; 4238aab4757SVinicius Costa Gomes } 4248aab4757SVinicius Costa Gomes 4258aab4757SVinicius Costa Gomes BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 4268aab4757SVinicius Costa Gomes 4278aab4757SVinicius Costa Gomes if (hcon->out) 4288aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, 42904124681SGustavo F. Padovan conn->src, hcon->dst_type, conn->dst, res); 4308aab4757SVinicius Costa Gomes else 4318aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 43204124681SGustavo F. Padovan hcon->dst_type, conn->dst, 0, conn->src, res); 4338aab4757SVinicius Costa Gomes if (ret) { 4348aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4358aab4757SVinicius Costa Gomes goto error; 4368aab4757SVinicius Costa Gomes } 4378aab4757SVinicius Costa Gomes 4388aab4757SVinicius Costa Gomes swap128(res, confirm); 4398aab4757SVinicius Costa Gomes 4408aab4757SVinicius Costa Gomes if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { 4418aab4757SVinicius Costa Gomes BT_ERR("Pairing failed (confirmation values mismatch)"); 4428aab4757SVinicius Costa Gomes reason = SMP_CONFIRM_FAILED; 4438aab4757SVinicius Costa Gomes goto error; 4448aab4757SVinicius Costa Gomes } 4458aab4757SVinicius Costa Gomes 4468aab4757SVinicius Costa Gomes if (hcon->out) { 4478aab4757SVinicius Costa Gomes u8 stk[16], rand[8]; 4488aab4757SVinicius Costa Gomes __le16 ediv; 4498aab4757SVinicius Costa Gomes 4508aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4518aab4757SVinicius Costa Gomes ediv = 0; 4528aab4757SVinicius Costa Gomes 4538aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); 4548aab4757SVinicius Costa Gomes swap128(key, stk); 4558aab4757SVinicius Costa Gomes 456f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 457f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4588aab4757SVinicius Costa Gomes 45951a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) { 4608aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4618aab4757SVinicius Costa Gomes goto error; 4628aab4757SVinicius Costa Gomes } 4638aab4757SVinicius Costa Gomes 4648aab4757SVinicius Costa Gomes hci_le_start_enc(hcon, ediv, rand, stk); 465f7aa611aSVinicius Costa Gomes hcon->enc_key_size = smp->enc_key_size; 4668aab4757SVinicius Costa Gomes } else { 4678aab4757SVinicius Costa Gomes u8 stk[16], r[16], rand[8]; 4688aab4757SVinicius Costa Gomes __le16 ediv; 4698aab4757SVinicius Costa Gomes 4708aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4718aab4757SVinicius Costa Gomes ediv = 0; 4728aab4757SVinicius Costa Gomes 4738aab4757SVinicius Costa Gomes swap128(smp->prnd, r); 4748aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 4758aab4757SVinicius Costa Gomes 4768aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); 4778aab4757SVinicius Costa Gomes swap128(key, stk); 4788aab4757SVinicius Costa Gomes 479f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 480f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4818aab4757SVinicius Costa Gomes 482c9839a11SVinicius Costa Gomes hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type, 48304124681SGustavo F. Padovan HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, 48404124681SGustavo F. Padovan ediv, rand); 4858aab4757SVinicius Costa Gomes } 4868aab4757SVinicius Costa Gomes 4878aab4757SVinicius Costa Gomes return; 4888aab4757SVinicius Costa Gomes 4898aab4757SVinicius Costa Gomes error: 4904f957a76SBrian Gix smp_failure(conn, reason, 1); 4918aab4757SVinicius Costa Gomes } 4928aab4757SVinicius Costa Gomes 4938aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 4948aab4757SVinicius Costa Gomes { 4958aab4757SVinicius Costa Gomes struct smp_chan *smp; 4968aab4757SVinicius Costa Gomes 4978aab4757SVinicius Costa Gomes smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); 4988aab4757SVinicius Costa Gomes if (!smp) 4998aab4757SVinicius Costa Gomes return NULL; 5008aab4757SVinicius Costa Gomes 5018aab4757SVinicius Costa Gomes INIT_WORK(&smp->confirm, confirm_work); 5028aab4757SVinicius Costa Gomes INIT_WORK(&smp->random, random_work); 5038aab4757SVinicius Costa Gomes 5048aab4757SVinicius Costa Gomes smp->conn = conn; 5058aab4757SVinicius Costa Gomes conn->smp_chan = smp; 5062b64d153SBrian Gix conn->hcon->smp_conn = conn; 5078aab4757SVinicius Costa Gomes 5088aab4757SVinicius Costa Gomes hci_conn_hold(conn->hcon); 5098aab4757SVinicius Costa Gomes 5108aab4757SVinicius Costa Gomes return smp; 5118aab4757SVinicius Costa Gomes } 5128aab4757SVinicius Costa Gomes 5138aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn) 5148aab4757SVinicius Costa Gomes { 515c8eb9690SBrian Gix struct smp_chan *smp = conn->smp_chan; 516c8eb9690SBrian Gix 517f1c09c07SVinicius Costa Gomes BUG_ON(!smp); 518c8eb9690SBrian Gix 519c8eb9690SBrian Gix if (smp->tfm) 520c8eb9690SBrian Gix crypto_free_blkcipher(smp->tfm); 521c8eb9690SBrian Gix 522c8eb9690SBrian Gix kfree(smp); 523c8eb9690SBrian Gix conn->smp_chan = NULL; 5242b64d153SBrian Gix conn->hcon->smp_conn = NULL; 52576a68ba0SDavid Herrmann hci_conn_drop(conn->hcon); 5268aab4757SVinicius Costa Gomes } 5278aab4757SVinicius Costa Gomes 5282b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) 5292b64d153SBrian Gix { 5302b64d153SBrian Gix struct l2cap_conn *conn = hcon->smp_conn; 5312b64d153SBrian Gix struct smp_chan *smp; 5322b64d153SBrian Gix u32 value; 5332b64d153SBrian Gix u8 key[16]; 5342b64d153SBrian Gix 5352b64d153SBrian Gix BT_DBG(""); 5362b64d153SBrian Gix 5372b64d153SBrian Gix if (!conn) 5382b64d153SBrian Gix return -ENOTCONN; 5392b64d153SBrian Gix 5402b64d153SBrian Gix smp = conn->smp_chan; 5412b64d153SBrian Gix 5422b64d153SBrian Gix switch (mgmt_op) { 5432b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_REPLY: 5442b64d153SBrian Gix value = le32_to_cpu(passkey); 5452b64d153SBrian Gix memset(key, 0, sizeof(key)); 5462b64d153SBrian Gix BT_DBG("PassKey: %d", value); 5472b64d153SBrian Gix put_unaligned_le32(value, key); 5482b64d153SBrian Gix swap128(key, smp->tk); 5492b64d153SBrian Gix /* Fall Through */ 5502b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_REPLY: 5512b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 5522b64d153SBrian Gix break; 5532b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_NEG_REPLY: 5542b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_NEG_REPLY: 5552b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5562b64d153SBrian Gix return 0; 5572b64d153SBrian Gix default: 5582b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5592b64d153SBrian Gix return -EOPNOTSUPP; 5602b64d153SBrian Gix } 5612b64d153SBrian Gix 5622b64d153SBrian Gix /* If it is our turn to send Pairing Confirm, do so now */ 5632b64d153SBrian Gix if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags)) 5642b64d153SBrian Gix queue_work(hcon->hdev->workqueue, &smp->confirm); 5652b64d153SBrian Gix 5662b64d153SBrian Gix return 0; 5672b64d153SBrian Gix } 5682b64d153SBrian Gix 569da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 57088ba43b6SAnderson Briglia { 5713158c50cSVinicius Costa Gomes struct smp_cmd_pairing rsp, *req = (void *) skb->data; 5728aab4757SVinicius Costa Gomes struct smp_chan *smp; 5733158c50cSVinicius Costa Gomes u8 key_size; 5742b64d153SBrian Gix u8 auth = SMP_AUTH_NONE; 5758aab4757SVinicius Costa Gomes int ret; 57688ba43b6SAnderson Briglia 57788ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 57888ba43b6SAnderson Briglia 5792b64d153SBrian Gix if (conn->hcon->link_mode & HCI_LM_MASTER) 5802b64d153SBrian Gix return SMP_CMD_NOTSUPP; 5812b64d153SBrian Gix 58251a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 5838aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 584d08fd0e7SAndrei Emeltchenko else 5858aab4757SVinicius Costa Gomes smp = conn->smp_chan; 586d26a2345SVinicius Costa Gomes 587d08fd0e7SAndrei Emeltchenko if (!smp) 588d08fd0e7SAndrei Emeltchenko return SMP_UNSPECIFIED; 589d08fd0e7SAndrei Emeltchenko 5901c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5911c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], req, sizeof(*req)); 5923158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*req)); 59388ba43b6SAnderson Briglia 5942b64d153SBrian Gix /* We didn't start the pairing, so match remote */ 5952b64d153SBrian Gix if (req->auth_req & SMP_AUTH_BONDING) 5962b64d153SBrian Gix auth = req->auth_req; 597da85e5e5SVinicius Costa Gomes 598fdde0a26SIdo Yariv conn->hcon->pending_sec_level = authreq_to_seclevel(auth); 599fdde0a26SIdo Yariv 6002b64d153SBrian Gix build_pairing_cmd(conn, req, &rsp, auth); 6013158c50cSVinicius Costa Gomes 6023158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp.max_key_size); 6033158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6043158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 60588ba43b6SAnderson Briglia 6068aab4757SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6078aab4757SVinicius Costa Gomes if (ret) 6088aab4757SVinicius Costa Gomes return SMP_UNSPECIFIED; 6098aab4757SVinicius Costa Gomes 6101c1def09SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6111c1def09SVinicius Costa Gomes memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 612f01ead31SAnderson Briglia 6133158c50cSVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 614da85e5e5SVinicius Costa Gomes 6152b64d153SBrian Gix /* Request setup of TK */ 6162b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); 6172b64d153SBrian Gix if (ret) 6182b64d153SBrian Gix return SMP_UNSPECIFIED; 6192b64d153SBrian Gix 620da85e5e5SVinicius Costa Gomes return 0; 62188ba43b6SAnderson Briglia } 62288ba43b6SAnderson Briglia 623da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 62488ba43b6SAnderson Briglia { 6253158c50cSVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 6261c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6278aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6282b64d153SBrian Gix u8 key_size, auth = SMP_AUTH_NONE; 6297d24ddccSAnderson Briglia int ret; 63088ba43b6SAnderson Briglia 63188ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 63288ba43b6SAnderson Briglia 6332b64d153SBrian Gix if (!(conn->hcon->link_mode & HCI_LM_MASTER)) 6342b64d153SBrian Gix return SMP_CMD_NOTSUPP; 6352b64d153SBrian Gix 6363158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*rsp)); 637da85e5e5SVinicius Costa Gomes 6381c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 6393158c50cSVinicius Costa Gomes 6403158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp->max_key_size); 6413158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6423158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 6433158c50cSVinicius Costa Gomes 6441c1def09SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6457d24ddccSAnderson Briglia if (ret) 646da85e5e5SVinicius Costa Gomes return SMP_UNSPECIFIED; 6477d24ddccSAnderson Briglia 6488aab4757SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6498aab4757SVinicius Costa Gomes memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 6507d24ddccSAnderson Briglia 6512b64d153SBrian Gix if ((req->auth_req & SMP_AUTH_BONDING) && 6522b64d153SBrian Gix (rsp->auth_req & SMP_AUTH_BONDING)) 6532b64d153SBrian Gix auth = SMP_AUTH_BONDING; 6542b64d153SBrian Gix 6552b64d153SBrian Gix auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; 6562b64d153SBrian Gix 657476585ecSJohan Hedberg ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); 6582b64d153SBrian Gix if (ret) 6592b64d153SBrian Gix return SMP_UNSPECIFIED; 6602b64d153SBrian Gix 6612b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 6622b64d153SBrian Gix 6632b64d153SBrian Gix /* Can't compose response until we have been confirmed */ 6642b64d153SBrian Gix if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) 6652b64d153SBrian Gix return 0; 6662b64d153SBrian Gix 6678aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 668da85e5e5SVinicius Costa Gomes 669da85e5e5SVinicius Costa Gomes return 0; 67088ba43b6SAnderson Briglia } 67188ba43b6SAnderson Briglia 672da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 67388ba43b6SAnderson Briglia { 6741c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6758aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6767d24ddccSAnderson Briglia 67788ba43b6SAnderson Briglia BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 67888ba43b6SAnderson Briglia 6791c1def09SVinicius Costa Gomes memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 6801c1def09SVinicius Costa Gomes skb_pull(skb, sizeof(smp->pcnf)); 6817d24ddccSAnderson Briglia 68288ba43b6SAnderson Briglia if (conn->hcon->out) { 6837d24ddccSAnderson Briglia u8 random[16]; 68488ba43b6SAnderson Briglia 6851c1def09SVinicius Costa Gomes swap128(smp->prnd, random); 68688ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 6877d24ddccSAnderson Briglia random); 6882b64d153SBrian Gix } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { 6898aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 6902b64d153SBrian Gix } else { 6912b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 69288ba43b6SAnderson Briglia } 693da85e5e5SVinicius Costa Gomes 694da85e5e5SVinicius Costa Gomes return 0; 69588ba43b6SAnderson Briglia } 69688ba43b6SAnderson Briglia 697da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 69888ba43b6SAnderson Briglia { 6991c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7008aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 7017d24ddccSAnderson Briglia 7028aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 7037d24ddccSAnderson Briglia 7048aab4757SVinicius Costa Gomes swap128(skb->data, smp->rrnd); 7058aab4757SVinicius Costa Gomes skb_pull(skb, sizeof(smp->rrnd)); 70688ba43b6SAnderson Briglia 7078aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->random); 708da85e5e5SVinicius Costa Gomes 709da85e5e5SVinicius Costa Gomes return 0; 71088ba43b6SAnderson Briglia } 71188ba43b6SAnderson Briglia 7124dab7864SJohan Hedberg static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) 713988c5997SVinicius Costa Gomes { 714c9839a11SVinicius Costa Gomes struct smp_ltk *key; 715988c5997SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 716988c5997SVinicius Costa Gomes 717c9839a11SVinicius Costa Gomes key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type); 718988c5997SVinicius Costa Gomes if (!key) 719988c5997SVinicius Costa Gomes return 0; 720988c5997SVinicius Costa Gomes 7214dab7864SJohan Hedberg if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) 7224dab7864SJohan Hedberg return 0; 7234dab7864SJohan Hedberg 72451a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) 725988c5997SVinicius Costa Gomes return 1; 726988c5997SVinicius Costa Gomes 727c9839a11SVinicius Costa Gomes hci_le_start_enc(hcon, key->ediv, key->rand, key->val); 728c9839a11SVinicius Costa Gomes hcon->enc_key_size = key->enc_size; 729988c5997SVinicius Costa Gomes 730988c5997SVinicius Costa Gomes return 1; 731988c5997SVinicius Costa Gomes 732988c5997SVinicius Costa Gomes } 733da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) 73488ba43b6SAnderson Briglia { 73588ba43b6SAnderson Briglia struct smp_cmd_security_req *rp = (void *) skb->data; 73688ba43b6SAnderson Briglia struct smp_cmd_pairing cp; 737f1cb9af5SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 7388aab4757SVinicius Costa Gomes struct smp_chan *smp; 73988ba43b6SAnderson Briglia 74088ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 74188ba43b6SAnderson Briglia 7422b64d153SBrian Gix hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); 743feb45eb5SVinicius Costa Gomes 7444dab7864SJohan Hedberg if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) 745988c5997SVinicius Costa Gomes return 0; 746988c5997SVinicius Costa Gomes 74751a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 748da85e5e5SVinicius Costa Gomes return 0; 749f1cb9af5SVinicius Costa Gomes 7508aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 751d26a2345SVinicius Costa Gomes 75288ba43b6SAnderson Briglia skb_pull(skb, sizeof(*rp)); 75388ba43b6SAnderson Briglia 754da85e5e5SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 75554790f73SVinicius Costa Gomes build_pairing_cmd(conn, &cp, NULL, rp->auth_req); 75688ba43b6SAnderson Briglia 7571c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 7581c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 759f01ead31SAnderson Briglia 76088ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 761f1cb9af5SVinicius Costa Gomes 762da85e5e5SVinicius Costa Gomes return 0; 76388ba43b6SAnderson Briglia } 76488ba43b6SAnderson Briglia 765cc110922SVinicius Costa Gomes int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) 766eb492e01SAnderson Briglia { 767cc110922SVinicius Costa Gomes struct l2cap_conn *conn = hcon->l2cap_data; 7681c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7692b64d153SBrian Gix __u8 authreq; 770eb492e01SAnderson Briglia 7713a0259bbSVinicius Costa Gomes BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); 7723a0259bbSVinicius Costa Gomes 7732e65c9d2SAndre Guedes if (!lmp_host_le_capable(hcon->hdev)) 7742e65c9d2SAndre Guedes return 1; 7752e65c9d2SAndre Guedes 776f1cb9af5SVinicius Costa Gomes if (sec_level == BT_SECURITY_LOW) 777eb492e01SAnderson Briglia return 1; 778f1cb9af5SVinicius Costa Gomes 779f1cb9af5SVinicius Costa Gomes if (hcon->sec_level >= sec_level) 780f1cb9af5SVinicius Costa Gomes return 1; 781f1cb9af5SVinicius Costa Gomes 782988c5997SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) 7834dab7864SJohan Hedberg if (smp_ltk_encrypt(conn, sec_level)) 784d26a2345SVinicius Costa Gomes goto done; 785d26a2345SVinicius Costa Gomes 78651a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 787d26a2345SVinicius Costa Gomes return 0; 788d26a2345SVinicius Costa Gomes 7898aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 7902b64d153SBrian Gix if (!smp) 7912b64d153SBrian Gix return 1; 7922b64d153SBrian Gix 7932b64d153SBrian Gix authreq = seclevel_to_authreq(sec_level); 794d26a2345SVinicius Costa Gomes 795d26a2345SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) { 796d26a2345SVinicius Costa Gomes struct smp_cmd_pairing cp; 797f01ead31SAnderson Briglia 7982b64d153SBrian Gix build_pairing_cmd(conn, &cp, NULL, authreq); 7991c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 8001c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 801f01ead31SAnderson Briglia 802eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 803eb492e01SAnderson Briglia } else { 804eb492e01SAnderson Briglia struct smp_cmd_security_req cp; 8052b64d153SBrian Gix cp.auth_req = authreq; 806eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 807eb492e01SAnderson Briglia } 808eb492e01SAnderson Briglia 80902bc7455SVinicius Costa Gomes done: 810f1cb9af5SVinicius Costa Gomes hcon->pending_sec_level = sec_level; 811f1cb9af5SVinicius Costa Gomes 812eb492e01SAnderson Briglia return 0; 813eb492e01SAnderson Briglia } 814eb492e01SAnderson Briglia 8157034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) 8167034b911SVinicius Costa Gomes { 81716b90839SVinicius Costa Gomes struct smp_cmd_encrypt_info *rp = (void *) skb->data; 8181c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 81916b90839SVinicius Costa Gomes 82016b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 82116b90839SVinicius Costa Gomes 8221c1def09SVinicius Costa Gomes memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); 82316b90839SVinicius Costa Gomes 8247034b911SVinicius Costa Gomes return 0; 8257034b911SVinicius Costa Gomes } 8267034b911SVinicius Costa Gomes 8277034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) 8287034b911SVinicius Costa Gomes { 82916b90839SVinicius Costa Gomes struct smp_cmd_master_ident *rp = (void *) skb->data; 8301c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 831c9839a11SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 832c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 833c9839a11SVinicius Costa Gomes u8 authenticated; 8347034b911SVinicius Costa Gomes 83516b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 83616b90839SVinicius Costa Gomes 837c9839a11SVinicius Costa Gomes hci_dev_lock(hdev); 838c9839a11SVinicius Costa Gomes authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); 839c9839a11SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, 84004124681SGustavo F. Padovan HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, 84104124681SGustavo F. Padovan rp->ediv, rp->rand); 8427034b911SVinicius Costa Gomes smp_distribute_keys(conn, 1); 843c9839a11SVinicius Costa Gomes hci_dev_unlock(hdev); 8447034b911SVinicius Costa Gomes 8457034b911SVinicius Costa Gomes return 0; 8467034b911SVinicius Costa Gomes } 8477034b911SVinicius Costa Gomes 848eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 849eb492e01SAnderson Briglia { 850eb492e01SAnderson Briglia __u8 code = skb->data[0]; 851eb492e01SAnderson Briglia __u8 reason; 852eb492e01SAnderson Briglia int err = 0; 853eb492e01SAnderson Briglia 8542e65c9d2SAndre Guedes if (!lmp_host_le_capable(conn->hcon->hdev)) { 8552e65c9d2SAndre Guedes err = -ENOTSUPP; 8562e65c9d2SAndre Guedes reason = SMP_PAIRING_NOTSUPP; 8572e65c9d2SAndre Guedes goto done; 8582e65c9d2SAndre Guedes } 8592e65c9d2SAndre Guedes 860eb492e01SAnderson Briglia skb_pull(skb, sizeof(code)); 861eb492e01SAnderson Briglia 8628cf9fa12SJohan Hedberg /* 8638cf9fa12SJohan Hedberg * The SMP context must be initialized for all other PDUs except 8648cf9fa12SJohan Hedberg * pairing and security requests. If we get any other PDU when 8658cf9fa12SJohan Hedberg * not initialized simply disconnect (done if this function 8668cf9fa12SJohan Hedberg * returns an error). 8678cf9fa12SJohan Hedberg */ 8688cf9fa12SJohan Hedberg if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ && 8698cf9fa12SJohan Hedberg !conn->smp_chan) { 8708cf9fa12SJohan Hedberg BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); 8718cf9fa12SJohan Hedberg kfree_skb(skb); 8728cf9fa12SJohan Hedberg return -ENOTSUPP; 8738cf9fa12SJohan Hedberg } 8748cf9fa12SJohan Hedberg 875eb492e01SAnderson Briglia switch (code) { 876eb492e01SAnderson Briglia case SMP_CMD_PAIRING_REQ: 877da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_req(conn, skb); 878eb492e01SAnderson Briglia break; 879eb492e01SAnderson Briglia 880eb492e01SAnderson Briglia case SMP_CMD_PAIRING_FAIL: 8814f957a76SBrian Gix smp_failure(conn, skb->data[0], 0); 882da85e5e5SVinicius Costa Gomes reason = 0; 883da85e5e5SVinicius Costa Gomes err = -EPERM; 884eb492e01SAnderson Briglia break; 885eb492e01SAnderson Briglia 886eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RSP: 887da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_rsp(conn, skb); 88888ba43b6SAnderson Briglia break; 88988ba43b6SAnderson Briglia 89088ba43b6SAnderson Briglia case SMP_CMD_SECURITY_REQ: 891da85e5e5SVinicius Costa Gomes reason = smp_cmd_security_req(conn, skb); 89288ba43b6SAnderson Briglia break; 89388ba43b6SAnderson Briglia 894eb492e01SAnderson Briglia case SMP_CMD_PAIRING_CONFIRM: 895da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_confirm(conn, skb); 89688ba43b6SAnderson Briglia break; 89788ba43b6SAnderson Briglia 898eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RANDOM: 899da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_random(conn, skb); 90088ba43b6SAnderson Briglia break; 90188ba43b6SAnderson Briglia 902eb492e01SAnderson Briglia case SMP_CMD_ENCRYPT_INFO: 9037034b911SVinicius Costa Gomes reason = smp_cmd_encrypt_info(conn, skb); 9047034b911SVinicius Costa Gomes break; 9057034b911SVinicius Costa Gomes 906eb492e01SAnderson Briglia case SMP_CMD_MASTER_IDENT: 9077034b911SVinicius Costa Gomes reason = smp_cmd_master_ident(conn, skb); 9087034b911SVinicius Costa Gomes break; 9097034b911SVinicius Costa Gomes 910eb492e01SAnderson Briglia case SMP_CMD_IDENT_INFO: 911eb492e01SAnderson Briglia case SMP_CMD_IDENT_ADDR_INFO: 912eb492e01SAnderson Briglia case SMP_CMD_SIGN_INFO: 9137034b911SVinicius Costa Gomes /* Just ignored */ 9147034b911SVinicius Costa Gomes reason = 0; 9157034b911SVinicius Costa Gomes break; 9167034b911SVinicius Costa Gomes 917eb492e01SAnderson Briglia default: 918eb492e01SAnderson Briglia BT_DBG("Unknown command code 0x%2.2x", code); 919eb492e01SAnderson Briglia 920eb492e01SAnderson Briglia reason = SMP_CMD_NOTSUPP; 9213a0259bbSVinicius Costa Gomes err = -EOPNOTSUPP; 9223a0259bbSVinicius Costa Gomes goto done; 9233a0259bbSVinicius Costa Gomes } 9243a0259bbSVinicius Costa Gomes 9253a0259bbSVinicius Costa Gomes done: 9263a0259bbSVinicius Costa Gomes if (reason) 9274f957a76SBrian Gix smp_failure(conn, reason, 1); 928eb492e01SAnderson Briglia 929eb492e01SAnderson Briglia kfree_skb(skb); 930eb492e01SAnderson Briglia return err; 931eb492e01SAnderson Briglia } 9327034b911SVinicius Costa Gomes 9337034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) 9347034b911SVinicius Costa Gomes { 9357034b911SVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp; 9361c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 9377034b911SVinicius Costa Gomes __u8 *keydist; 9387034b911SVinicius Costa Gomes 9397034b911SVinicius Costa Gomes BT_DBG("conn %p force %d", conn, force); 9407034b911SVinicius Costa Gomes 94151a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 942d26a2345SVinicius Costa Gomes return 0; 943d26a2345SVinicius Costa Gomes 9441c1def09SVinicius Costa Gomes rsp = (void *) &smp->prsp[1]; 9457034b911SVinicius Costa Gomes 9467034b911SVinicius Costa Gomes /* The responder sends its keys first */ 9477034b911SVinicius Costa Gomes if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) 9487034b911SVinicius Costa Gomes return 0; 9497034b911SVinicius Costa Gomes 9501c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 9517034b911SVinicius Costa Gomes 9527034b911SVinicius Costa Gomes if (conn->hcon->out) { 9537034b911SVinicius Costa Gomes keydist = &rsp->init_key_dist; 9547034b911SVinicius Costa Gomes *keydist &= req->init_key_dist; 9557034b911SVinicius Costa Gomes } else { 9567034b911SVinicius Costa Gomes keydist = &rsp->resp_key_dist; 9577034b911SVinicius Costa Gomes *keydist &= req->resp_key_dist; 9587034b911SVinicius Costa Gomes } 9597034b911SVinicius Costa Gomes 9607034b911SVinicius Costa Gomes 9617034b911SVinicius Costa Gomes BT_DBG("keydist 0x%x", *keydist); 9627034b911SVinicius Costa Gomes 9637034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ENC_KEY) { 9647034b911SVinicius Costa Gomes struct smp_cmd_encrypt_info enc; 9657034b911SVinicius Costa Gomes struct smp_cmd_master_ident ident; 966c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 967c9839a11SVinicius Costa Gomes u8 authenticated; 9687034b911SVinicius Costa Gomes __le16 ediv; 9697034b911SVinicius Costa Gomes 9707034b911SVinicius Costa Gomes get_random_bytes(enc.ltk, sizeof(enc.ltk)); 9717034b911SVinicius Costa Gomes get_random_bytes(&ediv, sizeof(ediv)); 9727034b911SVinicius Costa Gomes get_random_bytes(ident.rand, sizeof(ident.rand)); 9737034b911SVinicius Costa Gomes 9747034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 9757034b911SVinicius Costa Gomes 976c9839a11SVinicius Costa Gomes authenticated = hcon->sec_level == BT_SECURITY_HIGH; 977c9839a11SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, 978c9839a11SVinicius Costa Gomes HCI_SMP_LTK_SLAVE, 1, authenticated, 97904124681SGustavo F. Padovan enc.ltk, smp->enc_key_size, ediv, ident.rand); 98016b90839SVinicius Costa Gomes 98158115373SAndrei Emeltchenko ident.ediv = ediv; 9827034b911SVinicius Costa Gomes 9837034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); 9847034b911SVinicius Costa Gomes 9857034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ENC_KEY; 9867034b911SVinicius Costa Gomes } 9877034b911SVinicius Costa Gomes 9887034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ID_KEY) { 9897034b911SVinicius Costa Gomes struct smp_cmd_ident_addr_info addrinfo; 9907034b911SVinicius Costa Gomes struct smp_cmd_ident_info idinfo; 9917034b911SVinicius Costa Gomes 9927034b911SVinicius Costa Gomes /* Send a dummy key */ 9937034b911SVinicius Costa Gomes get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); 9947034b911SVinicius Costa Gomes 9957034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 9967034b911SVinicius Costa Gomes 9977034b911SVinicius Costa Gomes /* Just public address */ 9987034b911SVinicius Costa Gomes memset(&addrinfo, 0, sizeof(addrinfo)); 9997034b911SVinicius Costa Gomes bacpy(&addrinfo.bdaddr, conn->src); 10007034b911SVinicius Costa Gomes 10017034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 10027034b911SVinicius Costa Gomes &addrinfo); 10037034b911SVinicius Costa Gomes 10047034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ID_KEY; 10057034b911SVinicius Costa Gomes } 10067034b911SVinicius Costa Gomes 10077034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_SIGN) { 10087034b911SVinicius Costa Gomes struct smp_cmd_sign_info sign; 10097034b911SVinicius Costa Gomes 10107034b911SVinicius Costa Gomes /* Send a dummy key */ 10117034b911SVinicius Costa Gomes get_random_bytes(sign.csrk, sizeof(sign.csrk)); 10127034b911SVinicius Costa Gomes 10137034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 10147034b911SVinicius Costa Gomes 10157034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_SIGN; 10167034b911SVinicius Costa Gomes } 10177034b911SVinicius Costa Gomes 1018d26a2345SVinicius Costa Gomes if (conn->hcon->out || force) { 101951a8efd7SJohan Hedberg clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); 10206c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 10218aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 1022d26a2345SVinicius Costa Gomes } 1023d26a2345SVinicius Costa Gomes 10247034b911SVinicius Costa Gomes return 0; 10257034b911SVinicius Costa Gomes } 1026