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 3217b02e62SMarcel Holtmann #define SMP_TIMEOUT msecs_to_jiffies(30000) 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); 18917b02e62SMarcel Holtmann schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT); 190eb492e01SAnderson Briglia } 191eb492e01SAnderson Briglia 1922b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq) 1932b64d153SBrian Gix { 1942b64d153SBrian Gix if (authreq & SMP_AUTH_MITM) 1952b64d153SBrian Gix return BT_SECURITY_HIGH; 1962b64d153SBrian Gix else 1972b64d153SBrian Gix return BT_SECURITY_MEDIUM; 1982b64d153SBrian Gix } 1992b64d153SBrian Gix 2002b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level) 2012b64d153SBrian Gix { 2022b64d153SBrian Gix switch (sec_level) { 2032b64d153SBrian Gix case BT_SECURITY_HIGH: 2042b64d153SBrian Gix return SMP_AUTH_MITM | SMP_AUTH_BONDING; 2052b64d153SBrian Gix case BT_SECURITY_MEDIUM: 2062b64d153SBrian Gix return SMP_AUTH_BONDING; 2072b64d153SBrian Gix default: 2082b64d153SBrian Gix return SMP_AUTH_NONE; 2092b64d153SBrian Gix } 2102b64d153SBrian Gix } 2112b64d153SBrian Gix 212b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn, 21354790f73SVinicius Costa Gomes struct smp_cmd_pairing *req, 21454790f73SVinicius Costa Gomes struct smp_cmd_pairing *rsp, 21554790f73SVinicius Costa Gomes __u8 authreq) 216b8e66eacSVinicius Costa Gomes { 2172b64d153SBrian Gix u8 dist_keys = 0; 21854790f73SVinicius Costa Gomes 219a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { 220ca10b5eeSVinicius Costa Gomes dist_keys = SMP_DIST_ENC_KEY; 22154790f73SVinicius Costa Gomes authreq |= SMP_AUTH_BONDING; 2222b64d153SBrian Gix } else { 2232b64d153SBrian Gix authreq &= ~SMP_AUTH_BONDING; 22454790f73SVinicius Costa Gomes } 22554790f73SVinicius Costa Gomes 22654790f73SVinicius Costa Gomes if (rsp == NULL) { 22754790f73SVinicius Costa Gomes req->io_capability = conn->hcon->io_capability; 22854790f73SVinicius Costa Gomes req->oob_flag = SMP_OOB_NOT_PRESENT; 22954790f73SVinicius Costa Gomes req->max_key_size = SMP_MAX_ENC_KEY_SIZE; 2302b64d153SBrian Gix req->init_key_dist = 0; 23154790f73SVinicius Costa Gomes req->resp_key_dist = dist_keys; 23254790f73SVinicius Costa Gomes req->auth_req = authreq; 23354790f73SVinicius Costa Gomes return; 23454790f73SVinicius Costa Gomes } 23554790f73SVinicius Costa Gomes 23654790f73SVinicius Costa Gomes rsp->io_capability = conn->hcon->io_capability; 23754790f73SVinicius Costa Gomes rsp->oob_flag = SMP_OOB_NOT_PRESENT; 23854790f73SVinicius Costa Gomes rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; 2392b64d153SBrian Gix rsp->init_key_dist = 0; 24054790f73SVinicius Costa Gomes rsp->resp_key_dist = req->resp_key_dist & dist_keys; 24154790f73SVinicius Costa Gomes rsp->auth_req = authreq; 242b8e66eacSVinicius Costa Gomes } 243b8e66eacSVinicius Costa Gomes 2443158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) 2453158c50cSVinicius Costa Gomes { 2461c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 2471c1def09SVinicius Costa Gomes 2483158c50cSVinicius Costa Gomes if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || 2493158c50cSVinicius Costa Gomes (max_key_size < SMP_MIN_ENC_KEY_SIZE)) 2503158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 2513158c50cSVinicius Costa Gomes 252f7aa611aSVinicius Costa Gomes smp->enc_key_size = max_key_size; 2533158c50cSVinicius Costa Gomes 2543158c50cSVinicius Costa Gomes return 0; 2553158c50cSVinicius Costa Gomes } 2563158c50cSVinicius Costa Gomes 2574f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) 2584f957a76SBrian Gix { 259bab73cb6SJohan Hedberg struct hci_conn *hcon = conn->hcon; 260bab73cb6SJohan Hedberg 2614f957a76SBrian Gix if (send) 2624f957a76SBrian Gix smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), 2634f957a76SBrian Gix &reason); 2644f957a76SBrian Gix 26551a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); 266bab73cb6SJohan Hedberg mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, 267bab73cb6SJohan Hedberg hcon->dst_type, reason); 268f1c09c07SVinicius Costa Gomes 269f1c09c07SVinicius Costa Gomes if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { 2706c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 2714f957a76SBrian Gix smp_chan_destroy(conn); 2724f957a76SBrian Gix } 273f1c09c07SVinicius Costa Gomes } 2744f957a76SBrian Gix 2752b64d153SBrian Gix #define JUST_WORKS 0x00 2762b64d153SBrian Gix #define JUST_CFM 0x01 2772b64d153SBrian Gix #define REQ_PASSKEY 0x02 2782b64d153SBrian Gix #define CFM_PASSKEY 0x03 2792b64d153SBrian Gix #define REQ_OOB 0x04 2802b64d153SBrian Gix #define OVERLAP 0xFF 2812b64d153SBrian Gix 2822b64d153SBrian Gix static const u8 gen_method[5][5] = { 2832b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2842b64d153SBrian Gix { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 2852b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 2862b64d153SBrian Gix { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, 2872b64d153SBrian Gix { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, 2882b64d153SBrian Gix }; 2892b64d153SBrian Gix 2902b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, 2912b64d153SBrian Gix u8 local_io, u8 remote_io) 2922b64d153SBrian Gix { 2932b64d153SBrian Gix struct hci_conn *hcon = conn->hcon; 2942b64d153SBrian Gix struct smp_chan *smp = conn->smp_chan; 2952b64d153SBrian Gix u8 method; 2962b64d153SBrian Gix u32 passkey = 0; 2972b64d153SBrian Gix int ret = 0; 2982b64d153SBrian Gix 2992b64d153SBrian Gix /* Initialize key for JUST WORKS */ 3002b64d153SBrian Gix memset(smp->tk, 0, sizeof(smp->tk)); 3012b64d153SBrian Gix clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3022b64d153SBrian Gix 3032b64d153SBrian Gix BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); 3042b64d153SBrian Gix 3052b64d153SBrian Gix /* If neither side wants MITM, use JUST WORKS */ 3062b64d153SBrian Gix /* If either side has unknown io_caps, use JUST WORKS */ 3072b64d153SBrian Gix /* Otherwise, look up method from the table */ 3082b64d153SBrian Gix if (!(auth & SMP_AUTH_MITM) || 3092b64d153SBrian Gix local_io > SMP_IO_KEYBOARD_DISPLAY || 3102b64d153SBrian Gix remote_io > SMP_IO_KEYBOARD_DISPLAY) 3112b64d153SBrian Gix method = JUST_WORKS; 3122b64d153SBrian Gix else 313b3ff53ffSIdo Yariv method = gen_method[remote_io][local_io]; 3142b64d153SBrian Gix 3152b64d153SBrian Gix /* If not bonding, don't ask user to confirm a Zero TK */ 3162b64d153SBrian Gix if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) 3172b64d153SBrian Gix method = JUST_WORKS; 3182b64d153SBrian Gix 3192b64d153SBrian Gix /* If Just Works, Continue with Zero TK */ 3202b64d153SBrian Gix if (method == JUST_WORKS) { 3212b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 3222b64d153SBrian Gix return 0; 3232b64d153SBrian Gix } 3242b64d153SBrian Gix 3252b64d153SBrian Gix /* Not Just Works/Confirm results in MITM Authentication */ 3262b64d153SBrian Gix if (method != JUST_CFM) 3272b64d153SBrian Gix set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags); 3282b64d153SBrian Gix 3292b64d153SBrian Gix /* If both devices have Keyoard-Display I/O, the master 3302b64d153SBrian Gix * Confirms and the slave Enters the passkey. 3312b64d153SBrian Gix */ 3322b64d153SBrian Gix if (method == OVERLAP) { 3332b64d153SBrian Gix if (hcon->link_mode & HCI_LM_MASTER) 3342b64d153SBrian Gix method = CFM_PASSKEY; 3352b64d153SBrian Gix else 3362b64d153SBrian Gix method = REQ_PASSKEY; 3372b64d153SBrian Gix } 3382b64d153SBrian Gix 3392b64d153SBrian Gix /* Generate random passkey. Not valid until confirmed. */ 3402b64d153SBrian Gix if (method == CFM_PASSKEY) { 3412b64d153SBrian Gix u8 key[16]; 3422b64d153SBrian Gix 3432b64d153SBrian Gix memset(key, 0, sizeof(key)); 3442b64d153SBrian Gix get_random_bytes(&passkey, sizeof(passkey)); 3452b64d153SBrian Gix passkey %= 1000000; 3462b64d153SBrian Gix put_unaligned_le32(passkey, key); 3472b64d153SBrian Gix swap128(key, smp->tk); 3482b64d153SBrian Gix BT_DBG("PassKey: %d", passkey); 3492b64d153SBrian Gix } 3502b64d153SBrian Gix 3512b64d153SBrian Gix hci_dev_lock(hcon->hdev); 3522b64d153SBrian Gix 3532b64d153SBrian Gix if (method == REQ_PASSKEY) 354272d90dfSJohan Hedberg ret = mgmt_user_passkey_request(hcon->hdev, conn->dst, 355272d90dfSJohan Hedberg hcon->type, hcon->dst_type); 3562b64d153SBrian Gix else 3572b64d153SBrian Gix ret = mgmt_user_confirm_request(hcon->hdev, conn->dst, 358272d90dfSJohan Hedberg hcon->type, hcon->dst_type, 3592b64d153SBrian Gix cpu_to_le32(passkey), 0); 3602b64d153SBrian Gix 3612b64d153SBrian Gix hci_dev_unlock(hcon->hdev); 3622b64d153SBrian Gix 3632b64d153SBrian Gix return ret; 3642b64d153SBrian Gix } 3652b64d153SBrian Gix 3668aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work) 3678aab4757SVinicius Costa Gomes { 3688aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, confirm); 3698aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 3708aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm; 3718aab4757SVinicius Costa Gomes struct smp_cmd_pairing_confirm cp; 3728aab4757SVinicius Costa Gomes int ret; 3738aab4757SVinicius Costa Gomes u8 res[16], reason; 3748aab4757SVinicius Costa Gomes 3758aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 3768aab4757SVinicius Costa Gomes 3778aab4757SVinicius Costa Gomes tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); 3788aab4757SVinicius Costa Gomes if (IS_ERR(tfm)) { 3798aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3808aab4757SVinicius Costa Gomes goto error; 3818aab4757SVinicius Costa Gomes } 3828aab4757SVinicius Costa Gomes 3838aab4757SVinicius Costa Gomes smp->tfm = tfm; 3848aab4757SVinicius Costa Gomes 3858aab4757SVinicius Costa Gomes if (conn->hcon->out) 3868aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, 38704124681SGustavo F. Padovan conn->src, conn->hcon->dst_type, conn->dst, res); 3888aab4757SVinicius Costa Gomes else 3898aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 3908aab4757SVinicius Costa Gomes conn->hcon->dst_type, conn->dst, 0, conn->src, 3918aab4757SVinicius Costa Gomes res); 3928aab4757SVinicius Costa Gomes if (ret) { 3938aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3948aab4757SVinicius Costa Gomes goto error; 3958aab4757SVinicius Costa Gomes } 3968aab4757SVinicius Costa Gomes 3972b64d153SBrian Gix clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 3982b64d153SBrian Gix 3998aab4757SVinicius Costa Gomes swap128(res, cp.confirm_val); 4008aab4757SVinicius Costa Gomes smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 4018aab4757SVinicius Costa Gomes 4028aab4757SVinicius Costa Gomes return; 4038aab4757SVinicius Costa Gomes 4048aab4757SVinicius Costa Gomes error: 4054f957a76SBrian Gix smp_failure(conn, reason, 1); 4068aab4757SVinicius Costa Gomes } 4078aab4757SVinicius Costa Gomes 4088aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work) 4098aab4757SVinicius Costa Gomes { 4108aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, random); 4118aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 4128aab4757SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 4138aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm = smp->tfm; 4148aab4757SVinicius Costa Gomes u8 reason, confirm[16], res[16], key[16]; 4158aab4757SVinicius Costa Gomes int ret; 4168aab4757SVinicius Costa Gomes 4178aab4757SVinicius Costa Gomes if (IS_ERR_OR_NULL(tfm)) { 4188aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4198aab4757SVinicius Costa Gomes goto error; 4208aab4757SVinicius Costa Gomes } 4218aab4757SVinicius Costa Gomes 4228aab4757SVinicius Costa Gomes BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 4238aab4757SVinicius Costa Gomes 4248aab4757SVinicius Costa Gomes if (hcon->out) 4258aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, 42604124681SGustavo F. Padovan conn->src, hcon->dst_type, conn->dst, res); 4278aab4757SVinicius Costa Gomes else 4288aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 42904124681SGustavo F. Padovan hcon->dst_type, conn->dst, 0, conn->src, res); 4308aab4757SVinicius Costa Gomes if (ret) { 4318aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4328aab4757SVinicius Costa Gomes goto error; 4338aab4757SVinicius Costa Gomes } 4348aab4757SVinicius Costa Gomes 4358aab4757SVinicius Costa Gomes swap128(res, confirm); 4368aab4757SVinicius Costa Gomes 4378aab4757SVinicius Costa Gomes if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { 4388aab4757SVinicius Costa Gomes BT_ERR("Pairing failed (confirmation values mismatch)"); 4398aab4757SVinicius Costa Gomes reason = SMP_CONFIRM_FAILED; 4408aab4757SVinicius Costa Gomes goto error; 4418aab4757SVinicius Costa Gomes } 4428aab4757SVinicius Costa Gomes 4438aab4757SVinicius Costa Gomes if (hcon->out) { 4448aab4757SVinicius Costa Gomes u8 stk[16], rand[8]; 4458aab4757SVinicius Costa Gomes __le16 ediv; 4468aab4757SVinicius Costa Gomes 4478aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4488aab4757SVinicius Costa Gomes ediv = 0; 4498aab4757SVinicius Costa Gomes 4508aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); 4518aab4757SVinicius Costa Gomes swap128(key, stk); 4528aab4757SVinicius Costa Gomes 453f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 454f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4558aab4757SVinicius Costa Gomes 45651a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) { 4578aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 4588aab4757SVinicius Costa Gomes goto error; 4598aab4757SVinicius Costa Gomes } 4608aab4757SVinicius Costa Gomes 4618aab4757SVinicius Costa Gomes hci_le_start_enc(hcon, ediv, rand, stk); 462f7aa611aSVinicius Costa Gomes hcon->enc_key_size = smp->enc_key_size; 4638aab4757SVinicius Costa Gomes } else { 4648aab4757SVinicius Costa Gomes u8 stk[16], r[16], rand[8]; 4658aab4757SVinicius Costa Gomes __le16 ediv; 4668aab4757SVinicius Costa Gomes 4678aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 4688aab4757SVinicius Costa Gomes ediv = 0; 4698aab4757SVinicius Costa Gomes 4708aab4757SVinicius Costa Gomes swap128(smp->prnd, r); 4718aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 4728aab4757SVinicius Costa Gomes 4738aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); 4748aab4757SVinicius Costa Gomes swap128(key, stk); 4758aab4757SVinicius Costa Gomes 476f7aa611aSVinicius Costa Gomes memset(stk + smp->enc_key_size, 0, 477f7aa611aSVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); 4788aab4757SVinicius Costa Gomes 479c9839a11SVinicius Costa Gomes hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type, 48004124681SGustavo F. Padovan HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, 48104124681SGustavo F. Padovan ediv, rand); 4828aab4757SVinicius Costa Gomes } 4838aab4757SVinicius Costa Gomes 4848aab4757SVinicius Costa Gomes return; 4858aab4757SVinicius Costa Gomes 4868aab4757SVinicius Costa Gomes error: 4874f957a76SBrian Gix smp_failure(conn, reason, 1); 4888aab4757SVinicius Costa Gomes } 4898aab4757SVinicius Costa Gomes 4908aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 4918aab4757SVinicius Costa Gomes { 4928aab4757SVinicius Costa Gomes struct smp_chan *smp; 4938aab4757SVinicius Costa Gomes 4948aab4757SVinicius Costa Gomes smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); 4958aab4757SVinicius Costa Gomes if (!smp) 4968aab4757SVinicius Costa Gomes return NULL; 4978aab4757SVinicius Costa Gomes 4988aab4757SVinicius Costa Gomes INIT_WORK(&smp->confirm, confirm_work); 4998aab4757SVinicius Costa Gomes INIT_WORK(&smp->random, random_work); 5008aab4757SVinicius Costa Gomes 5018aab4757SVinicius Costa Gomes smp->conn = conn; 5028aab4757SVinicius Costa Gomes conn->smp_chan = smp; 5032b64d153SBrian Gix conn->hcon->smp_conn = conn; 5048aab4757SVinicius Costa Gomes 5058aab4757SVinicius Costa Gomes hci_conn_hold(conn->hcon); 5068aab4757SVinicius Costa Gomes 5078aab4757SVinicius Costa Gomes return smp; 5088aab4757SVinicius Costa Gomes } 5098aab4757SVinicius Costa Gomes 5108aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn) 5118aab4757SVinicius Costa Gomes { 512c8eb9690SBrian Gix struct smp_chan *smp = conn->smp_chan; 513c8eb9690SBrian Gix 514f1c09c07SVinicius Costa Gomes BUG_ON(!smp); 515c8eb9690SBrian Gix 516c8eb9690SBrian Gix if (smp->tfm) 517c8eb9690SBrian Gix crypto_free_blkcipher(smp->tfm); 518c8eb9690SBrian Gix 519c8eb9690SBrian Gix kfree(smp); 520c8eb9690SBrian Gix conn->smp_chan = NULL; 5212b64d153SBrian Gix conn->hcon->smp_conn = NULL; 5228aab4757SVinicius Costa Gomes hci_conn_put(conn->hcon); 5238aab4757SVinicius Costa Gomes } 5248aab4757SVinicius Costa Gomes 5252b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) 5262b64d153SBrian Gix { 5272b64d153SBrian Gix struct l2cap_conn *conn = hcon->smp_conn; 5282b64d153SBrian Gix struct smp_chan *smp; 5292b64d153SBrian Gix u32 value; 5302b64d153SBrian Gix u8 key[16]; 5312b64d153SBrian Gix 5322b64d153SBrian Gix BT_DBG(""); 5332b64d153SBrian Gix 5342b64d153SBrian Gix if (!conn) 5352b64d153SBrian Gix return -ENOTCONN; 5362b64d153SBrian Gix 5372b64d153SBrian Gix smp = conn->smp_chan; 5382b64d153SBrian Gix 5392b64d153SBrian Gix switch (mgmt_op) { 5402b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_REPLY: 5412b64d153SBrian Gix value = le32_to_cpu(passkey); 5422b64d153SBrian Gix memset(key, 0, sizeof(key)); 5432b64d153SBrian Gix BT_DBG("PassKey: %d", value); 5442b64d153SBrian Gix put_unaligned_le32(value, key); 5452b64d153SBrian Gix swap128(key, smp->tk); 5462b64d153SBrian Gix /* Fall Through */ 5472b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_REPLY: 5482b64d153SBrian Gix set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); 5492b64d153SBrian Gix break; 5502b64d153SBrian Gix case MGMT_OP_USER_PASSKEY_NEG_REPLY: 5512b64d153SBrian Gix case MGMT_OP_USER_CONFIRM_NEG_REPLY: 5522b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5532b64d153SBrian Gix return 0; 5542b64d153SBrian Gix default: 5552b64d153SBrian Gix smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); 5562b64d153SBrian Gix return -EOPNOTSUPP; 5572b64d153SBrian Gix } 5582b64d153SBrian Gix 5592b64d153SBrian Gix /* If it is our turn to send Pairing Confirm, do so now */ 5602b64d153SBrian Gix if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags)) 5612b64d153SBrian Gix queue_work(hcon->hdev->workqueue, &smp->confirm); 5622b64d153SBrian Gix 5632b64d153SBrian Gix return 0; 5642b64d153SBrian Gix } 5652b64d153SBrian Gix 566da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 56788ba43b6SAnderson Briglia { 5683158c50cSVinicius Costa Gomes struct smp_cmd_pairing rsp, *req = (void *) skb->data; 5698aab4757SVinicius Costa Gomes struct smp_chan *smp; 5703158c50cSVinicius Costa Gomes u8 key_size; 5712b64d153SBrian Gix u8 auth = SMP_AUTH_NONE; 5728aab4757SVinicius Costa Gomes int ret; 57388ba43b6SAnderson Briglia 57488ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 57588ba43b6SAnderson Briglia 5762b64d153SBrian Gix if (conn->hcon->link_mode & HCI_LM_MASTER) 5772b64d153SBrian Gix return SMP_CMD_NOTSUPP; 5782b64d153SBrian Gix 57951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 5808aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 5818aab4757SVinicius Costa Gomes 5828aab4757SVinicius Costa Gomes smp = conn->smp_chan; 583d26a2345SVinicius Costa Gomes 5841c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5851c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], req, sizeof(*req)); 5863158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*req)); 58788ba43b6SAnderson Briglia 5882b64d153SBrian Gix /* We didn't start the pairing, so match remote */ 5892b64d153SBrian Gix if (req->auth_req & SMP_AUTH_BONDING) 5902b64d153SBrian Gix auth = req->auth_req; 591da85e5e5SVinicius Costa Gomes 5922b64d153SBrian Gix build_pairing_cmd(conn, req, &rsp, auth); 5933158c50cSVinicius Costa Gomes 5943158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp.max_key_size); 5953158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 5963158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 59788ba43b6SAnderson Briglia 5988aab4757SVinicius Costa Gomes ret = smp_rand(smp->prnd); 5998aab4757SVinicius Costa Gomes if (ret) 6008aab4757SVinicius Costa Gomes return SMP_UNSPECIFIED; 6018aab4757SVinicius Costa Gomes 6021c1def09SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6031c1def09SVinicius Costa Gomes memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 604f01ead31SAnderson Briglia 6053158c50cSVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 606da85e5e5SVinicius Costa Gomes 6072b64d153SBrian Gix /* Request setup of TK */ 6082b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); 6092b64d153SBrian Gix if (ret) 6102b64d153SBrian Gix return SMP_UNSPECIFIED; 6112b64d153SBrian Gix 612da85e5e5SVinicius Costa Gomes return 0; 61388ba43b6SAnderson Briglia } 61488ba43b6SAnderson Briglia 615da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 61688ba43b6SAnderson Briglia { 6173158c50cSVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 6181c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6198aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6202b64d153SBrian Gix u8 key_size, auth = SMP_AUTH_NONE; 6217d24ddccSAnderson Briglia int ret; 62288ba43b6SAnderson Briglia 62388ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 62488ba43b6SAnderson Briglia 6252b64d153SBrian Gix if (!(conn->hcon->link_mode & HCI_LM_MASTER)) 6262b64d153SBrian Gix return SMP_CMD_NOTSUPP; 6272b64d153SBrian Gix 6283158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*rsp)); 629da85e5e5SVinicius Costa Gomes 6301c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 6313158c50cSVinicius Costa Gomes 6323158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp->max_key_size); 6333158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 6343158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 6353158c50cSVinicius Costa Gomes 6361c1def09SVinicius Costa Gomes ret = smp_rand(smp->prnd); 6377d24ddccSAnderson Briglia if (ret) 638da85e5e5SVinicius Costa Gomes return SMP_UNSPECIFIED; 6397d24ddccSAnderson Briglia 6408aab4757SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 6418aab4757SVinicius Costa Gomes memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 6427d24ddccSAnderson Briglia 6432b64d153SBrian Gix if ((req->auth_req & SMP_AUTH_BONDING) && 6442b64d153SBrian Gix (rsp->auth_req & SMP_AUTH_BONDING)) 6452b64d153SBrian Gix auth = SMP_AUTH_BONDING; 6462b64d153SBrian Gix 6472b64d153SBrian Gix auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; 6482b64d153SBrian Gix 6492b64d153SBrian Gix ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability); 6502b64d153SBrian Gix if (ret) 6512b64d153SBrian Gix return SMP_UNSPECIFIED; 6522b64d153SBrian Gix 6532b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 6542b64d153SBrian Gix 6552b64d153SBrian Gix /* Can't compose response until we have been confirmed */ 6562b64d153SBrian Gix if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) 6572b64d153SBrian Gix return 0; 6582b64d153SBrian Gix 6598aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 660da85e5e5SVinicius Costa Gomes 661da85e5e5SVinicius Costa Gomes return 0; 66288ba43b6SAnderson Briglia } 66388ba43b6SAnderson Briglia 664da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 66588ba43b6SAnderson Briglia { 6661c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6678aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6687d24ddccSAnderson Briglia 66988ba43b6SAnderson Briglia BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 67088ba43b6SAnderson Briglia 6711c1def09SVinicius Costa Gomes memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 6721c1def09SVinicius Costa Gomes skb_pull(skb, sizeof(smp->pcnf)); 6737d24ddccSAnderson Briglia 67488ba43b6SAnderson Briglia if (conn->hcon->out) { 6757d24ddccSAnderson Briglia u8 random[16]; 67688ba43b6SAnderson Briglia 6771c1def09SVinicius Costa Gomes swap128(smp->prnd, random); 67888ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 6797d24ddccSAnderson Briglia random); 6802b64d153SBrian Gix } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { 6818aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 6822b64d153SBrian Gix } else { 6832b64d153SBrian Gix set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); 68488ba43b6SAnderson Briglia } 685da85e5e5SVinicius Costa Gomes 686da85e5e5SVinicius Costa Gomes return 0; 68788ba43b6SAnderson Briglia } 68888ba43b6SAnderson Briglia 689da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 69088ba43b6SAnderson Briglia { 6911c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6928aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 6937d24ddccSAnderson Briglia 6948aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 6957d24ddccSAnderson Briglia 6968aab4757SVinicius Costa Gomes swap128(skb->data, smp->rrnd); 6978aab4757SVinicius Costa Gomes skb_pull(skb, sizeof(smp->rrnd)); 69888ba43b6SAnderson Briglia 6998aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->random); 700da85e5e5SVinicius Costa Gomes 701da85e5e5SVinicius Costa Gomes return 0; 70288ba43b6SAnderson Briglia } 70388ba43b6SAnderson Briglia 704988c5997SVinicius Costa Gomes static u8 smp_ltk_encrypt(struct l2cap_conn *conn) 705988c5997SVinicius Costa Gomes { 706c9839a11SVinicius Costa Gomes struct smp_ltk *key; 707988c5997SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 708988c5997SVinicius Costa Gomes 709c9839a11SVinicius Costa Gomes key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type); 710988c5997SVinicius Costa Gomes if (!key) 711988c5997SVinicius Costa Gomes return 0; 712988c5997SVinicius Costa Gomes 71351a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) 714988c5997SVinicius Costa Gomes return 1; 715988c5997SVinicius Costa Gomes 716c9839a11SVinicius Costa Gomes hci_le_start_enc(hcon, key->ediv, key->rand, key->val); 717c9839a11SVinicius Costa Gomes hcon->enc_key_size = key->enc_size; 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 73651a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 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 77551a8efd7SJohan Hedberg if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) 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; 820c9839a11SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 821c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 822c9839a11SVinicius Costa Gomes u8 authenticated; 8237034b911SVinicius Costa Gomes 82416b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 82516b90839SVinicius Costa Gomes 826c9839a11SVinicius Costa Gomes hci_dev_lock(hdev); 827c9839a11SVinicius Costa Gomes authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); 828c9839a11SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, 82904124681SGustavo F. Padovan HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, 83004124681SGustavo F. Padovan rp->ediv, rp->rand); 8317034b911SVinicius Costa Gomes smp_distribute_keys(conn, 1); 832c9839a11SVinicius Costa Gomes hci_dev_unlock(hdev); 8337034b911SVinicius Costa Gomes 8347034b911SVinicius Costa Gomes return 0; 8357034b911SVinicius Costa Gomes } 8367034b911SVinicius Costa Gomes 837eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 838eb492e01SAnderson Briglia { 839eb492e01SAnderson Briglia __u8 code = skb->data[0]; 840eb492e01SAnderson Briglia __u8 reason; 841eb492e01SAnderson Briglia int err = 0; 842eb492e01SAnderson Briglia 8432e65c9d2SAndre Guedes if (!lmp_host_le_capable(conn->hcon->hdev)) { 8442e65c9d2SAndre Guedes err = -ENOTSUPP; 8452e65c9d2SAndre Guedes reason = SMP_PAIRING_NOTSUPP; 8462e65c9d2SAndre Guedes goto done; 8472e65c9d2SAndre Guedes } 8482e65c9d2SAndre Guedes 849eb492e01SAnderson Briglia skb_pull(skb, sizeof(code)); 850eb492e01SAnderson Briglia 851eb492e01SAnderson Briglia switch (code) { 852eb492e01SAnderson Briglia case SMP_CMD_PAIRING_REQ: 853da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_req(conn, skb); 854eb492e01SAnderson Briglia break; 855eb492e01SAnderson Briglia 856eb492e01SAnderson Briglia case SMP_CMD_PAIRING_FAIL: 8574f957a76SBrian Gix smp_failure(conn, skb->data[0], 0); 858da85e5e5SVinicius Costa Gomes reason = 0; 859da85e5e5SVinicius Costa Gomes err = -EPERM; 860eb492e01SAnderson Briglia break; 861eb492e01SAnderson Briglia 862eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RSP: 863da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_rsp(conn, skb); 86488ba43b6SAnderson Briglia break; 86588ba43b6SAnderson Briglia 86688ba43b6SAnderson Briglia case SMP_CMD_SECURITY_REQ: 867da85e5e5SVinicius Costa Gomes reason = smp_cmd_security_req(conn, skb); 86888ba43b6SAnderson Briglia break; 86988ba43b6SAnderson Briglia 870eb492e01SAnderson Briglia case SMP_CMD_PAIRING_CONFIRM: 871da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_confirm(conn, skb); 87288ba43b6SAnderson Briglia break; 87388ba43b6SAnderson Briglia 874eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RANDOM: 875da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_random(conn, skb); 87688ba43b6SAnderson Briglia break; 87788ba43b6SAnderson Briglia 878eb492e01SAnderson Briglia case SMP_CMD_ENCRYPT_INFO: 8797034b911SVinicius Costa Gomes reason = smp_cmd_encrypt_info(conn, skb); 8807034b911SVinicius Costa Gomes break; 8817034b911SVinicius Costa Gomes 882eb492e01SAnderson Briglia case SMP_CMD_MASTER_IDENT: 8837034b911SVinicius Costa Gomes reason = smp_cmd_master_ident(conn, skb); 8847034b911SVinicius Costa Gomes break; 8857034b911SVinicius Costa Gomes 886eb492e01SAnderson Briglia case SMP_CMD_IDENT_INFO: 887eb492e01SAnderson Briglia case SMP_CMD_IDENT_ADDR_INFO: 888eb492e01SAnderson Briglia case SMP_CMD_SIGN_INFO: 8897034b911SVinicius Costa Gomes /* Just ignored */ 8907034b911SVinicius Costa Gomes reason = 0; 8917034b911SVinicius Costa Gomes break; 8927034b911SVinicius Costa Gomes 893eb492e01SAnderson Briglia default: 894eb492e01SAnderson Briglia BT_DBG("Unknown command code 0x%2.2x", code); 895eb492e01SAnderson Briglia 896eb492e01SAnderson Briglia reason = SMP_CMD_NOTSUPP; 8973a0259bbSVinicius Costa Gomes err = -EOPNOTSUPP; 8983a0259bbSVinicius Costa Gomes goto done; 8993a0259bbSVinicius Costa Gomes } 9003a0259bbSVinicius Costa Gomes 9013a0259bbSVinicius Costa Gomes done: 9023a0259bbSVinicius Costa Gomes if (reason) 9034f957a76SBrian Gix smp_failure(conn, reason, 1); 904eb492e01SAnderson Briglia 905eb492e01SAnderson Briglia kfree_skb(skb); 906eb492e01SAnderson Briglia return err; 907eb492e01SAnderson Briglia } 9087034b911SVinicius Costa Gomes 9097034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) 9107034b911SVinicius Costa Gomes { 9117034b911SVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp; 9121c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 9137034b911SVinicius Costa Gomes __u8 *keydist; 9147034b911SVinicius Costa Gomes 9157034b911SVinicius Costa Gomes BT_DBG("conn %p force %d", conn, force); 9167034b911SVinicius Costa Gomes 91751a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) 918d26a2345SVinicius Costa Gomes return 0; 919d26a2345SVinicius Costa Gomes 9201c1def09SVinicius Costa Gomes rsp = (void *) &smp->prsp[1]; 9217034b911SVinicius Costa Gomes 9227034b911SVinicius Costa Gomes /* The responder sends its keys first */ 9237034b911SVinicius Costa Gomes if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) 9247034b911SVinicius Costa Gomes return 0; 9257034b911SVinicius Costa Gomes 9261c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 9277034b911SVinicius Costa Gomes 9287034b911SVinicius Costa Gomes if (conn->hcon->out) { 9297034b911SVinicius Costa Gomes keydist = &rsp->init_key_dist; 9307034b911SVinicius Costa Gomes *keydist &= req->init_key_dist; 9317034b911SVinicius Costa Gomes } else { 9327034b911SVinicius Costa Gomes keydist = &rsp->resp_key_dist; 9337034b911SVinicius Costa Gomes *keydist &= req->resp_key_dist; 9347034b911SVinicius Costa Gomes } 9357034b911SVinicius Costa Gomes 9367034b911SVinicius Costa Gomes 9377034b911SVinicius Costa Gomes BT_DBG("keydist 0x%x", *keydist); 9387034b911SVinicius Costa Gomes 9397034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ENC_KEY) { 9407034b911SVinicius Costa Gomes struct smp_cmd_encrypt_info enc; 9417034b911SVinicius Costa Gomes struct smp_cmd_master_ident ident; 942c9839a11SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 943c9839a11SVinicius Costa Gomes u8 authenticated; 9447034b911SVinicius Costa Gomes __le16 ediv; 9457034b911SVinicius Costa Gomes 9467034b911SVinicius Costa Gomes get_random_bytes(enc.ltk, sizeof(enc.ltk)); 9477034b911SVinicius Costa Gomes get_random_bytes(&ediv, sizeof(ediv)); 9487034b911SVinicius Costa Gomes get_random_bytes(ident.rand, sizeof(ident.rand)); 9497034b911SVinicius Costa Gomes 9507034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 9517034b911SVinicius Costa Gomes 952c9839a11SVinicius Costa Gomes authenticated = hcon->sec_level == BT_SECURITY_HIGH; 953c9839a11SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, 954c9839a11SVinicius Costa Gomes HCI_SMP_LTK_SLAVE, 1, authenticated, 95504124681SGustavo F. Padovan enc.ltk, smp->enc_key_size, ediv, ident.rand); 95616b90839SVinicius Costa Gomes 9577034b911SVinicius Costa Gomes ident.ediv = cpu_to_le16(ediv); 9587034b911SVinicius Costa Gomes 9597034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); 9607034b911SVinicius Costa Gomes 9617034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ENC_KEY; 9627034b911SVinicius Costa Gomes } 9637034b911SVinicius Costa Gomes 9647034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ID_KEY) { 9657034b911SVinicius Costa Gomes struct smp_cmd_ident_addr_info addrinfo; 9667034b911SVinicius Costa Gomes struct smp_cmd_ident_info idinfo; 9677034b911SVinicius Costa Gomes 9687034b911SVinicius Costa Gomes /* Send a dummy key */ 9697034b911SVinicius Costa Gomes get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); 9707034b911SVinicius Costa Gomes 9717034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 9727034b911SVinicius Costa Gomes 9737034b911SVinicius Costa Gomes /* Just public address */ 9747034b911SVinicius Costa Gomes memset(&addrinfo, 0, sizeof(addrinfo)); 9757034b911SVinicius Costa Gomes bacpy(&addrinfo.bdaddr, conn->src); 9767034b911SVinicius Costa Gomes 9777034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 9787034b911SVinicius Costa Gomes &addrinfo); 9797034b911SVinicius Costa Gomes 9807034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ID_KEY; 9817034b911SVinicius Costa Gomes } 9827034b911SVinicius Costa Gomes 9837034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_SIGN) { 9847034b911SVinicius Costa Gomes struct smp_cmd_sign_info sign; 9857034b911SVinicius Costa Gomes 9867034b911SVinicius Costa Gomes /* Send a dummy key */ 9877034b911SVinicius Costa Gomes get_random_bytes(sign.csrk, sizeof(sign.csrk)); 9887034b911SVinicius Costa Gomes 9897034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 9907034b911SVinicius Costa Gomes 9917034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_SIGN; 9927034b911SVinicius Costa Gomes } 9937034b911SVinicius Costa Gomes 994d26a2345SVinicius Costa Gomes if (conn->hcon->out || force) { 99551a8efd7SJohan Hedberg clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); 9966c9d42a1SGustavo F. Padovan cancel_delayed_work_sync(&conn->security_timer); 9978aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 998d26a2345SVinicius Costa Gomes } 999d26a2345SVinicius Costa Gomes 10007034b911SVinicius Costa Gomes return 0; 10017034b911SVinicius Costa Gomes } 1002