xref: /openbmc/linux/net/bluetooth/smp.c (revision 76a68ba0)
1eb492e01SAnderson Briglia /*
2eb492e01SAnderson Briglia    BlueZ - Bluetooth protocol stack for Linux
3eb492e01SAnderson Briglia    Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4eb492e01SAnderson Briglia 
5eb492e01SAnderson Briglia    This program is free software; you can redistribute it and/or modify
6eb492e01SAnderson Briglia    it under the terms of the GNU General Public License version 2 as
7eb492e01SAnderson Briglia    published by the Free Software Foundation;
8eb492e01SAnderson Briglia 
9eb492e01SAnderson Briglia    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10eb492e01SAnderson Briglia    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11eb492e01SAnderson Briglia    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12eb492e01SAnderson Briglia    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13eb492e01SAnderson Briglia    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14eb492e01SAnderson Briglia    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15eb492e01SAnderson Briglia    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16eb492e01SAnderson Briglia    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eb492e01SAnderson Briglia 
18eb492e01SAnderson Briglia    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19eb492e01SAnderson Briglia    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20eb492e01SAnderson Briglia    SOFTWARE IS DISCLAIMED.
21eb492e01SAnderson Briglia */
22eb492e01SAnderson Briglia 
238c520a59SGustavo Padovan #include <linux/crypto.h>
248c520a59SGustavo Padovan #include <linux/scatterlist.h>
258c520a59SGustavo Padovan #include <crypto/b128ops.h>
268c520a59SGustavo Padovan 
27eb492e01SAnderson Briglia #include <net/bluetooth/bluetooth.h>
28eb492e01SAnderson Briglia #include <net/bluetooth/hci_core.h>
29eb492e01SAnderson Briglia #include <net/bluetooth/l2cap.h>
302b64d153SBrian Gix #include <net/bluetooth/mgmt.h>
31eb492e01SAnderson Briglia #include <net/bluetooth/smp.h>
32d22ef0bcSAnderson Briglia 
3317b02e62SMarcel Holtmann #define SMP_TIMEOUT	msecs_to_jiffies(30000)
345d3de7dfSVinicius Costa Gomes 
35065a13e2SJohan Hedberg #define AUTH_REQ_MASK   0x07
36065a13e2SJohan Hedberg 
37d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16])
38d22ef0bcSAnderson Briglia {
39d22ef0bcSAnderson Briglia 	int i;
40d22ef0bcSAnderson Briglia 	for (i = 0; i < 16; i++)
41d22ef0bcSAnderson Briglia 		dst[15 - i] = src[i];
42d22ef0bcSAnderson Briglia }
43d22ef0bcSAnderson Briglia 
44d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7])
45d22ef0bcSAnderson Briglia {
46d22ef0bcSAnderson Briglia 	int i;
47d22ef0bcSAnderson Briglia 	for (i = 0; i < 7; i++)
48d22ef0bcSAnderson Briglia 		dst[6 - i] = src[i];
49d22ef0bcSAnderson Briglia }
50d22ef0bcSAnderson Briglia 
51d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
52d22ef0bcSAnderson Briglia {
53d22ef0bcSAnderson Briglia 	struct blkcipher_desc desc;
54d22ef0bcSAnderson Briglia 	struct scatterlist sg;
55d22ef0bcSAnderson Briglia 	int err, iv_len;
56d22ef0bcSAnderson Briglia 	unsigned char iv[128];
57d22ef0bcSAnderson Briglia 
58d22ef0bcSAnderson Briglia 	if (tfm == NULL) {
59d22ef0bcSAnderson Briglia 		BT_ERR("tfm %p", tfm);
60d22ef0bcSAnderson Briglia 		return -EINVAL;
61d22ef0bcSAnderson Briglia 	}
62d22ef0bcSAnderson Briglia 
63d22ef0bcSAnderson Briglia 	desc.tfm = tfm;
64d22ef0bcSAnderson Briglia 	desc.flags = 0;
65d22ef0bcSAnderson Briglia 
66d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_setkey(tfm, k, 16);
67d22ef0bcSAnderson Briglia 	if (err) {
68d22ef0bcSAnderson Briglia 		BT_ERR("cipher setkey failed: %d", err);
69d22ef0bcSAnderson Briglia 		return err;
70d22ef0bcSAnderson Briglia 	}
71d22ef0bcSAnderson Briglia 
72d22ef0bcSAnderson Briglia 	sg_init_one(&sg, r, 16);
73d22ef0bcSAnderson Briglia 
74d22ef0bcSAnderson Briglia 	iv_len = crypto_blkcipher_ivsize(tfm);
75d22ef0bcSAnderson Briglia 	if (iv_len) {
76d22ef0bcSAnderson Briglia 		memset(&iv, 0xff, iv_len);
77d22ef0bcSAnderson Briglia 		crypto_blkcipher_set_iv(tfm, iv, iv_len);
78d22ef0bcSAnderson Briglia 	}
79d22ef0bcSAnderson Briglia 
80d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
81d22ef0bcSAnderson Briglia 	if (err)
82d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error %d", err);
83d22ef0bcSAnderson Briglia 
84d22ef0bcSAnderson Briglia 	return err;
85d22ef0bcSAnderson Briglia }
86d22ef0bcSAnderson Briglia 
87d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
88d22ef0bcSAnderson Briglia 		u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
89d22ef0bcSAnderson Briglia 		u8 _rat, bdaddr_t *ra, u8 res[16])
90d22ef0bcSAnderson Briglia {
91d22ef0bcSAnderson Briglia 	u8 p1[16], p2[16];
92d22ef0bcSAnderson Briglia 	int err;
93d22ef0bcSAnderson Briglia 
94d22ef0bcSAnderson Briglia 	memset(p1, 0, 16);
95d22ef0bcSAnderson Briglia 
96d22ef0bcSAnderson Briglia 	/* p1 = pres || preq || _rat || _iat */
97d22ef0bcSAnderson Briglia 	swap56(pres, p1);
98d22ef0bcSAnderson Briglia 	swap56(preq, p1 + 7);
99d22ef0bcSAnderson Briglia 	p1[14] = _rat;
100d22ef0bcSAnderson Briglia 	p1[15] = _iat;
101d22ef0bcSAnderson Briglia 
102d22ef0bcSAnderson Briglia 	memset(p2, 0, 16);
103d22ef0bcSAnderson Briglia 
104d22ef0bcSAnderson Briglia 	/* p2 = padding || ia || ra */
105d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 4), ia);
106d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 10), ra);
107d22ef0bcSAnderson Briglia 
108d22ef0bcSAnderson Briglia 	/* res = r XOR p1 */
109d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
110d22ef0bcSAnderson Briglia 
111d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
112d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
113d22ef0bcSAnderson Briglia 	if (err) {
114d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
115d22ef0bcSAnderson Briglia 		return err;
116d22ef0bcSAnderson Briglia 	}
117d22ef0bcSAnderson Briglia 
118d22ef0bcSAnderson Briglia 	/* res = res XOR p2 */
119d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
120d22ef0bcSAnderson Briglia 
121d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
122d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
123d22ef0bcSAnderson Briglia 	if (err)
124d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
125d22ef0bcSAnderson Briglia 
126d22ef0bcSAnderson Briglia 	return err;
127d22ef0bcSAnderson Briglia }
128d22ef0bcSAnderson Briglia 
129d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
130d22ef0bcSAnderson Briglia 			u8 r1[16], u8 r2[16], u8 _r[16])
131d22ef0bcSAnderson Briglia {
132d22ef0bcSAnderson Briglia 	int err;
133d22ef0bcSAnderson Briglia 
134d22ef0bcSAnderson Briglia 	/* Just least significant octets from r1 and r2 are considered */
135d22ef0bcSAnderson Briglia 	memcpy(_r, r1 + 8, 8);
136d22ef0bcSAnderson Briglia 	memcpy(_r + 8, r2 + 8, 8);
137d22ef0bcSAnderson Briglia 
138d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, _r);
139d22ef0bcSAnderson Briglia 	if (err)
140d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
141d22ef0bcSAnderson Briglia 
142d22ef0bcSAnderson Briglia 	return err;
143d22ef0bcSAnderson Briglia }
144d22ef0bcSAnderson Briglia 
145d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf)
146d22ef0bcSAnderson Briglia {
147d22ef0bcSAnderson Briglia 	get_random_bytes(buf, 16);
148d22ef0bcSAnderson Briglia 
149d22ef0bcSAnderson Briglia 	return 0;
150d22ef0bcSAnderson Briglia }
151eb492e01SAnderson Briglia 
152eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
153eb492e01SAnderson Briglia 						u16 dlen, void *data)
154eb492e01SAnderson Briglia {
155eb492e01SAnderson Briglia 	struct sk_buff *skb;
156eb492e01SAnderson Briglia 	struct l2cap_hdr *lh;
157eb492e01SAnderson Briglia 	int len;
158eb492e01SAnderson Briglia 
159eb492e01SAnderson Briglia 	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
160eb492e01SAnderson Briglia 
161eb492e01SAnderson Briglia 	if (len > conn->mtu)
162eb492e01SAnderson Briglia 		return NULL;
163eb492e01SAnderson Briglia 
164eb492e01SAnderson Briglia 	skb = bt_skb_alloc(len, GFP_ATOMIC);
165eb492e01SAnderson Briglia 	if (!skb)
166eb492e01SAnderson Briglia 		return NULL;
167eb492e01SAnderson Briglia 
168eb492e01SAnderson Briglia 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
169eb492e01SAnderson Briglia 	lh->len = cpu_to_le16(sizeof(code) + dlen);
170d8aece2aSSyam Sidhardhan 	lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
171eb492e01SAnderson Briglia 
172eb492e01SAnderson Briglia 	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
173eb492e01SAnderson Briglia 
174eb492e01SAnderson Briglia 	memcpy(skb_put(skb, dlen), data, dlen);
175eb492e01SAnderson Briglia 
176eb492e01SAnderson Briglia 	return skb;
177eb492e01SAnderson Briglia }
178eb492e01SAnderson Briglia 
179eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
180eb492e01SAnderson Briglia {
181eb492e01SAnderson Briglia 	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
182eb492e01SAnderson Briglia 
183eb492e01SAnderson Briglia 	BT_DBG("code 0x%2.2x", code);
184eb492e01SAnderson Briglia 
185eb492e01SAnderson Briglia 	if (!skb)
186eb492e01SAnderson Briglia 		return;
187eb492e01SAnderson Briglia 
18873d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
18973d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, 0);
190e2dcd113SVinicius Costa Gomes 
1916c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
19217b02e62SMarcel Holtmann 	schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
193eb492e01SAnderson Briglia }
194eb492e01SAnderson Briglia 
1952b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq)
1962b64d153SBrian Gix {
1972b64d153SBrian Gix 	if (authreq & SMP_AUTH_MITM)
1982b64d153SBrian Gix 		return BT_SECURITY_HIGH;
1992b64d153SBrian Gix 	else
2002b64d153SBrian Gix 		return BT_SECURITY_MEDIUM;
2012b64d153SBrian Gix }
2022b64d153SBrian Gix 
2032b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level)
2042b64d153SBrian Gix {
2052b64d153SBrian Gix 	switch (sec_level) {
2062b64d153SBrian Gix 	case BT_SECURITY_HIGH:
2072b64d153SBrian Gix 		return SMP_AUTH_MITM | SMP_AUTH_BONDING;
2082b64d153SBrian Gix 	case BT_SECURITY_MEDIUM:
2092b64d153SBrian Gix 		return SMP_AUTH_BONDING;
2102b64d153SBrian Gix 	default:
2112b64d153SBrian Gix 		return SMP_AUTH_NONE;
2122b64d153SBrian Gix 	}
2132b64d153SBrian Gix }
2142b64d153SBrian Gix 
215b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn,
21654790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *req,
21754790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *rsp,
21854790f73SVinicius Costa Gomes 				__u8 authreq)
219b8e66eacSVinicius Costa Gomes {
2202b64d153SBrian Gix 	u8 dist_keys = 0;
22154790f73SVinicius Costa Gomes 
222a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
223ca10b5eeSVinicius Costa Gomes 		dist_keys = SMP_DIST_ENC_KEY;
22454790f73SVinicius Costa Gomes 		authreq |= SMP_AUTH_BONDING;
2252b64d153SBrian Gix 	} else {
2262b64d153SBrian Gix 		authreq &= ~SMP_AUTH_BONDING;
22754790f73SVinicius Costa Gomes 	}
22854790f73SVinicius Costa Gomes 
22954790f73SVinicius Costa Gomes 	if (rsp == NULL) {
23054790f73SVinicius Costa Gomes 		req->io_capability = conn->hcon->io_capability;
23154790f73SVinicius Costa Gomes 		req->oob_flag = SMP_OOB_NOT_PRESENT;
23254790f73SVinicius Costa Gomes 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2332b64d153SBrian Gix 		req->init_key_dist = 0;
23454790f73SVinicius Costa Gomes 		req->resp_key_dist = dist_keys;
235065a13e2SJohan Hedberg 		req->auth_req = (authreq & AUTH_REQ_MASK);
23654790f73SVinicius Costa Gomes 		return;
23754790f73SVinicius Costa Gomes 	}
23854790f73SVinicius Costa Gomes 
23954790f73SVinicius Costa Gomes 	rsp->io_capability = conn->hcon->io_capability;
24054790f73SVinicius Costa Gomes 	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
24154790f73SVinicius Costa Gomes 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2422b64d153SBrian Gix 	rsp->init_key_dist = 0;
24354790f73SVinicius Costa Gomes 	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
244065a13e2SJohan Hedberg 	rsp->auth_req = (authreq & AUTH_REQ_MASK);
245b8e66eacSVinicius Costa Gomes }
246b8e66eacSVinicius Costa Gomes 
2473158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
2483158c50cSVinicius Costa Gomes {
2491c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
2501c1def09SVinicius Costa Gomes 
2513158c50cSVinicius Costa Gomes 	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
2523158c50cSVinicius Costa Gomes 			(max_key_size < SMP_MIN_ENC_KEY_SIZE))
2533158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
2543158c50cSVinicius Costa Gomes 
255f7aa611aSVinicius Costa Gomes 	smp->enc_key_size = max_key_size;
2563158c50cSVinicius Costa Gomes 
2573158c50cSVinicius Costa Gomes 	return 0;
2583158c50cSVinicius Costa Gomes }
2593158c50cSVinicius Costa Gomes 
2604f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
2614f957a76SBrian Gix {
262bab73cb6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
263bab73cb6SJohan Hedberg 
2644f957a76SBrian Gix 	if (send)
2654f957a76SBrian Gix 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
2664f957a76SBrian Gix 								&reason);
2674f957a76SBrian Gix 
26851a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
269bab73cb6SJohan Hedberg 	mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
270896ea28eSPaulo Sérgio 			 hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
271f1c09c07SVinicius Costa Gomes 
2726c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
27361a0cfb0SAndre Guedes 
27461a0cfb0SAndre Guedes 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
2754f957a76SBrian Gix 		smp_chan_destroy(conn);
2764f957a76SBrian Gix }
2774f957a76SBrian Gix 
2782b64d153SBrian Gix #define JUST_WORKS	0x00
2792b64d153SBrian Gix #define JUST_CFM	0x01
2802b64d153SBrian Gix #define REQ_PASSKEY	0x02
2812b64d153SBrian Gix #define CFM_PASSKEY	0x03
2822b64d153SBrian Gix #define REQ_OOB		0x04
2832b64d153SBrian Gix #define OVERLAP		0xFF
2842b64d153SBrian Gix 
2852b64d153SBrian Gix static const u8 gen_method[5][5] = {
2862b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
2872b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
2882b64d153SBrian Gix 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
2892b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    JUST_WORKS,  JUST_WORKS, JUST_CFM    },
2902b64d153SBrian Gix 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP     },
2912b64d153SBrian Gix };
2922b64d153SBrian Gix 
2932b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
2942b64d153SBrian Gix 						u8 local_io, u8 remote_io)
2952b64d153SBrian Gix {
2962b64d153SBrian Gix 	struct hci_conn *hcon = conn->hcon;
2972b64d153SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
2982b64d153SBrian Gix 	u8 method;
2992b64d153SBrian Gix 	u32 passkey = 0;
3002b64d153SBrian Gix 	int ret = 0;
3012b64d153SBrian Gix 
3022b64d153SBrian Gix 	/* Initialize key for JUST WORKS */
3032b64d153SBrian Gix 	memset(smp->tk, 0, sizeof(smp->tk));
3042b64d153SBrian Gix 	clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
3052b64d153SBrian Gix 
3062b64d153SBrian Gix 	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
3072b64d153SBrian Gix 
3082b64d153SBrian Gix 	/* If neither side wants MITM, use JUST WORKS */
3092b64d153SBrian Gix 	/* If either side has unknown io_caps, use JUST WORKS */
3102b64d153SBrian Gix 	/* Otherwise, look up method from the table */
3112b64d153SBrian Gix 	if (!(auth & SMP_AUTH_MITM) ||
3122b64d153SBrian Gix 			local_io > SMP_IO_KEYBOARD_DISPLAY ||
3132b64d153SBrian Gix 			remote_io > SMP_IO_KEYBOARD_DISPLAY)
3142b64d153SBrian Gix 		method = JUST_WORKS;
3152b64d153SBrian Gix 	else
316b3ff53ffSIdo Yariv 		method = gen_method[remote_io][local_io];
3172b64d153SBrian Gix 
3182b64d153SBrian Gix 	/* If not bonding, don't ask user to confirm a Zero TK */
3192b64d153SBrian Gix 	if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
3202b64d153SBrian Gix 		method = JUST_WORKS;
3212b64d153SBrian Gix 
3222b64d153SBrian Gix 	/* If Just Works, Continue with Zero TK */
3232b64d153SBrian Gix 	if (method == JUST_WORKS) {
3242b64d153SBrian Gix 		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
3252b64d153SBrian Gix 		return 0;
3262b64d153SBrian Gix 	}
3272b64d153SBrian Gix 
3282b64d153SBrian Gix 	/* Not Just Works/Confirm results in MITM Authentication */
3292b64d153SBrian Gix 	if (method != JUST_CFM)
3302b64d153SBrian Gix 		set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
3312b64d153SBrian Gix 
3322b64d153SBrian Gix 	/* If both devices have Keyoard-Display I/O, the master
3332b64d153SBrian Gix 	 * Confirms and the slave Enters the passkey.
3342b64d153SBrian Gix 	 */
3352b64d153SBrian Gix 	if (method == OVERLAP) {
3362b64d153SBrian Gix 		if (hcon->link_mode & HCI_LM_MASTER)
3372b64d153SBrian Gix 			method = CFM_PASSKEY;
3382b64d153SBrian Gix 		else
3392b64d153SBrian Gix 			method = REQ_PASSKEY;
3402b64d153SBrian Gix 	}
3412b64d153SBrian Gix 
3422b64d153SBrian Gix 	/* Generate random passkey. Not valid until confirmed. */
3432b64d153SBrian Gix 	if (method == CFM_PASSKEY) {
3442b64d153SBrian Gix 		u8 key[16];
3452b64d153SBrian Gix 
3462b64d153SBrian Gix 		memset(key, 0, sizeof(key));
3472b64d153SBrian Gix 		get_random_bytes(&passkey, sizeof(passkey));
3482b64d153SBrian Gix 		passkey %= 1000000;
3492b64d153SBrian Gix 		put_unaligned_le32(passkey, key);
3502b64d153SBrian Gix 		swap128(key, smp->tk);
3512b64d153SBrian Gix 		BT_DBG("PassKey: %d", passkey);
3522b64d153SBrian Gix 	}
3532b64d153SBrian Gix 
3542b64d153SBrian Gix 	hci_dev_lock(hcon->hdev);
3552b64d153SBrian Gix 
3562b64d153SBrian Gix 	if (method == REQ_PASSKEY)
357272d90dfSJohan Hedberg 		ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
358272d90dfSJohan Hedberg 						hcon->type, hcon->dst_type);
3592b64d153SBrian Gix 	else
3602b64d153SBrian Gix 		ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
361272d90dfSJohan Hedberg 						hcon->type, hcon->dst_type,
3622b64d153SBrian Gix 						cpu_to_le32(passkey), 0);
3632b64d153SBrian Gix 
3642b64d153SBrian Gix 	hci_dev_unlock(hcon->hdev);
3652b64d153SBrian Gix 
3662b64d153SBrian Gix 	return ret;
3672b64d153SBrian Gix }
3682b64d153SBrian Gix 
3698aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work)
3708aab4757SVinicius Costa Gomes {
3718aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
3728aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
3738aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm;
3748aab4757SVinicius Costa Gomes 	struct smp_cmd_pairing_confirm cp;
3758aab4757SVinicius Costa Gomes 	int ret;
3768aab4757SVinicius Costa Gomes 	u8 res[16], reason;
3778aab4757SVinicius Costa Gomes 
3788aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
3798aab4757SVinicius Costa Gomes 
3808aab4757SVinicius Costa Gomes 	tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
3818aab4757SVinicius Costa Gomes 	if (IS_ERR(tfm)) {
3828aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3838aab4757SVinicius Costa Gomes 		goto error;
3848aab4757SVinicius Costa Gomes 	}
3858aab4757SVinicius Costa Gomes 
3868aab4757SVinicius Costa Gomes 	smp->tfm = tfm;
3878aab4757SVinicius Costa Gomes 
3888aab4757SVinicius Costa Gomes 	if (conn->hcon->out)
3898aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
39004124681SGustavo F. Padovan 			     conn->src, conn->hcon->dst_type, conn->dst, res);
3918aab4757SVinicius Costa Gomes 	else
3928aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
3938aab4757SVinicius Costa Gomes 			     conn->hcon->dst_type, conn->dst, 0, conn->src,
3948aab4757SVinicius Costa Gomes 			     res);
3958aab4757SVinicius Costa Gomes 	if (ret) {
3968aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3978aab4757SVinicius Costa Gomes 		goto error;
3988aab4757SVinicius Costa Gomes 	}
3998aab4757SVinicius Costa Gomes 
4002b64d153SBrian Gix 	clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
4012b64d153SBrian Gix 
4028aab4757SVinicius Costa Gomes 	swap128(res, cp.confirm_val);
4038aab4757SVinicius Costa Gomes 	smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
4048aab4757SVinicius Costa Gomes 
4058aab4757SVinicius Costa Gomes 	return;
4068aab4757SVinicius Costa Gomes 
4078aab4757SVinicius Costa Gomes error:
4084f957a76SBrian Gix 	smp_failure(conn, reason, 1);
4098aab4757SVinicius Costa Gomes }
4108aab4757SVinicius Costa Gomes 
4118aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work)
4128aab4757SVinicius Costa Gomes {
4138aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, random);
4148aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
4158aab4757SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
4168aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm = smp->tfm;
4178aab4757SVinicius Costa Gomes 	u8 reason, confirm[16], res[16], key[16];
4188aab4757SVinicius Costa Gomes 	int ret;
4198aab4757SVinicius Costa Gomes 
4208aab4757SVinicius Costa Gomes 	if (IS_ERR_OR_NULL(tfm)) {
4218aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
4228aab4757SVinicius Costa Gomes 		goto error;
4238aab4757SVinicius Costa Gomes 	}
4248aab4757SVinicius Costa Gomes 
4258aab4757SVinicius Costa Gomes 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
4268aab4757SVinicius Costa Gomes 
4278aab4757SVinicius Costa Gomes 	if (hcon->out)
4288aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
42904124681SGustavo F. Padovan 			     conn->src, hcon->dst_type, conn->dst, res);
4308aab4757SVinicius Costa Gomes 	else
4318aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
43204124681SGustavo F. Padovan 			     hcon->dst_type, conn->dst, 0, conn->src, res);
4338aab4757SVinicius Costa Gomes 	if (ret) {
4348aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
4358aab4757SVinicius Costa Gomes 		goto error;
4368aab4757SVinicius Costa Gomes 	}
4378aab4757SVinicius Costa Gomes 
4388aab4757SVinicius Costa Gomes 	swap128(res, confirm);
4398aab4757SVinicius Costa Gomes 
4408aab4757SVinicius Costa Gomes 	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
4418aab4757SVinicius Costa Gomes 		BT_ERR("Pairing failed (confirmation values mismatch)");
4428aab4757SVinicius Costa Gomes 		reason = SMP_CONFIRM_FAILED;
4438aab4757SVinicius Costa Gomes 		goto error;
4448aab4757SVinicius Costa Gomes 	}
4458aab4757SVinicius Costa Gomes 
4468aab4757SVinicius Costa Gomes 	if (hcon->out) {
4478aab4757SVinicius Costa Gomes 		u8 stk[16], rand[8];
4488aab4757SVinicius Costa Gomes 		__le16 ediv;
4498aab4757SVinicius Costa Gomes 
4508aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
4518aab4757SVinicius Costa Gomes 		ediv = 0;
4528aab4757SVinicius Costa Gomes 
4538aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
4548aab4757SVinicius Costa Gomes 		swap128(key, stk);
4558aab4757SVinicius Costa Gomes 
456f7aa611aSVinicius Costa Gomes 		memset(stk + smp->enc_key_size, 0,
457f7aa611aSVinicius Costa Gomes 		       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
4588aab4757SVinicius Costa Gomes 
45951a8efd7SJohan Hedberg 		if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
4608aab4757SVinicius Costa Gomes 			reason = SMP_UNSPECIFIED;
4618aab4757SVinicius Costa Gomes 			goto error;
4628aab4757SVinicius Costa Gomes 		}
4638aab4757SVinicius Costa Gomes 
4648aab4757SVinicius Costa Gomes 		hci_le_start_enc(hcon, ediv, rand, stk);
465f7aa611aSVinicius Costa Gomes 		hcon->enc_key_size = smp->enc_key_size;
4668aab4757SVinicius Costa Gomes 	} else {
4678aab4757SVinicius Costa Gomes 		u8 stk[16], r[16], rand[8];
4688aab4757SVinicius Costa Gomes 		__le16 ediv;
4698aab4757SVinicius Costa Gomes 
4708aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
4718aab4757SVinicius Costa Gomes 		ediv = 0;
4728aab4757SVinicius Costa Gomes 
4738aab4757SVinicius Costa Gomes 		swap128(smp->prnd, r);
4748aab4757SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
4758aab4757SVinicius Costa Gomes 
4768aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
4778aab4757SVinicius Costa Gomes 		swap128(key, stk);
4788aab4757SVinicius Costa Gomes 
479f7aa611aSVinicius Costa Gomes 		memset(stk + smp->enc_key_size, 0,
480f7aa611aSVinicius Costa Gomes 				SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
4818aab4757SVinicius Costa Gomes 
482c9839a11SVinicius Costa Gomes 		hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
48304124681SGustavo F. Padovan 			    HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
48404124681SGustavo F. Padovan 			    ediv, rand);
4858aab4757SVinicius Costa Gomes 	}
4868aab4757SVinicius Costa Gomes 
4878aab4757SVinicius Costa Gomes 	return;
4888aab4757SVinicius Costa Gomes 
4898aab4757SVinicius Costa Gomes error:
4904f957a76SBrian Gix 	smp_failure(conn, reason, 1);
4918aab4757SVinicius Costa Gomes }
4928aab4757SVinicius Costa Gomes 
4938aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
4948aab4757SVinicius Costa Gomes {
4958aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
4968aab4757SVinicius Costa Gomes 
4978aab4757SVinicius Costa Gomes 	smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
4988aab4757SVinicius Costa Gomes 	if (!smp)
4998aab4757SVinicius Costa Gomes 		return NULL;
5008aab4757SVinicius Costa Gomes 
5018aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->confirm, confirm_work);
5028aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->random, random_work);
5038aab4757SVinicius Costa Gomes 
5048aab4757SVinicius Costa Gomes 	smp->conn = conn;
5058aab4757SVinicius Costa Gomes 	conn->smp_chan = smp;
5062b64d153SBrian Gix 	conn->hcon->smp_conn = conn;
5078aab4757SVinicius Costa Gomes 
5088aab4757SVinicius Costa Gomes 	hci_conn_hold(conn->hcon);
5098aab4757SVinicius Costa Gomes 
5108aab4757SVinicius Costa Gomes 	return smp;
5118aab4757SVinicius Costa Gomes }
5128aab4757SVinicius Costa Gomes 
5138aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn)
5148aab4757SVinicius Costa Gomes {
515c8eb9690SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
516c8eb9690SBrian Gix 
517f1c09c07SVinicius Costa Gomes 	BUG_ON(!smp);
518c8eb9690SBrian Gix 
519c8eb9690SBrian Gix 	if (smp->tfm)
520c8eb9690SBrian Gix 		crypto_free_blkcipher(smp->tfm);
521c8eb9690SBrian Gix 
522c8eb9690SBrian Gix 	kfree(smp);
523c8eb9690SBrian Gix 	conn->smp_chan = NULL;
5242b64d153SBrian Gix 	conn->hcon->smp_conn = NULL;
52576a68ba0SDavid Herrmann 	hci_conn_drop(conn->hcon);
5268aab4757SVinicius Costa Gomes }
5278aab4757SVinicius Costa Gomes 
5282b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
5292b64d153SBrian Gix {
5302b64d153SBrian Gix 	struct l2cap_conn *conn = hcon->smp_conn;
5312b64d153SBrian Gix 	struct smp_chan *smp;
5322b64d153SBrian Gix 	u32 value;
5332b64d153SBrian Gix 	u8 key[16];
5342b64d153SBrian Gix 
5352b64d153SBrian Gix 	BT_DBG("");
5362b64d153SBrian Gix 
5372b64d153SBrian Gix 	if (!conn)
5382b64d153SBrian Gix 		return -ENOTCONN;
5392b64d153SBrian Gix 
5402b64d153SBrian Gix 	smp = conn->smp_chan;
5412b64d153SBrian Gix 
5422b64d153SBrian Gix 	switch (mgmt_op) {
5432b64d153SBrian Gix 	case MGMT_OP_USER_PASSKEY_REPLY:
5442b64d153SBrian Gix 		value = le32_to_cpu(passkey);
5452b64d153SBrian Gix 		memset(key, 0, sizeof(key));
5462b64d153SBrian Gix 		BT_DBG("PassKey: %d", value);
5472b64d153SBrian Gix 		put_unaligned_le32(value, key);
5482b64d153SBrian Gix 		swap128(key, smp->tk);
5492b64d153SBrian Gix 		/* Fall Through */
5502b64d153SBrian Gix 	case MGMT_OP_USER_CONFIRM_REPLY:
5512b64d153SBrian Gix 		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
5522b64d153SBrian Gix 		break;
5532b64d153SBrian Gix 	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
5542b64d153SBrian Gix 	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
5552b64d153SBrian Gix 		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
5562b64d153SBrian Gix 		return 0;
5572b64d153SBrian Gix 	default:
5582b64d153SBrian Gix 		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
5592b64d153SBrian Gix 		return -EOPNOTSUPP;
5602b64d153SBrian Gix 	}
5612b64d153SBrian Gix 
5622b64d153SBrian Gix 	/* If it is our turn to send Pairing Confirm, do so now */
5632b64d153SBrian Gix 	if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
5642b64d153SBrian Gix 		queue_work(hcon->hdev->workqueue, &smp->confirm);
5652b64d153SBrian Gix 
5662b64d153SBrian Gix 	return 0;
5672b64d153SBrian Gix }
5682b64d153SBrian Gix 
569da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
57088ba43b6SAnderson Briglia {
5713158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
5728aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
5733158c50cSVinicius Costa Gomes 	u8 key_size;
5742b64d153SBrian Gix 	u8 auth = SMP_AUTH_NONE;
5758aab4757SVinicius Costa Gomes 	int ret;
57688ba43b6SAnderson Briglia 
57788ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
57888ba43b6SAnderson Briglia 
5792b64d153SBrian Gix 	if (conn->hcon->link_mode & HCI_LM_MASTER)
5802b64d153SBrian Gix 		return SMP_CMD_NOTSUPP;
5812b64d153SBrian Gix 
58251a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
5838aab4757SVinicius Costa Gomes 		smp = smp_chan_create(conn);
584d08fd0e7SAndrei Emeltchenko 	else
5858aab4757SVinicius Costa Gomes 		smp = conn->smp_chan;
586d26a2345SVinicius Costa Gomes 
587d08fd0e7SAndrei Emeltchenko 	if (!smp)
588d08fd0e7SAndrei Emeltchenko 		return SMP_UNSPECIFIED;
589d08fd0e7SAndrei Emeltchenko 
5901c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
5911c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], req, sizeof(*req));
5923158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*req));
59388ba43b6SAnderson Briglia 
5942b64d153SBrian Gix 	/* We didn't start the pairing, so match remote */
5952b64d153SBrian Gix 	if (req->auth_req & SMP_AUTH_BONDING)
5962b64d153SBrian Gix 		auth = req->auth_req;
597da85e5e5SVinicius Costa Gomes 
598fdde0a26SIdo Yariv 	conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
599fdde0a26SIdo Yariv 
6002b64d153SBrian Gix 	build_pairing_cmd(conn, req, &rsp, auth);
6013158c50cSVinicius Costa Gomes 
6023158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp.max_key_size);
6033158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
6043158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
60588ba43b6SAnderson Briglia 
6068aab4757SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
6078aab4757SVinicius Costa Gomes 	if (ret)
6088aab4757SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
6098aab4757SVinicius Costa Gomes 
6101c1def09SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
6111c1def09SVinicius Costa Gomes 	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
612f01ead31SAnderson Briglia 
6133158c50cSVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
614da85e5e5SVinicius Costa Gomes 
6152b64d153SBrian Gix 	/* Request setup of TK */
6162b64d153SBrian Gix 	ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
6172b64d153SBrian Gix 	if (ret)
6182b64d153SBrian Gix 		return SMP_UNSPECIFIED;
6192b64d153SBrian Gix 
620da85e5e5SVinicius Costa Gomes 	return 0;
62188ba43b6SAnderson Briglia }
62288ba43b6SAnderson Briglia 
623da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
62488ba43b6SAnderson Briglia {
6253158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
6261c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6278aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6282b64d153SBrian Gix 	u8 key_size, auth = SMP_AUTH_NONE;
6297d24ddccSAnderson Briglia 	int ret;
63088ba43b6SAnderson Briglia 
63188ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
63288ba43b6SAnderson Briglia 
6332b64d153SBrian Gix 	if (!(conn->hcon->link_mode & HCI_LM_MASTER))
6342b64d153SBrian Gix 		return SMP_CMD_NOTSUPP;
6352b64d153SBrian Gix 
6363158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*rsp));
637da85e5e5SVinicius Costa Gomes 
6381c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
6393158c50cSVinicius Costa Gomes 
6403158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp->max_key_size);
6413158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
6423158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
6433158c50cSVinicius Costa Gomes 
6441c1def09SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
6457d24ddccSAnderson Briglia 	if (ret)
646da85e5e5SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
6477d24ddccSAnderson Briglia 
6488aab4757SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
6498aab4757SVinicius Costa Gomes 	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
6507d24ddccSAnderson Briglia 
6512b64d153SBrian Gix 	if ((req->auth_req & SMP_AUTH_BONDING) &&
6522b64d153SBrian Gix 			(rsp->auth_req & SMP_AUTH_BONDING))
6532b64d153SBrian Gix 		auth = SMP_AUTH_BONDING;
6542b64d153SBrian Gix 
6552b64d153SBrian Gix 	auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
6562b64d153SBrian Gix 
657476585ecSJohan Hedberg 	ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
6582b64d153SBrian Gix 	if (ret)
6592b64d153SBrian Gix 		return SMP_UNSPECIFIED;
6602b64d153SBrian Gix 
6612b64d153SBrian Gix 	set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
6622b64d153SBrian Gix 
6632b64d153SBrian Gix 	/* Can't compose response until we have been confirmed */
6642b64d153SBrian Gix 	if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
6652b64d153SBrian Gix 		return 0;
6662b64d153SBrian Gix 
6678aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->confirm);
668da85e5e5SVinicius Costa Gomes 
669da85e5e5SVinicius Costa Gomes 	return 0;
67088ba43b6SAnderson Briglia }
67188ba43b6SAnderson Briglia 
672da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
67388ba43b6SAnderson Briglia {
6741c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6758aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6767d24ddccSAnderson Briglia 
67788ba43b6SAnderson Briglia 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
67888ba43b6SAnderson Briglia 
6791c1def09SVinicius Costa Gomes 	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
6801c1def09SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->pcnf));
6817d24ddccSAnderson Briglia 
68288ba43b6SAnderson Briglia 	if (conn->hcon->out) {
6837d24ddccSAnderson Briglia 		u8 random[16];
68488ba43b6SAnderson Briglia 
6851c1def09SVinicius Costa Gomes 		swap128(smp->prnd, random);
68688ba43b6SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
6877d24ddccSAnderson Briglia 								random);
6882b64d153SBrian Gix 	} else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
6898aab4757SVinicius Costa Gomes 		queue_work(hdev->workqueue, &smp->confirm);
6902b64d153SBrian Gix 	} else {
6912b64d153SBrian Gix 		set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
69288ba43b6SAnderson Briglia 	}
693da85e5e5SVinicius Costa Gomes 
694da85e5e5SVinicius Costa Gomes 	return 0;
69588ba43b6SAnderson Briglia }
69688ba43b6SAnderson Briglia 
697da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
69888ba43b6SAnderson Briglia {
6991c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7008aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
7017d24ddccSAnderson Briglia 
7028aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
7037d24ddccSAnderson Briglia 
7048aab4757SVinicius Costa Gomes 	swap128(skb->data, smp->rrnd);
7058aab4757SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->rrnd));
70688ba43b6SAnderson Briglia 
7078aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->random);
708da85e5e5SVinicius Costa Gomes 
709da85e5e5SVinicius Costa Gomes 	return 0;
71088ba43b6SAnderson Briglia }
71188ba43b6SAnderson Briglia 
7124dab7864SJohan Hedberg static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
713988c5997SVinicius Costa Gomes {
714c9839a11SVinicius Costa Gomes 	struct smp_ltk *key;
715988c5997SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
716988c5997SVinicius Costa Gomes 
717c9839a11SVinicius Costa Gomes 	key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
718988c5997SVinicius Costa Gomes 	if (!key)
719988c5997SVinicius Costa Gomes 		return 0;
720988c5997SVinicius Costa Gomes 
7214dab7864SJohan Hedberg 	if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
7224dab7864SJohan Hedberg 		return 0;
7234dab7864SJohan Hedberg 
72451a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
725988c5997SVinicius Costa Gomes 		return 1;
726988c5997SVinicius Costa Gomes 
727c9839a11SVinicius Costa Gomes 	hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
728c9839a11SVinicius Costa Gomes 	hcon->enc_key_size = key->enc_size;
729988c5997SVinicius Costa Gomes 
730988c5997SVinicius Costa Gomes 	return 1;
731988c5997SVinicius Costa Gomes 
732988c5997SVinicius Costa Gomes }
733da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
73488ba43b6SAnderson Briglia {
73588ba43b6SAnderson Briglia 	struct smp_cmd_security_req *rp = (void *) skb->data;
73688ba43b6SAnderson Briglia 	struct smp_cmd_pairing cp;
737f1cb9af5SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
7388aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
73988ba43b6SAnderson Briglia 
74088ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
74188ba43b6SAnderson Briglia 
7422b64d153SBrian Gix 	hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
743feb45eb5SVinicius Costa Gomes 
7444dab7864SJohan Hedberg 	if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
745988c5997SVinicius Costa Gomes 		return 0;
746988c5997SVinicius Costa Gomes 
74751a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
748da85e5e5SVinicius Costa Gomes 		return 0;
749f1cb9af5SVinicius Costa Gomes 
7508aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
751d26a2345SVinicius Costa Gomes 
75288ba43b6SAnderson Briglia 	skb_pull(skb, sizeof(*rp));
75388ba43b6SAnderson Briglia 
754da85e5e5SVinicius Costa Gomes 	memset(&cp, 0, sizeof(cp));
75554790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
75688ba43b6SAnderson Briglia 
7571c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
7581c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], &cp, sizeof(cp));
759f01ead31SAnderson Briglia 
76088ba43b6SAnderson Briglia 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
761f1cb9af5SVinicius Costa Gomes 
762da85e5e5SVinicius Costa Gomes 	return 0;
76388ba43b6SAnderson Briglia }
76488ba43b6SAnderson Briglia 
765cc110922SVinicius Costa Gomes int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
766eb492e01SAnderson Briglia {
767cc110922SVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
7681c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7692b64d153SBrian Gix 	__u8 authreq;
770eb492e01SAnderson Briglia 
7713a0259bbSVinicius Costa Gomes 	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
7723a0259bbSVinicius Costa Gomes 
7732e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(hcon->hdev))
7742e65c9d2SAndre Guedes 		return 1;
7752e65c9d2SAndre Guedes 
776f1cb9af5SVinicius Costa Gomes 	if (sec_level == BT_SECURITY_LOW)
777eb492e01SAnderson Briglia 		return 1;
778f1cb9af5SVinicius Costa Gomes 
779f1cb9af5SVinicius Costa Gomes 	if (hcon->sec_level >= sec_level)
780f1cb9af5SVinicius Costa Gomes 		return 1;
781f1cb9af5SVinicius Costa Gomes 
782988c5997SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER)
7834dab7864SJohan Hedberg 		if (smp_ltk_encrypt(conn, sec_level))
784d26a2345SVinicius Costa Gomes 			goto done;
785d26a2345SVinicius Costa Gomes 
78651a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
787d26a2345SVinicius Costa Gomes 		return 0;
788d26a2345SVinicius Costa Gomes 
7898aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
7902b64d153SBrian Gix 	if (!smp)
7912b64d153SBrian Gix 		return 1;
7922b64d153SBrian Gix 
7932b64d153SBrian Gix 	authreq = seclevel_to_authreq(sec_level);
794d26a2345SVinicius Costa Gomes 
795d26a2345SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER) {
796d26a2345SVinicius Costa Gomes 		struct smp_cmd_pairing cp;
797f01ead31SAnderson Briglia 
7982b64d153SBrian Gix 		build_pairing_cmd(conn, &cp, NULL, authreq);
7991c1def09SVinicius Costa Gomes 		smp->preq[0] = SMP_CMD_PAIRING_REQ;
8001c1def09SVinicius Costa Gomes 		memcpy(&smp->preq[1], &cp, sizeof(cp));
801f01ead31SAnderson Briglia 
802eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
803eb492e01SAnderson Briglia 	} else {
804eb492e01SAnderson Briglia 		struct smp_cmd_security_req cp;
8052b64d153SBrian Gix 		cp.auth_req = authreq;
806eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
807eb492e01SAnderson Briglia 	}
808eb492e01SAnderson Briglia 
80902bc7455SVinicius Costa Gomes done:
810f1cb9af5SVinicius Costa Gomes 	hcon->pending_sec_level = sec_level;
811f1cb9af5SVinicius Costa Gomes 
812eb492e01SAnderson Briglia 	return 0;
813eb492e01SAnderson Briglia }
814eb492e01SAnderson Briglia 
8157034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
8167034b911SVinicius Costa Gomes {
81716b90839SVinicius Costa Gomes 	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
8181c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
81916b90839SVinicius Costa Gomes 
82016b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
82116b90839SVinicius Costa Gomes 
8221c1def09SVinicius Costa Gomes 	memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
82316b90839SVinicius Costa Gomes 
8247034b911SVinicius Costa Gomes 	return 0;
8257034b911SVinicius Costa Gomes }
8267034b911SVinicius Costa Gomes 
8277034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
8287034b911SVinicius Costa Gomes {
82916b90839SVinicius Costa Gomes 	struct smp_cmd_master_ident *rp = (void *) skb->data;
8301c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
831c9839a11SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
832c9839a11SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
833c9839a11SVinicius Costa Gomes 	u8 authenticated;
8347034b911SVinicius Costa Gomes 
83516b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
83616b90839SVinicius Costa Gomes 
837c9839a11SVinicius Costa Gomes 	hci_dev_lock(hdev);
838c9839a11SVinicius Costa Gomes 	authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
839c9839a11SVinicius Costa Gomes 	hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
84004124681SGustavo F. Padovan 		    HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
84104124681SGustavo F. Padovan 		    rp->ediv, rp->rand);
8427034b911SVinicius Costa Gomes 	smp_distribute_keys(conn, 1);
843c9839a11SVinicius Costa Gomes 	hci_dev_unlock(hdev);
8447034b911SVinicius Costa Gomes 
8457034b911SVinicius Costa Gomes 	return 0;
8467034b911SVinicius Costa Gomes }
8477034b911SVinicius Costa Gomes 
848eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
849eb492e01SAnderson Briglia {
850eb492e01SAnderson Briglia 	__u8 code = skb->data[0];
851eb492e01SAnderson Briglia 	__u8 reason;
852eb492e01SAnderson Briglia 	int err = 0;
853eb492e01SAnderson Briglia 
8542e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(conn->hcon->hdev)) {
8552e65c9d2SAndre Guedes 		err = -ENOTSUPP;
8562e65c9d2SAndre Guedes 		reason = SMP_PAIRING_NOTSUPP;
8572e65c9d2SAndre Guedes 		goto done;
8582e65c9d2SAndre Guedes 	}
8592e65c9d2SAndre Guedes 
860eb492e01SAnderson Briglia 	skb_pull(skb, sizeof(code));
861eb492e01SAnderson Briglia 
8628cf9fa12SJohan Hedberg 	/*
8638cf9fa12SJohan Hedberg 	 * The SMP context must be initialized for all other PDUs except
8648cf9fa12SJohan Hedberg 	 * pairing and security requests. If we get any other PDU when
8658cf9fa12SJohan Hedberg 	 * not initialized simply disconnect (done if this function
8668cf9fa12SJohan Hedberg 	 * returns an error).
8678cf9fa12SJohan Hedberg 	 */
8688cf9fa12SJohan Hedberg 	if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
8698cf9fa12SJohan Hedberg 	    !conn->smp_chan) {
8708cf9fa12SJohan Hedberg 		BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
8718cf9fa12SJohan Hedberg 		kfree_skb(skb);
8728cf9fa12SJohan Hedberg 		return -ENOTSUPP;
8738cf9fa12SJohan Hedberg 	}
8748cf9fa12SJohan Hedberg 
875eb492e01SAnderson Briglia 	switch (code) {
876eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_REQ:
877da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_req(conn, skb);
878eb492e01SAnderson Briglia 		break;
879eb492e01SAnderson Briglia 
880eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_FAIL:
8814f957a76SBrian Gix 		smp_failure(conn, skb->data[0], 0);
882da85e5e5SVinicius Costa Gomes 		reason = 0;
883da85e5e5SVinicius Costa Gomes 		err = -EPERM;
884eb492e01SAnderson Briglia 		break;
885eb492e01SAnderson Briglia 
886eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RSP:
887da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_rsp(conn, skb);
88888ba43b6SAnderson Briglia 		break;
88988ba43b6SAnderson Briglia 
89088ba43b6SAnderson Briglia 	case SMP_CMD_SECURITY_REQ:
891da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_security_req(conn, skb);
89288ba43b6SAnderson Briglia 		break;
89388ba43b6SAnderson Briglia 
894eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_CONFIRM:
895da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_confirm(conn, skb);
89688ba43b6SAnderson Briglia 		break;
89788ba43b6SAnderson Briglia 
898eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RANDOM:
899da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_random(conn, skb);
90088ba43b6SAnderson Briglia 		break;
90188ba43b6SAnderson Briglia 
902eb492e01SAnderson Briglia 	case SMP_CMD_ENCRYPT_INFO:
9037034b911SVinicius Costa Gomes 		reason = smp_cmd_encrypt_info(conn, skb);
9047034b911SVinicius Costa Gomes 		break;
9057034b911SVinicius Costa Gomes 
906eb492e01SAnderson Briglia 	case SMP_CMD_MASTER_IDENT:
9077034b911SVinicius Costa Gomes 		reason = smp_cmd_master_ident(conn, skb);
9087034b911SVinicius Costa Gomes 		break;
9097034b911SVinicius Costa Gomes 
910eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_INFO:
911eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_ADDR_INFO:
912eb492e01SAnderson Briglia 	case SMP_CMD_SIGN_INFO:
9137034b911SVinicius Costa Gomes 		/* Just ignored */
9147034b911SVinicius Costa Gomes 		reason = 0;
9157034b911SVinicius Costa Gomes 		break;
9167034b911SVinicius Costa Gomes 
917eb492e01SAnderson Briglia 	default:
918eb492e01SAnderson Briglia 		BT_DBG("Unknown command code 0x%2.2x", code);
919eb492e01SAnderson Briglia 
920eb492e01SAnderson Briglia 		reason = SMP_CMD_NOTSUPP;
9213a0259bbSVinicius Costa Gomes 		err = -EOPNOTSUPP;
9223a0259bbSVinicius Costa Gomes 		goto done;
9233a0259bbSVinicius Costa Gomes 	}
9243a0259bbSVinicius Costa Gomes 
9253a0259bbSVinicius Costa Gomes done:
9263a0259bbSVinicius Costa Gomes 	if (reason)
9274f957a76SBrian Gix 		smp_failure(conn, reason, 1);
928eb492e01SAnderson Briglia 
929eb492e01SAnderson Briglia 	kfree_skb(skb);
930eb492e01SAnderson Briglia 	return err;
931eb492e01SAnderson Briglia }
9327034b911SVinicius Costa Gomes 
9337034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
9347034b911SVinicius Costa Gomes {
9357034b911SVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp;
9361c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
9377034b911SVinicius Costa Gomes 	__u8 *keydist;
9387034b911SVinicius Costa Gomes 
9397034b911SVinicius Costa Gomes 	BT_DBG("conn %p force %d", conn, force);
9407034b911SVinicius Costa Gomes 
94151a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
942d26a2345SVinicius Costa Gomes 		return 0;
943d26a2345SVinicius Costa Gomes 
9441c1def09SVinicius Costa Gomes 	rsp = (void *) &smp->prsp[1];
9457034b911SVinicius Costa Gomes 
9467034b911SVinicius Costa Gomes 	/* The responder sends its keys first */
9477034b911SVinicius Costa Gomes 	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
9487034b911SVinicius Costa Gomes 		return 0;
9497034b911SVinicius Costa Gomes 
9501c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
9517034b911SVinicius Costa Gomes 
9527034b911SVinicius Costa Gomes 	if (conn->hcon->out) {
9537034b911SVinicius Costa Gomes 		keydist = &rsp->init_key_dist;
9547034b911SVinicius Costa Gomes 		*keydist &= req->init_key_dist;
9557034b911SVinicius Costa Gomes 	} else {
9567034b911SVinicius Costa Gomes 		keydist = &rsp->resp_key_dist;
9577034b911SVinicius Costa Gomes 		*keydist &= req->resp_key_dist;
9587034b911SVinicius Costa Gomes 	}
9597034b911SVinicius Costa Gomes 
9607034b911SVinicius Costa Gomes 
9617034b911SVinicius Costa Gomes 	BT_DBG("keydist 0x%x", *keydist);
9627034b911SVinicius Costa Gomes 
9637034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ENC_KEY) {
9647034b911SVinicius Costa Gomes 		struct smp_cmd_encrypt_info enc;
9657034b911SVinicius Costa Gomes 		struct smp_cmd_master_ident ident;
966c9839a11SVinicius Costa Gomes 		struct hci_conn *hcon = conn->hcon;
967c9839a11SVinicius Costa Gomes 		u8 authenticated;
9687034b911SVinicius Costa Gomes 		__le16 ediv;
9697034b911SVinicius Costa Gomes 
9707034b911SVinicius Costa Gomes 		get_random_bytes(enc.ltk, sizeof(enc.ltk));
9717034b911SVinicius Costa Gomes 		get_random_bytes(&ediv, sizeof(ediv));
9727034b911SVinicius Costa Gomes 		get_random_bytes(ident.rand, sizeof(ident.rand));
9737034b911SVinicius Costa Gomes 
9747034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
9757034b911SVinicius Costa Gomes 
976c9839a11SVinicius Costa Gomes 		authenticated = hcon->sec_level == BT_SECURITY_HIGH;
977c9839a11SVinicius Costa Gomes 		hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
978c9839a11SVinicius Costa Gomes 			    HCI_SMP_LTK_SLAVE, 1, authenticated,
97904124681SGustavo F. Padovan 			    enc.ltk, smp->enc_key_size, ediv, ident.rand);
98016b90839SVinicius Costa Gomes 
98158115373SAndrei Emeltchenko 		ident.ediv = ediv;
9827034b911SVinicius Costa Gomes 
9837034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
9847034b911SVinicius Costa Gomes 
9857034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ENC_KEY;
9867034b911SVinicius Costa Gomes 	}
9877034b911SVinicius Costa Gomes 
9887034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ID_KEY) {
9897034b911SVinicius Costa Gomes 		struct smp_cmd_ident_addr_info addrinfo;
9907034b911SVinicius Costa Gomes 		struct smp_cmd_ident_info idinfo;
9917034b911SVinicius Costa Gomes 
9927034b911SVinicius Costa Gomes 		/* Send a dummy key */
9937034b911SVinicius Costa Gomes 		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
9947034b911SVinicius Costa Gomes 
9957034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
9967034b911SVinicius Costa Gomes 
9977034b911SVinicius Costa Gomes 		/* Just public address */
9987034b911SVinicius Costa Gomes 		memset(&addrinfo, 0, sizeof(addrinfo));
9997034b911SVinicius Costa Gomes 		bacpy(&addrinfo.bdaddr, conn->src);
10007034b911SVinicius Costa Gomes 
10017034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
10027034b911SVinicius Costa Gomes 								&addrinfo);
10037034b911SVinicius Costa Gomes 
10047034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ID_KEY;
10057034b911SVinicius Costa Gomes 	}
10067034b911SVinicius Costa Gomes 
10077034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_SIGN) {
10087034b911SVinicius Costa Gomes 		struct smp_cmd_sign_info sign;
10097034b911SVinicius Costa Gomes 
10107034b911SVinicius Costa Gomes 		/* Send a dummy key */
10117034b911SVinicius Costa Gomes 		get_random_bytes(sign.csrk, sizeof(sign.csrk));
10127034b911SVinicius Costa Gomes 
10137034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
10147034b911SVinicius Costa Gomes 
10157034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_SIGN;
10167034b911SVinicius Costa Gomes 	}
10177034b911SVinicius Costa Gomes 
1018d26a2345SVinicius Costa Gomes 	if (conn->hcon->out || force) {
101951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
10206c9d42a1SGustavo F. Padovan 		cancel_delayed_work_sync(&conn->security_timer);
10218aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1022d26a2345SVinicius Costa Gomes 	}
1023d26a2345SVinicius Costa Gomes 
10247034b911SVinicius Costa Gomes 	return 0;
10257034b911SVinicius Costa Gomes }
1026