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 23eb492e01SAnderson Briglia #include <net/bluetooth/bluetooth.h> 24eb492e01SAnderson Briglia #include <net/bluetooth/hci_core.h> 25eb492e01SAnderson Briglia #include <net/bluetooth/l2cap.h> 262b64d153SBrian Gix #include <net/bluetooth/mgmt.h> 27eb492e01SAnderson Briglia #include <net/bluetooth/smp.h> 28d22ef0bcSAnderson Briglia #include <linux/crypto.h> 29f70490e6SStephen Rothwell #include <linux/scatterlist.h> 30d22ef0bcSAnderson Briglia #include <crypto/b128ops.h> 31d22ef0bcSAnderson Briglia 325d3de7dfSVinicius Costa Gomes #define SMP_TIMEOUT 30000 /* 30 seconds */ 335d3de7dfSVinicius Costa Gomes 34d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16]) 35d22ef0bcSAnderson Briglia { 36d22ef0bcSAnderson Briglia int i; 37d22ef0bcSAnderson Briglia for (i = 0; i < 16; i++) 38d22ef0bcSAnderson Briglia dst[15 - i] = src[i]; 39d22ef0bcSAnderson Briglia } 40d22ef0bcSAnderson Briglia 41d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7]) 42d22ef0bcSAnderson Briglia { 43d22ef0bcSAnderson Briglia int i; 44d22ef0bcSAnderson Briglia for (i = 0; i < 7; i++) 45d22ef0bcSAnderson Briglia dst[6 - i] = src[i]; 46d22ef0bcSAnderson Briglia } 47d22ef0bcSAnderson Briglia 48d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) 49d22ef0bcSAnderson Briglia { 50d22ef0bcSAnderson Briglia struct blkcipher_desc desc; 51d22ef0bcSAnderson Briglia struct scatterlist sg; 52d22ef0bcSAnderson Briglia int err, iv_len; 53d22ef0bcSAnderson Briglia unsigned char iv[128]; 54d22ef0bcSAnderson Briglia 55d22ef0bcSAnderson Briglia if (tfm == NULL) { 56d22ef0bcSAnderson Briglia BT_ERR("tfm %p", tfm); 57d22ef0bcSAnderson Briglia return -EINVAL; 58d22ef0bcSAnderson Briglia } 59d22ef0bcSAnderson Briglia 60d22ef0bcSAnderson Briglia desc.tfm = tfm; 61d22ef0bcSAnderson Briglia desc.flags = 0; 62d22ef0bcSAnderson Briglia 63d22ef0bcSAnderson Briglia err = crypto_blkcipher_setkey(tfm, k, 16); 64d22ef0bcSAnderson Briglia if (err) { 65d22ef0bcSAnderson Briglia BT_ERR("cipher setkey failed: %d", err); 66d22ef0bcSAnderson Briglia return err; 67d22ef0bcSAnderson Briglia } 68d22ef0bcSAnderson Briglia 69d22ef0bcSAnderson Briglia sg_init_one(&sg, r, 16); 70d22ef0bcSAnderson Briglia 71d22ef0bcSAnderson Briglia iv_len = crypto_blkcipher_ivsize(tfm); 72d22ef0bcSAnderson Briglia if (iv_len) { 73d22ef0bcSAnderson Briglia memset(&iv, 0xff, iv_len); 74d22ef0bcSAnderson Briglia crypto_blkcipher_set_iv(tfm, iv, iv_len); 75d22ef0bcSAnderson Briglia } 76d22ef0bcSAnderson Briglia 77d22ef0bcSAnderson Briglia err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); 78d22ef0bcSAnderson Briglia if (err) 79d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error %d", err); 80d22ef0bcSAnderson Briglia 81d22ef0bcSAnderson Briglia return err; 82d22ef0bcSAnderson Briglia } 83d22ef0bcSAnderson Briglia 84d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], 85d22ef0bcSAnderson Briglia u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, 86d22ef0bcSAnderson Briglia u8 _rat, bdaddr_t *ra, u8 res[16]) 87d22ef0bcSAnderson Briglia { 88d22ef0bcSAnderson Briglia u8 p1[16], p2[16]; 89d22ef0bcSAnderson Briglia int err; 90d22ef0bcSAnderson Briglia 91d22ef0bcSAnderson Briglia memset(p1, 0, 16); 92d22ef0bcSAnderson Briglia 93d22ef0bcSAnderson Briglia /* p1 = pres || preq || _rat || _iat */ 94d22ef0bcSAnderson Briglia swap56(pres, p1); 95d22ef0bcSAnderson Briglia swap56(preq, p1 + 7); 96d22ef0bcSAnderson Briglia p1[14] = _rat; 97d22ef0bcSAnderson Briglia p1[15] = _iat; 98d22ef0bcSAnderson Briglia 99d22ef0bcSAnderson Briglia memset(p2, 0, 16); 100d22ef0bcSAnderson Briglia 101d22ef0bcSAnderson Briglia /* p2 = padding || ia || ra */ 102d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 4), ia); 103d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 10), ra); 104d22ef0bcSAnderson Briglia 105d22ef0bcSAnderson Briglia /* res = r XOR p1 */ 106d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); 107d22ef0bcSAnderson Briglia 108d22ef0bcSAnderson Briglia /* res = e(k, res) */ 109d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 110d22ef0bcSAnderson Briglia if (err) { 111d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 112d22ef0bcSAnderson Briglia return err; 113d22ef0bcSAnderson Briglia } 114d22ef0bcSAnderson Briglia 115d22ef0bcSAnderson Briglia /* res = res XOR p2 */ 116d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); 117d22ef0bcSAnderson Briglia 118d22ef0bcSAnderson Briglia /* res = e(k, res) */ 119d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 120d22ef0bcSAnderson Briglia if (err) 121d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 122d22ef0bcSAnderson Briglia 123d22ef0bcSAnderson Briglia return err; 124d22ef0bcSAnderson Briglia } 125d22ef0bcSAnderson Briglia 126d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], 127d22ef0bcSAnderson Briglia u8 r1[16], u8 r2[16], u8 _r[16]) 128d22ef0bcSAnderson Briglia { 129d22ef0bcSAnderson Briglia int err; 130d22ef0bcSAnderson Briglia 131d22ef0bcSAnderson Briglia /* Just least significant octets from r1 and r2 are considered */ 132d22ef0bcSAnderson Briglia memcpy(_r, r1 + 8, 8); 133d22ef0bcSAnderson Briglia memcpy(_r + 8, r2 + 8, 8); 134d22ef0bcSAnderson Briglia 135d22ef0bcSAnderson Briglia err = smp_e(tfm, k, _r); 136d22ef0bcSAnderson Briglia if (err) 137d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 138d22ef0bcSAnderson Briglia 139d22ef0bcSAnderson Briglia return err; 140d22ef0bcSAnderson Briglia } 141d22ef0bcSAnderson Briglia 142d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf) 143d22ef0bcSAnderson Briglia { 144d22ef0bcSAnderson Briglia get_random_bytes(buf, 16); 145d22ef0bcSAnderson Briglia 146d22ef0bcSAnderson Briglia return 0; 147d22ef0bcSAnderson Briglia } 148eb492e01SAnderson Briglia 149eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, 150eb492e01SAnderson Briglia u16 dlen, void *data) 151eb492e01SAnderson Briglia { 152eb492e01SAnderson Briglia struct sk_buff *skb; 153eb492e01SAnderson Briglia struct l2cap_hdr *lh; 154eb492e01SAnderson Briglia int len; 155eb492e01SAnderson Briglia 156eb492e01SAnderson Briglia len = L2CAP_HDR_SIZE + sizeof(code) + dlen; 157eb492e01SAnderson Briglia 158eb492e01SAnderson Briglia if (len > conn->mtu) 159eb492e01SAnderson Briglia return NULL; 160eb492e01SAnderson Briglia 161eb492e01SAnderson Briglia skb = bt_skb_alloc(len, GFP_ATOMIC); 162eb492e01SAnderson Briglia if (!skb) 163eb492e01SAnderson Briglia return NULL; 164eb492e01SAnderson Briglia 165eb492e01SAnderson Briglia lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 166eb492e01SAnderson Briglia lh->len = cpu_to_le16(sizeof(code) + dlen); 167eb492e01SAnderson Briglia lh->cid = cpu_to_le16(L2CAP_CID_SMP); 168eb492e01SAnderson Briglia 169eb492e01SAnderson Briglia memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); 170eb492e01SAnderson Briglia 171eb492e01SAnderson Briglia memcpy(skb_put(skb, dlen), data, dlen); 172eb492e01SAnderson Briglia 173eb492e01SAnderson Briglia return skb; 174eb492e01SAnderson Briglia } 175eb492e01SAnderson Briglia 176eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) 177eb492e01SAnderson Briglia { 178eb492e01SAnderson Briglia struct sk_buff *skb = smp_build_cmd(conn, code, len, data); 179eb492e01SAnderson Briglia 180eb492e01SAnderson Briglia BT_DBG("code 0x%2.2x", code); 181eb492e01SAnderson Briglia 182eb492e01SAnderson Briglia if (!skb) 183eb492e01SAnderson Briglia return; 184eb492e01SAnderson Briglia 18573d80debSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX; 18673d80debSLuiz Augusto von Dentz hci_send_acl(conn->hchan, skb, 0); 187e2dcd113SVinicius Costa Gomes 1886c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 1896c9d42a1SGustavo F. Padovan schedule_delayed_work(&conn->security_timer, 190e2dcd113SVinicius Costa Gomes msecs_to_jiffies(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 2531c1def09SVinicius Costa Gomes smp->smp_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 { 2604f957a76SBrian Gix if (send) 2614f957a76SBrian Gix smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), 2624f957a76SBrian Gix &reason); 2634f957a76SBrian Gix 2644f957a76SBrian Gix clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); 2654f957a76SBrian Gix mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason); 2666c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 2674f957a76SBrian Gix smp_chan_destroy(conn); 2684f957a76SBrian Gix } 2694f957a76SBrian Gix 2702b64d153SBrian Gix #define JUST_WORKS 0x00 2712b64d153SBrian Gix #define JUST_CFM 0x01 2722b64d153SBrian Gix #define REQ_PASSKEY 0x02 2732b64d153SBrian Gix #define CFM_PASSKEY 0x03 2742b64d153SBrian Gix #define REQ_OOB 0x04 2752b64d153SBrian Gix #define OVERLAP 0xFF 2762b64d153SBrian Gix 2772b64d153SBrian Gix static const u8 gen_method[5][5] = { 2782b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2792b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2802b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 2812b64d153SBrian Gix { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, 2822b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, 2832b64d153SBrian Gix }; 2842b64d153SBrian Gix 2852b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, 2862b64d153SBrian Gix u8 local_io, u8 remote_io) 2872b64d153SBrian Gix { 2882b64d153SBrian Gix struct hci_conn *hcon = conn->hcon; 2892b64d153SBrian Gix struct smp_chan *smp = conn->smp_chan; 2902b64d153SBrian Gix u8 method; 2912b64d153SBrian Gix u32 passkey = 0; 2922b64d153SBrian Gix int ret = 0; 2932b64d153SBrian Gix 2942b64d153SBrian Gix /* Initialize key for JUST WORKS */ 2952b64d153SBrian Gix memset(smp->tk, 0, sizeof(smp->tk)); 2962b64d153SBrian Gix clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 2972b64d153SBrian Gix 2982b64d153SBrian Gix BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); 2992b64d153SBrian Gix 3002b64d153SBrian Gix /* If neither side wants MITM, use JUST WORKS */ 3012b64d153SBrian Gix /* If either side has unknown io_caps, use JUST WORKS */ 3022b64d153SBrian Gix /* Otherwise, look up method from the table */ 3032b64d153SBrian Gix if (!(auth & SMP_AUTH_MITM) || 3042b64d153SBrian Gix local_io > SMP_IO_KEYBOARD_DISPLAY || 3052b64d153SBrian Gix remote_io > SMP_IO_KEYBOARD_DISPLAY) 3062b64d153SBrian Gix method = JUST_WORKS; 3072b64d153SBrian Gix else 3082b64d153SBrian Gix method = gen_method[local_io][remote_io]; 3092b64d153SBrian Gix 3102b64d153SBrian Gix /* If not bonding, don't ask user to confirm a Zero TK */ 3112b64d153SBrian Gix if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) 3122b64d153SBrian Gix method = JUST_WORKS; 3132b64d153SBrian Gix 3142b64d153SBrian Gix /* If Just Works, Continue with Zero TK */ 3152b64d153SBrian Gix if (method == JUST_WORKS) { 3162b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3172b64d153SBrian Gix return 0; 3182b64d153SBrian Gix } 3192b64d153SBrian Gix 3202b64d153SBrian Gix /* Not Just Works/Confirm results in MITM Authentication */ 3212b64d153SBrian Gix if (method != JUST_CFM) 3222b64d153SBrian Gix set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags); 3232b64d153SBrian Gix 3242b64d153SBrian Gix /* If both devices have Keyoard-Display I/O, the master 3252b64d153SBrian Gix * Confirms and the slave Enters the passkey. 3262b64d153SBrian Gix */ 3272b64d153SBrian Gix if (method == OVERLAP) { 3282b64d153SBrian Gix if (hcon->link_mode & HCI_LM_MASTER) 3292b64d153SBrian Gix method = CFM_PASSKEY; 3302b64d153SBrian Gix else 3312b64d153SBrian Gix method = REQ_PASSKEY; 3322b64d153SBrian Gix } 3332b64d153SBrian Gix 3342b64d153SBrian Gix /* Generate random passkey. Not valid until confirmed. */ 3352b64d153SBrian Gix if (method == CFM_PASSKEY) { 3362b64d153SBrian Gix u8 key[16]; 3372b64d153SBrian Gix 3382b64d153SBrian Gix memset(key, 0, sizeof(key)); 3392b64d153SBrian Gix get_random_bytes(&passkey, sizeof(passkey)); 3402b64d153SBrian Gix passkey %= 1000000; 3412b64d153SBrian Gix put_unaligned_le32(passkey, key); 3422b64d153SBrian Gix swap128(key, smp->tk); 3432b64d153SBrian Gix BT_DBG("PassKey: %d", passkey); 3442b64d153SBrian Gix } 3452b64d153SBrian Gix 3462b64d153SBrian Gix hci_dev_lock(hcon->hdev); 3472b64d153SBrian Gix 3482b64d153SBrian Gix if (method == REQ_PASSKEY) 3492b64d153SBrian Gix ret = mgmt_user_passkey_request(hcon->hdev, conn->dst); 3502b64d153SBrian Gix else 3512b64d153SBrian Gix ret = mgmt_user_confirm_request(hcon->hdev, conn->dst, 3522b64d153SBrian Gix cpu_to_le32(passkey), 0); 3532b64d153SBrian Gix 3542b64d153SBrian Gix hci_dev_unlock(hcon->hdev); 3552b64d153SBrian Gix 3562b64d153SBrian Gix return ret; 3572b64d153SBrian Gix } 3582b64d153SBrian Gix 3598aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work) 3608aab4757SVinicius Costa Gomes { 3618aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, confirm); 3628aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 3638aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm; 3648aab4757SVinicius Costa Gomes struct smp_cmd_pairing_confirm cp; 3658aab4757SVinicius Costa Gomes int ret; 3668aab4757SVinicius Costa Gomes u8 res[16], reason; 3678aab4757SVinicius Costa Gomes 3688aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 3698aab4757SVinicius Costa Gomes 3708aab4757SVinicius Costa Gomes tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); 3718aab4757SVinicius Costa Gomes if (IS_ERR(tfm)) { 3728aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3738aab4757SVinicius Costa Gomes goto error; 3748aab4757SVinicius Costa Gomes } 3758aab4757SVinicius Costa Gomes 3768aab4757SVinicius Costa Gomes smp->tfm = tfm; 3778aab4757SVinicius Costa Gomes 3788aab4757SVinicius Costa Gomes if (conn->hcon->out) 3798aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, 3808aab4757SVinicius Costa Gomes conn->src, conn->hcon->dst_type, conn->dst, 3818aab4757SVinicius Costa Gomes res); 3828aab4757SVinicius Costa Gomes else 3838aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 3848aab4757SVinicius Costa Gomes conn->hcon->dst_type, conn->dst, 0, conn->src, 3858aab4757SVinicius Costa Gomes res); 3868aab4757SVinicius Costa Gomes if (ret) { 3878aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3888aab4757SVinicius Costa Gomes goto error; 3898aab4757SVinicius Costa Gomes } 3908aab4757SVinicius Costa Gomes 3912b64d153SBrian Gix clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 3922b64d153SBrian Gix 3938aab4757SVinicius Costa Gomes swap128(res, cp.confirm_val); 3948aab4757SVinicius Costa Gomes smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 3958aab4757SVinicius Costa Gomes 3968aab4757SVinicius Costa Gomes return; 3978aab4757SVinicius Costa Gomes 3988aab4757SVinicius Costa Gomes error: 3994f957a76SBrian Gix smp_failure(conn, reason, 1); 4008aab4757SVinicius Costa Gomes } 4018aab4757SVinicius Costa Gomes 4028aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work) 4038aab4757SVinicius Costa Gomes { 4048aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, random); 4058aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 4068aab4757SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 4078aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm = smp->tfm; 4088aab4757SVinicius Costa Gomes u8 reason, confirm[16], res[16], key[16]; 4098aab4757SVinicius Costa Gomes int ret; 4108aab4757SVinicius Costa Gomes 4118aab4757SVinicius Costa Gomes if (IS_ERR_OR_NULL(tfm)) { 4128aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4138aab4757SVinicius Costa Gomes goto error; 4148aab4757SVinicius Costa Gomes } 4158aab4757SVinicius Costa Gomes 4168aab4757SVinicius Costa Gomes BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 4178aab4757SVinicius Costa Gomes 4188aab4757SVinicius Costa Gomes if (hcon->out) 4198aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, 4208aab4757SVinicius Costa Gomes conn->src, hcon->dst_type, conn->dst, 4218aab4757SVinicius Costa Gomes res); 4228aab4757SVinicius Costa Gomes else 4238aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 4248aab4757SVinicius Costa Gomes hcon->dst_type, conn->dst, 0, conn->src, 4258aab4757SVinicius Costa Gomes res); 4268aab4757SVinicius Costa Gomes if (ret) { 4278aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4288aab4757SVinicius Costa Gomes goto error; 4298aab4757SVinicius Costa Gomes } 4308aab4757SVinicius Costa Gomes 4318aab4757SVinicius Costa Gomes swap128(res, confirm); 4328aab4757SVinicius Costa Gomes 4338aab4757SVinicius Costa Gomes if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { 4348aab4757SVinicius Costa Gomes BT_ERR("Pairing failed (confirmation values mismatch)"); 4358aab4757SVinicius Costa Gomes reason = SMP_CONFIRM_FAILED; 4368aab4757SVinicius Costa Gomes goto error; 4378aab4757SVinicius Costa Gomes } 4388aab4757SVinicius Costa Gomes 4398aab4757SVinicius Costa Gomes if (hcon->out) { 4408aab4757SVinicius Costa Gomes u8 stk[16], rand[8]; 4418aab4757SVinicius Costa Gomes __le16 ediv; 4428aab4757SVinicius Costa Gomes 4438aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4448aab4757SVinicius Costa Gomes ediv = 0; 4458aab4757SVinicius Costa Gomes 4468aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); 4478aab4757SVinicius Costa Gomes swap128(key, stk); 4488aab4757SVinicius Costa Gomes 4498aab4757SVinicius Costa Gomes memset(stk + smp->smp_key_size, 0, 4508aab4757SVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); 4518aab4757SVinicius Costa Gomes 4528aab4757SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) { 4538aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4548aab4757SVinicius Costa Gomes goto error; 4558aab4757SVinicius Costa Gomes } 4568aab4757SVinicius Costa Gomes 4578aab4757SVinicius Costa Gomes hci_le_start_enc(hcon, ediv, rand, stk); 4588aab4757SVinicius Costa Gomes hcon->enc_key_size = smp->smp_key_size; 4598aab4757SVinicius Costa Gomes } else { 4608aab4757SVinicius Costa Gomes u8 stk[16], r[16], rand[8]; 4618aab4757SVinicius Costa Gomes __le16 ediv; 4628aab4757SVinicius Costa Gomes 4638aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4648aab4757SVinicius Costa Gomes ediv = 0; 4658aab4757SVinicius Costa Gomes 4668aab4757SVinicius Costa Gomes swap128(smp->prnd, r); 4678aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 4688aab4757SVinicius Costa Gomes 4698aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); 4708aab4757SVinicius Costa Gomes swap128(key, stk); 4718aab4757SVinicius Costa Gomes 4728aab4757SVinicius Costa Gomes memset(stk + smp->smp_key_size, 0, 4738aab4757SVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); 4748aab4757SVinicius Costa Gomes 4758aab4757SVinicius Costa Gomes hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size, 4768aab4757SVinicius Costa Gomes ediv, rand, stk); 4778aab4757SVinicius Costa Gomes } 4788aab4757SVinicius Costa Gomes 4798aab4757SVinicius Costa Gomes return; 4808aab4757SVinicius Costa Gomes 4818aab4757SVinicius Costa Gomes error: 4824f957a76SBrian Gix smp_failure(conn, reason, 1); 4838aab4757SVinicius Costa Gomes } 4848aab4757SVinicius Costa Gomes 4858aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 4868aab4757SVinicius Costa Gomes { 4878aab4757SVinicius Costa Gomes struct smp_chan *smp; 4888aab4757SVinicius Costa Gomes 4898aab4757SVinicius Costa Gomes smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); 4908aab4757SVinicius Costa Gomes if (!smp) 4918aab4757SVinicius Costa Gomes return NULL; 4928aab4757SVinicius Costa Gomes 4938aab4757SVinicius Costa Gomes INIT_WORK(&smp->confirm, confirm_work); 4948aab4757SVinicius Costa Gomes INIT_WORK(&smp->random, random_work); 4958aab4757SVinicius Costa Gomes 4968aab4757SVinicius Costa Gomes smp->conn = conn; 4978aab4757SVinicius Costa Gomes conn->smp_chan = smp; 4982b64d153SBrian Gix conn->hcon->smp_conn = conn; 4998aab4757SVinicius Costa Gomes 5008aab4757SVinicius Costa Gomes hci_conn_hold(conn->hcon); 5018aab4757SVinicius Costa Gomes 5028aab4757SVinicius Costa Gomes return smp; 5038aab4757SVinicius Costa Gomes } 5048aab4757SVinicius Costa Gomes 5058aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn) 5068aab4757SVinicius Costa Gomes { 507c8eb9690SBrian Gix struct smp_chan *smp = conn->smp_chan; 508c8eb9690SBrian Gix 509c8eb9690SBrian Gix clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); 510c8eb9690SBrian Gix 511c8eb9690SBrian Gix if (smp->tfm) 512c8eb9690SBrian Gix crypto_free_blkcipher(smp->tfm); 513c8eb9690SBrian Gix 514c8eb9690SBrian Gix kfree(smp); 515c8eb9690SBrian Gix conn->smp_chan = NULL; 5162b64d153SBrian Gix conn->hcon->smp_conn = NULL; 5178aab4757SVinicius Costa Gomes hci_conn_put(conn->hcon); 5188aab4757SVinicius Costa Gomes } 5198aab4757SVinicius Costa Gomes 5202b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) 5212b64d153SBrian Gix { 5222b64d153SBrian Gix struct l2cap_conn *conn = hcon->smp_conn; 5232b64d153SBrian Gix struct smp_chan *smp; 5242b64d153SBrian Gix u32 value; 5252b64d153SBrian Gix u8 key[16]; 5262b64d153SBrian Gix 5272b64d153SBrian Gix BT_DBG(""); 5282b64d153SBrian Gix 5292b64d153SBrian Gix if (!conn) 5302b64d153SBrian Gix return -ENOTCONN; 5312b64d153SBrian Gix 5322b64d153SBrian Gix smp = conn->smp_chan; 5332b64d153SBrian Gix 5342b64d153SBrian Gix switch (mgmt_op) { 5352b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_REPLY: 5362b64d153SBrian Gix value = le32_to_cpu(passkey); 5372b64d153SBrian Gix memset(key, 0, sizeof(key)); 5382b64d153SBrian Gix BT_DBG("PassKey: %d", value); 5392b64d153SBrian Gix put_unaligned_le32(value, key); 5402b64d153SBrian Gix swap128(key, smp->tk); 5412b64d153SBrian Gix /* Fall Through */ 5422b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_REPLY: 5432b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 5442b64d153SBrian Gix break; 5452b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_NEG_REPLY: 5462b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_NEG_REPLY: 5472b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5482b64d153SBrian Gix return 0; 5492b64d153SBrian Gix default: 5502b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5512b64d153SBrian Gix return -EOPNOTSUPP; 5522b64d153SBrian Gix } 5532b64d153SBrian Gix 5542b64d153SBrian Gix /* If it is our turn to send Pairing Confirm, do so now */ 5552b64d153SBrian Gix if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags)) 5562b64d153SBrian Gix queue_work(hcon->hdev->workqueue, &smp->confirm); 5572b64d153SBrian Gix 5582b64d153SBrian Gix return 0; 5592b64d153SBrian Gix } 5602b64d153SBrian Gix 561da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 56288ba43b6SAnderson Briglia { 5633158c50cSVinicius Costa Gomes struct smp_cmd_pairing rsp, *req = (void *) skb->data; 5648aab4757SVinicius Costa Gomes struct smp_chan *smp; 5653158c50cSVinicius Costa Gomes u8 key_size; 5662b64d153SBrian Gix u8 auth = SMP_AUTH_NONE; 5678aab4757SVinicius Costa Gomes int ret; 56888ba43b6SAnderson Briglia 56988ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 57088ba43b6SAnderson Briglia 5712b64d153SBrian Gix if (conn->hcon->link_mode & HCI_LM_MASTER) 5722b64d153SBrian Gix return SMP_CMD_NOTSUPP; 5732b64d153SBrian Gix 574d26a2345SVinicius Costa Gomes if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) 5758aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 5768aab4757SVinicius Costa Gomes 5778aab4757SVinicius Costa Gomes smp = conn->smp_chan; 578d26a2345SVinicius Costa Gomes 5791c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5801c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], req, sizeof(*req)); 5813158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*req)); 58288ba43b6SAnderson Briglia 5832b64d153SBrian Gix /* We didn't start the pairing, so match remote */ 5842b64d153SBrian Gix if (req->auth_req & SMP_AUTH_BONDING) 5852b64d153SBrian Gix auth = req->auth_req; 586da85e5e5SVinicius Costa Gomes 5872b64d153SBrian Gix build_pairing_cmd(conn, req, &rsp, auth); 5883158c50cSVinicius Costa Gomes 5893158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp.max_key_size); 5903158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 5913158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 59288ba43b6SAnderson Briglia 5938aab4757SVinicius Costa Gomes ret = smp_rand(smp->prnd); 5948aab4757SVinicius Costa Gomes if (ret) 5958aab4757SVinicius Costa Gomes return SMP_UNSPECIFIED; 5968aab4757SVinicius Costa Gomes 5971c1def09SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 5981c1def09SVinicius Costa Gomes memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 599f01ead31SAnderson Briglia 6003158c50cSVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 601da85e5e5SVinicius Costa Gomes 6022b64d153SBrian Gix /* Request setup of TK */ 6032b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); 6042b64d153SBrian Gix if (ret) 6052b64d153SBrian Gix return SMP_UNSPECIFIED; 6062b64d153SBrian Gix 607da85e5e5SVinicius Costa Gomes return 0; 60888ba43b6SAnderson Briglia } 60988ba43b6SAnderson Briglia 610da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 61188ba43b6SAnderson Briglia { 6123158c50cSVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 6131c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6148aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6152b64d153SBrian Gix u8 key_size, auth = SMP_AUTH_NONE; 6167d24ddccSAnderson Briglia int ret; 61788ba43b6SAnderson Briglia 61888ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 61988ba43b6SAnderson Briglia 6202b64d153SBrian Gix if (!(conn->hcon->link_mode & HCI_LM_MASTER)) 6212b64d153SBrian Gix return SMP_CMD_NOTSUPP; 6222b64d153SBrian Gix 6233158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*rsp)); 624da85e5e5SVinicius Costa Gomes 6251c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 6263158c50cSVinicius Costa Gomes 6273158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp->max_key_size); 6283158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6293158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 6303158c50cSVinicius Costa Gomes 6311c1def09SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6327d24ddccSAnderson Briglia if (ret) 633da85e5e5SVinicius Costa Gomes return SMP_UNSPECIFIED; 6347d24ddccSAnderson Briglia 6358aab4757SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6368aab4757SVinicius Costa Gomes memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 6377d24ddccSAnderson Briglia 6382b64d153SBrian Gix if ((req->auth_req & SMP_AUTH_BONDING) && 6392b64d153SBrian Gix (rsp->auth_req & SMP_AUTH_BONDING)) 6402b64d153SBrian Gix auth = SMP_AUTH_BONDING; 6412b64d153SBrian Gix 6422b64d153SBrian Gix auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; 6432b64d153SBrian Gix 6442b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability); 6452b64d153SBrian Gix if (ret) 6462b64d153SBrian Gix return SMP_UNSPECIFIED; 6472b64d153SBrian Gix 6482b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 6492b64d153SBrian Gix 6502b64d153SBrian Gix /* Can't compose response until we have been confirmed */ 6512b64d153SBrian Gix if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) 6522b64d153SBrian Gix return 0; 6532b64d153SBrian Gix 6548aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 655da85e5e5SVinicius Costa Gomes 656da85e5e5SVinicius Costa Gomes return 0; 65788ba43b6SAnderson Briglia } 65888ba43b6SAnderson Briglia 659da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 66088ba43b6SAnderson Briglia { 6611c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6628aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6637d24ddccSAnderson Briglia 66488ba43b6SAnderson Briglia BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 66588ba43b6SAnderson Briglia 6661c1def09SVinicius Costa Gomes memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 6671c1def09SVinicius Costa Gomes skb_pull(skb, sizeof(smp->pcnf)); 6687d24ddccSAnderson Briglia 66988ba43b6SAnderson Briglia if (conn->hcon->out) { 6707d24ddccSAnderson Briglia u8 random[16]; 67188ba43b6SAnderson Briglia 6721c1def09SVinicius Costa Gomes swap128(smp->prnd, random); 67388ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 6747d24ddccSAnderson Briglia random); 6752b64d153SBrian Gix } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { 6768aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 6772b64d153SBrian Gix } else { 6782b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 67988ba43b6SAnderson Briglia } 680da85e5e5SVinicius Costa Gomes 681da85e5e5SVinicius Costa Gomes return 0; 68288ba43b6SAnderson Briglia } 68388ba43b6SAnderson Briglia 684da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 68588ba43b6SAnderson Briglia { 6861c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6878aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6887d24ddccSAnderson Briglia 6898aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 6907d24ddccSAnderson Briglia 6918aab4757SVinicius Costa Gomes swap128(skb->data, smp->rrnd); 6928aab4757SVinicius Costa Gomes skb_pull(skb, sizeof(smp->rrnd)); 69388ba43b6SAnderson Briglia 6948aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->random); 695da85e5e5SVinicius Costa Gomes 696da85e5e5SVinicius Costa Gomes return 0; 69788ba43b6SAnderson Briglia } 69888ba43b6SAnderson Briglia 699988c5997SVinicius Costa Gomes static u8 smp_ltk_encrypt(struct l2cap_conn *conn) 700988c5997SVinicius Costa Gomes { 701988c5997SVinicius Costa Gomes struct link_key *key; 702988c5997SVinicius Costa Gomes struct key_master_id *master; 703988c5997SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 704988c5997SVinicius Costa Gomes 705988c5997SVinicius Costa Gomes key = hci_find_link_key_type(hcon->hdev, conn->dst, 706988c5997SVinicius Costa Gomes HCI_LK_SMP_LTK); 707988c5997SVinicius Costa Gomes if (!key) 708988c5997SVinicius Costa Gomes return 0; 709988c5997SVinicius Costa Gomes 710988c5997SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, 711988c5997SVinicius Costa Gomes &hcon->pend)) 712988c5997SVinicius Costa Gomes return 1; 713988c5997SVinicius Costa Gomes 714988c5997SVinicius Costa Gomes master = (void *) key->data; 715988c5997SVinicius Costa Gomes hci_le_start_enc(hcon, master->ediv, master->rand, 716988c5997SVinicius Costa Gomes key->val); 717988c5997SVinicius Costa Gomes hcon->enc_key_size = key->pin_len; 718988c5997SVinicius Costa Gomes 719988c5997SVinicius Costa Gomes return 1; 720988c5997SVinicius Costa Gomes 721988c5997SVinicius Costa Gomes } 722da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) 72388ba43b6SAnderson Briglia { 72488ba43b6SAnderson Briglia struct smp_cmd_security_req *rp = (void *) skb->data; 72588ba43b6SAnderson Briglia struct smp_cmd_pairing cp; 726f1cb9af5SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 7278aab4757SVinicius Costa Gomes struct smp_chan *smp; 72888ba43b6SAnderson Briglia 72988ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 73088ba43b6SAnderson Briglia 7312b64d153SBrian Gix hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); 732feb45eb5SVinicius Costa Gomes 733988c5997SVinicius Costa Gomes if (smp_ltk_encrypt(conn)) 734988c5997SVinicius Costa Gomes return 0; 735988c5997SVinicius Costa Gomes 736d26a2345SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) 737da85e5e5SVinicius Costa Gomes return 0; 738f1cb9af5SVinicius Costa Gomes 7398aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 740d26a2345SVinicius Costa Gomes 74188ba43b6SAnderson Briglia skb_pull(skb, sizeof(*rp)); 74288ba43b6SAnderson Briglia 743da85e5e5SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 74454790f73SVinicius Costa Gomes build_pairing_cmd(conn, &cp, NULL, rp->auth_req); 74588ba43b6SAnderson Briglia 7461c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 7471c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 748f01ead31SAnderson Briglia 74988ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 750f1cb9af5SVinicius Costa Gomes 751da85e5e5SVinicius Costa Gomes return 0; 75288ba43b6SAnderson Briglia } 75388ba43b6SAnderson Briglia 754eb492e01SAnderson Briglia int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) 755eb492e01SAnderson Briglia { 7563a0259bbSVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 7571c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7582b64d153SBrian Gix __u8 authreq; 759eb492e01SAnderson Briglia 7603a0259bbSVinicius Costa Gomes BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); 7613a0259bbSVinicius Costa Gomes 7622e65c9d2SAndre Guedes if (!lmp_host_le_capable(hcon->hdev)) 7632e65c9d2SAndre Guedes return 1; 7642e65c9d2SAndre Guedes 765f1cb9af5SVinicius Costa Gomes if (sec_level == BT_SECURITY_LOW) 766eb492e01SAnderson Briglia return 1; 767f1cb9af5SVinicius Costa Gomes 768f1cb9af5SVinicius Costa Gomes if (hcon->sec_level >= sec_level) 769f1cb9af5SVinicius Costa Gomes return 1; 770f1cb9af5SVinicius Costa Gomes 771988c5997SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) 772988c5997SVinicius Costa Gomes if (smp_ltk_encrypt(conn)) 773d26a2345SVinicius Costa Gomes goto done; 774d26a2345SVinicius Costa Gomes 775d26a2345SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) 776d26a2345SVinicius Costa Gomes return 0; 777d26a2345SVinicius Costa Gomes 7788aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 7792b64d153SBrian Gix if (!smp) 7802b64d153SBrian Gix return 1; 7812b64d153SBrian Gix 7822b64d153SBrian Gix authreq = seclevel_to_authreq(sec_level); 783d26a2345SVinicius Costa Gomes 784d26a2345SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) { 785d26a2345SVinicius Costa Gomes struct smp_cmd_pairing cp; 786f01ead31SAnderson Briglia 7872b64d153SBrian Gix build_pairing_cmd(conn, &cp, NULL, authreq); 7881c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 7891c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 790f01ead31SAnderson Briglia 791eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 792eb492e01SAnderson Briglia } else { 793eb492e01SAnderson Briglia struct smp_cmd_security_req cp; 7942b64d153SBrian Gix cp.auth_req = authreq; 795eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 796eb492e01SAnderson Briglia } 797eb492e01SAnderson Briglia 79802bc7455SVinicius Costa Gomes done: 799f1cb9af5SVinicius Costa Gomes hcon->pending_sec_level = sec_level; 800f1cb9af5SVinicius Costa Gomes 801eb492e01SAnderson Briglia return 0; 802eb492e01SAnderson Briglia } 803eb492e01SAnderson Briglia 8047034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) 8057034b911SVinicius Costa Gomes { 80616b90839SVinicius Costa Gomes struct smp_cmd_encrypt_info *rp = (void *) skb->data; 8071c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 80816b90839SVinicius Costa Gomes 80916b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 81016b90839SVinicius Costa Gomes 8111c1def09SVinicius Costa Gomes memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); 81216b90839SVinicius Costa Gomes 8137034b911SVinicius Costa Gomes return 0; 8147034b911SVinicius Costa Gomes } 8157034b911SVinicius Costa Gomes 8167034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) 8177034b911SVinicius Costa Gomes { 81816b90839SVinicius Costa Gomes struct smp_cmd_master_ident *rp = (void *) skb->data; 8191c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 8207034b911SVinicius Costa Gomes 82116b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 82216b90839SVinicius Costa Gomes 8233573b80cSHemant Gupta hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size, 8241c1def09SVinicius Costa Gomes rp->ediv, rp->rand, smp->tk); 8257034b911SVinicius Costa Gomes 8267034b911SVinicius Costa Gomes smp_distribute_keys(conn, 1); 8277034b911SVinicius Costa Gomes 8287034b911SVinicius Costa Gomes return 0; 8297034b911SVinicius Costa Gomes } 8307034b911SVinicius Costa Gomes 831eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 832eb492e01SAnderson Briglia { 833eb492e01SAnderson Briglia __u8 code = skb->data[0]; 834eb492e01SAnderson Briglia __u8 reason; 835eb492e01SAnderson Briglia int err = 0; 836eb492e01SAnderson Briglia 8372e65c9d2SAndre Guedes if (!lmp_host_le_capable(conn->hcon->hdev)) { 8382e65c9d2SAndre Guedes err = -ENOTSUPP; 8392e65c9d2SAndre Guedes reason = SMP_PAIRING_NOTSUPP; 8402e65c9d2SAndre Guedes goto done; 8412e65c9d2SAndre Guedes } 8422e65c9d2SAndre Guedes 843eb492e01SAnderson Briglia skb_pull(skb, sizeof(code)); 844eb492e01SAnderson Briglia 845eb492e01SAnderson Briglia switch (code) { 846eb492e01SAnderson Briglia case SMP_CMD_PAIRING_REQ: 847da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_req(conn, skb); 848eb492e01SAnderson Briglia break; 849eb492e01SAnderson Briglia 850eb492e01SAnderson Briglia case SMP_CMD_PAIRING_FAIL: 8514f957a76SBrian Gix smp_failure(conn, skb->data[0], 0); 852da85e5e5SVinicius Costa Gomes reason = 0; 853da85e5e5SVinicius Costa Gomes err = -EPERM; 854eb492e01SAnderson Briglia break; 855eb492e01SAnderson Briglia 856eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RSP: 857da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_rsp(conn, skb); 85888ba43b6SAnderson Briglia break; 85988ba43b6SAnderson Briglia 86088ba43b6SAnderson Briglia case SMP_CMD_SECURITY_REQ: 861da85e5e5SVinicius Costa Gomes reason = smp_cmd_security_req(conn, skb); 86288ba43b6SAnderson Briglia break; 86388ba43b6SAnderson Briglia 864eb492e01SAnderson Briglia case SMP_CMD_PAIRING_CONFIRM: 865da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_confirm(conn, skb); 86688ba43b6SAnderson Briglia break; 86788ba43b6SAnderson Briglia 868eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RANDOM: 869da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_random(conn, skb); 87088ba43b6SAnderson Briglia break; 87188ba43b6SAnderson Briglia 872eb492e01SAnderson Briglia case SMP_CMD_ENCRYPT_INFO: 8737034b911SVinicius Costa Gomes reason = smp_cmd_encrypt_info(conn, skb); 8747034b911SVinicius Costa Gomes break; 8757034b911SVinicius Costa Gomes 876eb492e01SAnderson Briglia case SMP_CMD_MASTER_IDENT: 8777034b911SVinicius Costa Gomes reason = smp_cmd_master_ident(conn, skb); 8787034b911SVinicius Costa Gomes break; 8797034b911SVinicius Costa Gomes 880eb492e01SAnderson Briglia case SMP_CMD_IDENT_INFO: 881eb492e01SAnderson Briglia case SMP_CMD_IDENT_ADDR_INFO: 882eb492e01SAnderson Briglia case SMP_CMD_SIGN_INFO: 8837034b911SVinicius Costa Gomes /* Just ignored */ 8847034b911SVinicius Costa Gomes reason = 0; 8857034b911SVinicius Costa Gomes break; 8867034b911SVinicius Costa Gomes 887eb492e01SAnderson Briglia default: 888eb492e01SAnderson Briglia BT_DBG("Unknown command code 0x%2.2x", code); 889eb492e01SAnderson Briglia 890eb492e01SAnderson Briglia reason = SMP_CMD_NOTSUPP; 8913a0259bbSVinicius Costa Gomes err = -EOPNOTSUPP; 8923a0259bbSVinicius Costa Gomes goto done; 8933a0259bbSVinicius Costa Gomes } 8943a0259bbSVinicius Costa Gomes 8953a0259bbSVinicius Costa Gomes done: 8963a0259bbSVinicius Costa Gomes if (reason) 8974f957a76SBrian Gix smp_failure(conn, reason, 1); 898eb492e01SAnderson Briglia 899eb492e01SAnderson Briglia kfree_skb(skb); 900eb492e01SAnderson Briglia return err; 901eb492e01SAnderson Briglia } 9027034b911SVinicius Costa Gomes 9037034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) 9047034b911SVinicius Costa Gomes { 9057034b911SVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp; 9061c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 9077034b911SVinicius Costa Gomes __u8 *keydist; 9087034b911SVinicius Costa Gomes 9097034b911SVinicius Costa Gomes BT_DBG("conn %p force %d", conn, force); 9107034b911SVinicius Costa Gomes 911d26a2345SVinicius Costa Gomes if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) 912d26a2345SVinicius Costa Gomes return 0; 913d26a2345SVinicius Costa Gomes 9141c1def09SVinicius Costa Gomes rsp = (void *) &smp->prsp[1]; 9157034b911SVinicius Costa Gomes 9167034b911SVinicius Costa Gomes /* The responder sends its keys first */ 9177034b911SVinicius Costa Gomes if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) 9187034b911SVinicius Costa Gomes return 0; 9197034b911SVinicius Costa Gomes 9201c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 9217034b911SVinicius Costa Gomes 9227034b911SVinicius Costa Gomes if (conn->hcon->out) { 9237034b911SVinicius Costa Gomes keydist = &rsp->init_key_dist; 9247034b911SVinicius Costa Gomes *keydist &= req->init_key_dist; 9257034b911SVinicius Costa Gomes } else { 9267034b911SVinicius Costa Gomes keydist = &rsp->resp_key_dist; 9277034b911SVinicius Costa Gomes *keydist &= req->resp_key_dist; 9287034b911SVinicius Costa Gomes } 9297034b911SVinicius Costa Gomes 9307034b911SVinicius Costa Gomes 9317034b911SVinicius Costa Gomes BT_DBG("keydist 0x%x", *keydist); 9327034b911SVinicius Costa Gomes 9337034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ENC_KEY) { 9347034b911SVinicius Costa Gomes struct smp_cmd_encrypt_info enc; 9357034b911SVinicius Costa Gomes struct smp_cmd_master_ident ident; 9367034b911SVinicius Costa Gomes __le16 ediv; 9377034b911SVinicius Costa Gomes 9387034b911SVinicius Costa Gomes get_random_bytes(enc.ltk, sizeof(enc.ltk)); 9397034b911SVinicius Costa Gomes get_random_bytes(&ediv, sizeof(ediv)); 9407034b911SVinicius Costa Gomes get_random_bytes(ident.rand, sizeof(ident.rand)); 9417034b911SVinicius Costa Gomes 9427034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 9437034b911SVinicius Costa Gomes 9441c1def09SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size, 945726b4ffcSVinicius Costa Gomes ediv, ident.rand, enc.ltk); 94616b90839SVinicius Costa Gomes 9477034b911SVinicius Costa Gomes ident.ediv = cpu_to_le16(ediv); 9487034b911SVinicius Costa Gomes 9497034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); 9507034b911SVinicius Costa Gomes 9517034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ENC_KEY; 9527034b911SVinicius Costa Gomes } 9537034b911SVinicius Costa Gomes 9547034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ID_KEY) { 9557034b911SVinicius Costa Gomes struct smp_cmd_ident_addr_info addrinfo; 9567034b911SVinicius Costa Gomes struct smp_cmd_ident_info idinfo; 9577034b911SVinicius Costa Gomes 9587034b911SVinicius Costa Gomes /* Send a dummy key */ 9597034b911SVinicius Costa Gomes get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); 9607034b911SVinicius Costa Gomes 9617034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 9627034b911SVinicius Costa Gomes 9637034b911SVinicius Costa Gomes /* Just public address */ 9647034b911SVinicius Costa Gomes memset(&addrinfo, 0, sizeof(addrinfo)); 9657034b911SVinicius Costa Gomes bacpy(&addrinfo.bdaddr, conn->src); 9667034b911SVinicius Costa Gomes 9677034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 9687034b911SVinicius Costa Gomes &addrinfo); 9697034b911SVinicius Costa Gomes 9707034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ID_KEY; 9717034b911SVinicius Costa Gomes } 9727034b911SVinicius Costa Gomes 9737034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_SIGN) { 9747034b911SVinicius Costa Gomes struct smp_cmd_sign_info sign; 9757034b911SVinicius Costa Gomes 9767034b911SVinicius Costa Gomes /* Send a dummy key */ 9777034b911SVinicius Costa Gomes get_random_bytes(sign.csrk, sizeof(sign.csrk)); 9787034b911SVinicius Costa Gomes 9797034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 9807034b911SVinicius Costa Gomes 9817034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_SIGN; 9827034b911SVinicius Costa Gomes } 9837034b911SVinicius Costa Gomes 984d26a2345SVinicius Costa Gomes if (conn->hcon->out || force) { 985d26a2345SVinicius Costa Gomes clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); 9866c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 9878aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 988d26a2345SVinicius Costa Gomes } 989d26a2345SVinicius Costa Gomes 9907034b911SVinicius Costa Gomes return 0; 9917034b911SVinicius Costa Gomes } 992