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