xref: /openbmc/linux/net/bluetooth/smp.c (revision b3ff53ff)
1eb492e01SAnderson Briglia /*
2eb492e01SAnderson Briglia    BlueZ - Bluetooth protocol stack for Linux
3eb492e01SAnderson Briglia    Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4eb492e01SAnderson Briglia 
5eb492e01SAnderson Briglia    This program is free software; you can redistribute it and/or modify
6eb492e01SAnderson Briglia    it under the terms of the GNU General Public License version 2 as
7eb492e01SAnderson Briglia    published by the Free Software Foundation;
8eb492e01SAnderson Briglia 
9eb492e01SAnderson Briglia    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10eb492e01SAnderson Briglia    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11eb492e01SAnderson Briglia    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12eb492e01SAnderson Briglia    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13eb492e01SAnderson Briglia    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14eb492e01SAnderson Briglia    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15eb492e01SAnderson Briglia    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16eb492e01SAnderson Briglia    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eb492e01SAnderson Briglia 
18eb492e01SAnderson Briglia    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19eb492e01SAnderson Briglia    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20eb492e01SAnderson Briglia    SOFTWARE IS DISCLAIMED.
21eb492e01SAnderson Briglia */
22eb492e01SAnderson Briglia 
23eb492e01SAnderson Briglia #include <net/bluetooth/bluetooth.h>
24eb492e01SAnderson Briglia #include <net/bluetooth/hci_core.h>
25eb492e01SAnderson Briglia #include <net/bluetooth/l2cap.h>
262b64d153SBrian Gix #include <net/bluetooth/mgmt.h>
27eb492e01SAnderson Briglia #include <net/bluetooth/smp.h>
28d22ef0bcSAnderson Briglia #include <linux/crypto.h>
29f70490e6SStephen Rothwell #include <linux/scatterlist.h>
30d22ef0bcSAnderson Briglia #include <crypto/b128ops.h>
31d22ef0bcSAnderson Briglia 
3217b02e62SMarcel Holtmann #define SMP_TIMEOUT	msecs_to_jiffies(30000)
335d3de7dfSVinicius Costa Gomes 
34d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16])
35d22ef0bcSAnderson Briglia {
36d22ef0bcSAnderson Briglia 	int i;
37d22ef0bcSAnderson Briglia 	for (i = 0; i < 16; i++)
38d22ef0bcSAnderson Briglia 		dst[15 - i] = src[i];
39d22ef0bcSAnderson Briglia }
40d22ef0bcSAnderson Briglia 
41d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7])
42d22ef0bcSAnderson Briglia {
43d22ef0bcSAnderson Briglia 	int i;
44d22ef0bcSAnderson Briglia 	for (i = 0; i < 7; i++)
45d22ef0bcSAnderson Briglia 		dst[6 - i] = src[i];
46d22ef0bcSAnderson Briglia }
47d22ef0bcSAnderson Briglia 
48d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
49d22ef0bcSAnderson Briglia {
50d22ef0bcSAnderson Briglia 	struct blkcipher_desc desc;
51d22ef0bcSAnderson Briglia 	struct scatterlist sg;
52d22ef0bcSAnderson Briglia 	int err, iv_len;
53d22ef0bcSAnderson Briglia 	unsigned char iv[128];
54d22ef0bcSAnderson Briglia 
55d22ef0bcSAnderson Briglia 	if (tfm == NULL) {
56d22ef0bcSAnderson Briglia 		BT_ERR("tfm %p", tfm);
57d22ef0bcSAnderson Briglia 		return -EINVAL;
58d22ef0bcSAnderson Briglia 	}
59d22ef0bcSAnderson Briglia 
60d22ef0bcSAnderson Briglia 	desc.tfm = tfm;
61d22ef0bcSAnderson Briglia 	desc.flags = 0;
62d22ef0bcSAnderson Briglia 
63d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_setkey(tfm, k, 16);
64d22ef0bcSAnderson Briglia 	if (err) {
65d22ef0bcSAnderson Briglia 		BT_ERR("cipher setkey failed: %d", err);
66d22ef0bcSAnderson Briglia 		return err;
67d22ef0bcSAnderson Briglia 	}
68d22ef0bcSAnderson Briglia 
69d22ef0bcSAnderson Briglia 	sg_init_one(&sg, r, 16);
70d22ef0bcSAnderson Briglia 
71d22ef0bcSAnderson Briglia 	iv_len = crypto_blkcipher_ivsize(tfm);
72d22ef0bcSAnderson Briglia 	if (iv_len) {
73d22ef0bcSAnderson Briglia 		memset(&iv, 0xff, iv_len);
74d22ef0bcSAnderson Briglia 		crypto_blkcipher_set_iv(tfm, iv, iv_len);
75d22ef0bcSAnderson Briglia 	}
76d22ef0bcSAnderson Briglia 
77d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
78d22ef0bcSAnderson Briglia 	if (err)
79d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error %d", err);
80d22ef0bcSAnderson Briglia 
81d22ef0bcSAnderson Briglia 	return err;
82d22ef0bcSAnderson Briglia }
83d22ef0bcSAnderson Briglia 
84d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
85d22ef0bcSAnderson Briglia 		u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
86d22ef0bcSAnderson Briglia 		u8 _rat, bdaddr_t *ra, u8 res[16])
87d22ef0bcSAnderson Briglia {
88d22ef0bcSAnderson Briglia 	u8 p1[16], p2[16];
89d22ef0bcSAnderson Briglia 	int err;
90d22ef0bcSAnderson Briglia 
91d22ef0bcSAnderson Briglia 	memset(p1, 0, 16);
92d22ef0bcSAnderson Briglia 
93d22ef0bcSAnderson Briglia 	/* p1 = pres || preq || _rat || _iat */
94d22ef0bcSAnderson Briglia 	swap56(pres, p1);
95d22ef0bcSAnderson Briglia 	swap56(preq, p1 + 7);
96d22ef0bcSAnderson Briglia 	p1[14] = _rat;
97d22ef0bcSAnderson Briglia 	p1[15] = _iat;
98d22ef0bcSAnderson Briglia 
99d22ef0bcSAnderson Briglia 	memset(p2, 0, 16);
100d22ef0bcSAnderson Briglia 
101d22ef0bcSAnderson Briglia 	/* p2 = padding || ia || ra */
102d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 4), ia);
103d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 10), ra);
104d22ef0bcSAnderson Briglia 
105d22ef0bcSAnderson Briglia 	/* res = r XOR p1 */
106d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
107d22ef0bcSAnderson Briglia 
108d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
109d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
110d22ef0bcSAnderson Briglia 	if (err) {
111d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
112d22ef0bcSAnderson Briglia 		return err;
113d22ef0bcSAnderson Briglia 	}
114d22ef0bcSAnderson Briglia 
115d22ef0bcSAnderson Briglia 	/* res = res XOR p2 */
116d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
117d22ef0bcSAnderson Briglia 
118d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
119d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
120d22ef0bcSAnderson Briglia 	if (err)
121d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
122d22ef0bcSAnderson Briglia 
123d22ef0bcSAnderson Briglia 	return err;
124d22ef0bcSAnderson Briglia }
125d22ef0bcSAnderson Briglia 
126d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
127d22ef0bcSAnderson Briglia 			u8 r1[16], u8 r2[16], u8 _r[16])
128d22ef0bcSAnderson Briglia {
129d22ef0bcSAnderson Briglia 	int err;
130d22ef0bcSAnderson Briglia 
131d22ef0bcSAnderson Briglia 	/* Just least significant octets from r1 and r2 are considered */
132d22ef0bcSAnderson Briglia 	memcpy(_r, r1 + 8, 8);
133d22ef0bcSAnderson Briglia 	memcpy(_r + 8, r2 + 8, 8);
134d22ef0bcSAnderson Briglia 
135d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, _r);
136d22ef0bcSAnderson Briglia 	if (err)
137d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
138d22ef0bcSAnderson Briglia 
139d22ef0bcSAnderson Briglia 	return err;
140d22ef0bcSAnderson Briglia }
141d22ef0bcSAnderson Briglia 
142d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf)
143d22ef0bcSAnderson Briglia {
144d22ef0bcSAnderson Briglia 	get_random_bytes(buf, 16);
145d22ef0bcSAnderson Briglia 
146d22ef0bcSAnderson Briglia 	return 0;
147d22ef0bcSAnderson Briglia }
148eb492e01SAnderson Briglia 
149eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
150eb492e01SAnderson Briglia 						u16 dlen, void *data)
151eb492e01SAnderson Briglia {
152eb492e01SAnderson Briglia 	struct sk_buff *skb;
153eb492e01SAnderson Briglia 	struct l2cap_hdr *lh;
154eb492e01SAnderson Briglia 	int len;
155eb492e01SAnderson Briglia 
156eb492e01SAnderson Briglia 	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
157eb492e01SAnderson Briglia 
158eb492e01SAnderson Briglia 	if (len > conn->mtu)
159eb492e01SAnderson Briglia 		return NULL;
160eb492e01SAnderson Briglia 
161eb492e01SAnderson Briglia 	skb = bt_skb_alloc(len, GFP_ATOMIC);
162eb492e01SAnderson Briglia 	if (!skb)
163eb492e01SAnderson Briglia 		return NULL;
164eb492e01SAnderson Briglia 
165eb492e01SAnderson Briglia 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
166eb492e01SAnderson Briglia 	lh->len = cpu_to_le16(sizeof(code) + dlen);
167eb492e01SAnderson Briglia 	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
168eb492e01SAnderson Briglia 
169eb492e01SAnderson Briglia 	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
170eb492e01SAnderson Briglia 
171eb492e01SAnderson Briglia 	memcpy(skb_put(skb, dlen), data, dlen);
172eb492e01SAnderson Briglia 
173eb492e01SAnderson Briglia 	return skb;
174eb492e01SAnderson Briglia }
175eb492e01SAnderson Briglia 
176eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
177eb492e01SAnderson Briglia {
178eb492e01SAnderson Briglia 	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
179eb492e01SAnderson Briglia 
180eb492e01SAnderson Briglia 	BT_DBG("code 0x%2.2x", code);
181eb492e01SAnderson Briglia 
182eb492e01SAnderson Briglia 	if (!skb)
183eb492e01SAnderson Briglia 		return;
184eb492e01SAnderson Briglia 
18573d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
18673d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, 0);
187e2dcd113SVinicius Costa Gomes 
1886c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
18917b02e62SMarcel Holtmann 	schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
190eb492e01SAnderson Briglia }
191eb492e01SAnderson Briglia 
1922b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq)
1932b64d153SBrian Gix {
1942b64d153SBrian Gix 	if (authreq & SMP_AUTH_MITM)
1952b64d153SBrian Gix 		return BT_SECURITY_HIGH;
1962b64d153SBrian Gix 	else
1972b64d153SBrian Gix 		return BT_SECURITY_MEDIUM;
1982b64d153SBrian Gix }
1992b64d153SBrian Gix 
2002b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level)
2012b64d153SBrian Gix {
2022b64d153SBrian Gix 	switch (sec_level) {
2032b64d153SBrian Gix 	case BT_SECURITY_HIGH:
2042b64d153SBrian Gix 		return SMP_AUTH_MITM | SMP_AUTH_BONDING;
2052b64d153SBrian Gix 	case BT_SECURITY_MEDIUM:
2062b64d153SBrian Gix 		return SMP_AUTH_BONDING;
2072b64d153SBrian Gix 	default:
2082b64d153SBrian Gix 		return SMP_AUTH_NONE;
2092b64d153SBrian Gix 	}
2102b64d153SBrian Gix }
2112b64d153SBrian Gix 
212b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn,
21354790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *req,
21454790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *rsp,
21554790f73SVinicius Costa Gomes 				__u8 authreq)
216b8e66eacSVinicius Costa Gomes {
2172b64d153SBrian Gix 	u8 dist_keys = 0;
21854790f73SVinicius Costa Gomes 
219a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
220ca10b5eeSVinicius Costa Gomes 		dist_keys = SMP_DIST_ENC_KEY;
22154790f73SVinicius Costa Gomes 		authreq |= SMP_AUTH_BONDING;
2222b64d153SBrian Gix 	} else {
2232b64d153SBrian Gix 		authreq &= ~SMP_AUTH_BONDING;
22454790f73SVinicius Costa Gomes 	}
22554790f73SVinicius Costa Gomes 
22654790f73SVinicius Costa Gomes 	if (rsp == NULL) {
22754790f73SVinicius Costa Gomes 		req->io_capability = conn->hcon->io_capability;
22854790f73SVinicius Costa Gomes 		req->oob_flag = SMP_OOB_NOT_PRESENT;
22954790f73SVinicius Costa Gomes 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2302b64d153SBrian Gix 		req->init_key_dist = 0;
23154790f73SVinicius Costa Gomes 		req->resp_key_dist = dist_keys;
23254790f73SVinicius Costa Gomes 		req->auth_req = authreq;
23354790f73SVinicius Costa Gomes 		return;
23454790f73SVinicius Costa Gomes 	}
23554790f73SVinicius Costa Gomes 
23654790f73SVinicius Costa Gomes 	rsp->io_capability = conn->hcon->io_capability;
23754790f73SVinicius Costa Gomes 	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
23854790f73SVinicius Costa Gomes 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2392b64d153SBrian Gix 	rsp->init_key_dist = 0;
24054790f73SVinicius Costa Gomes 	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
24154790f73SVinicius Costa Gomes 	rsp->auth_req = authreq;
242b8e66eacSVinicius Costa Gomes }
243b8e66eacSVinicius Costa Gomes 
2443158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
2453158c50cSVinicius Costa Gomes {
2461c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
2471c1def09SVinicius Costa Gomes 
2483158c50cSVinicius Costa Gomes 	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
2493158c50cSVinicius Costa Gomes 			(max_key_size < SMP_MIN_ENC_KEY_SIZE))
2503158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
2513158c50cSVinicius Costa Gomes 
252f7aa611aSVinicius Costa Gomes 	smp->enc_key_size = max_key_size;
2533158c50cSVinicius Costa Gomes 
2543158c50cSVinicius Costa Gomes 	return 0;
2553158c50cSVinicius Costa Gomes }
2563158c50cSVinicius Costa Gomes 
2574f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
2584f957a76SBrian Gix {
259bab73cb6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
260bab73cb6SJohan Hedberg 
2614f957a76SBrian Gix 	if (send)
2624f957a76SBrian Gix 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
2634f957a76SBrian Gix 								&reason);
2644f957a76SBrian Gix 
26551a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
266bab73cb6SJohan Hedberg 	mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
267bab73cb6SJohan Hedberg 			 hcon->dst_type, reason);
268f1c09c07SVinicius Costa Gomes 
269f1c09c07SVinicius Costa Gomes 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
2706c9d42a1SGustavo F. Padovan 		cancel_delayed_work_sync(&conn->security_timer);
2714f957a76SBrian Gix 		smp_chan_destroy(conn);
2724f957a76SBrian Gix 	}
273f1c09c07SVinicius Costa Gomes }
2744f957a76SBrian Gix 
2752b64d153SBrian Gix #define JUST_WORKS	0x00
2762b64d153SBrian Gix #define JUST_CFM	0x01
2772b64d153SBrian Gix #define REQ_PASSKEY	0x02
2782b64d153SBrian Gix #define CFM_PASSKEY	0x03
2792b64d153SBrian Gix #define REQ_OOB		0x04
2802b64d153SBrian Gix #define OVERLAP		0xFF
2812b64d153SBrian Gix 
2822b64d153SBrian Gix static const u8 gen_method[5][5] = {
2832b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
2842b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
2852b64d153SBrian Gix 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
2862b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    JUST_WORKS,  JUST_WORKS, JUST_CFM    },
2872b64d153SBrian Gix 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP     },
2882b64d153SBrian Gix };
2892b64d153SBrian Gix 
2902b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
2912b64d153SBrian Gix 						u8 local_io, u8 remote_io)
2922b64d153SBrian Gix {
2932b64d153SBrian Gix 	struct hci_conn *hcon = conn->hcon;
2942b64d153SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
2952b64d153SBrian Gix 	u8 method;
2962b64d153SBrian Gix 	u32 passkey = 0;
2972b64d153SBrian Gix 	int ret = 0;
2982b64d153SBrian Gix 
2992b64d153SBrian Gix 	/* Initialize key for JUST WORKS */
3002b64d153SBrian Gix 	memset(smp->tk, 0, sizeof(smp->tk));
3012b64d153SBrian Gix 	clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
3022b64d153SBrian Gix 
3032b64d153SBrian Gix 	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
3042b64d153SBrian Gix 
3052b64d153SBrian Gix 	/* If neither side wants MITM, use JUST WORKS */
3062b64d153SBrian Gix 	/* If either side has unknown io_caps, use JUST WORKS */
3072b64d153SBrian Gix 	/* Otherwise, look up method from the table */
3082b64d153SBrian Gix 	if (!(auth & SMP_AUTH_MITM) ||
3092b64d153SBrian Gix 			local_io > SMP_IO_KEYBOARD_DISPLAY ||
3102b64d153SBrian Gix 			remote_io > SMP_IO_KEYBOARD_DISPLAY)
3112b64d153SBrian Gix 		method = JUST_WORKS;
3122b64d153SBrian Gix 	else
313b3ff53ffSIdo Yariv 		method = gen_method[remote_io][local_io];
3142b64d153SBrian Gix 
3152b64d153SBrian Gix 	/* If not bonding, don't ask user to confirm a Zero TK */
3162b64d153SBrian Gix 	if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
3172b64d153SBrian Gix 		method = JUST_WORKS;
3182b64d153SBrian Gix 
3192b64d153SBrian Gix 	/* If Just Works, Continue with Zero TK */
3202b64d153SBrian Gix 	if (method == JUST_WORKS) {
3212b64d153SBrian Gix 		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
3222b64d153SBrian Gix 		return 0;
3232b64d153SBrian Gix 	}
3242b64d153SBrian Gix 
3252b64d153SBrian Gix 	/* Not Just Works/Confirm results in MITM Authentication */
3262b64d153SBrian Gix 	if (method != JUST_CFM)
3272b64d153SBrian Gix 		set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
3282b64d153SBrian Gix 
3292b64d153SBrian Gix 	/* If both devices have Keyoard-Display I/O, the master
3302b64d153SBrian Gix 	 * Confirms and the slave Enters the passkey.
3312b64d153SBrian Gix 	 */
3322b64d153SBrian Gix 	if (method == OVERLAP) {
3332b64d153SBrian Gix 		if (hcon->link_mode & HCI_LM_MASTER)
3342b64d153SBrian Gix 			method = CFM_PASSKEY;
3352b64d153SBrian Gix 		else
3362b64d153SBrian Gix 			method = REQ_PASSKEY;
3372b64d153SBrian Gix 	}
3382b64d153SBrian Gix 
3392b64d153SBrian Gix 	/* Generate random passkey. Not valid until confirmed. */
3402b64d153SBrian Gix 	if (method == CFM_PASSKEY) {
3412b64d153SBrian Gix 		u8 key[16];
3422b64d153SBrian Gix 
3432b64d153SBrian Gix 		memset(key, 0, sizeof(key));
3442b64d153SBrian Gix 		get_random_bytes(&passkey, sizeof(passkey));
3452b64d153SBrian Gix 		passkey %= 1000000;
3462b64d153SBrian Gix 		put_unaligned_le32(passkey, key);
3472b64d153SBrian Gix 		swap128(key, smp->tk);
3482b64d153SBrian Gix 		BT_DBG("PassKey: %d", passkey);
3492b64d153SBrian Gix 	}
3502b64d153SBrian Gix 
3512b64d153SBrian Gix 	hci_dev_lock(hcon->hdev);
3522b64d153SBrian Gix 
3532b64d153SBrian Gix 	if (method == REQ_PASSKEY)
354272d90dfSJohan Hedberg 		ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
355272d90dfSJohan Hedberg 						hcon->type, hcon->dst_type);
3562b64d153SBrian Gix 	else
3572b64d153SBrian Gix 		ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
358272d90dfSJohan Hedberg 						hcon->type, hcon->dst_type,
3592b64d153SBrian Gix 						cpu_to_le32(passkey), 0);
3602b64d153SBrian Gix 
3612b64d153SBrian Gix 	hci_dev_unlock(hcon->hdev);
3622b64d153SBrian Gix 
3632b64d153SBrian Gix 	return ret;
3642b64d153SBrian Gix }
3652b64d153SBrian Gix 
3668aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work)
3678aab4757SVinicius Costa Gomes {
3688aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
3698aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
3708aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm;
3718aab4757SVinicius Costa Gomes 	struct smp_cmd_pairing_confirm cp;
3728aab4757SVinicius Costa Gomes 	int ret;
3738aab4757SVinicius Costa Gomes 	u8 res[16], reason;
3748aab4757SVinicius Costa Gomes 
3758aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
3768aab4757SVinicius Costa Gomes 
3778aab4757SVinicius Costa Gomes 	tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
3788aab4757SVinicius Costa Gomes 	if (IS_ERR(tfm)) {
3798aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3808aab4757SVinicius Costa Gomes 		goto error;
3818aab4757SVinicius Costa Gomes 	}
3828aab4757SVinicius Costa Gomes 
3838aab4757SVinicius Costa Gomes 	smp->tfm = tfm;
3848aab4757SVinicius Costa Gomes 
3858aab4757SVinicius Costa Gomes 	if (conn->hcon->out)
3868aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
38704124681SGustavo F. Padovan 			     conn->src, conn->hcon->dst_type, conn->dst, res);
3888aab4757SVinicius Costa Gomes 	else
3898aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
3908aab4757SVinicius Costa Gomes 			     conn->hcon->dst_type, conn->dst, 0, conn->src,
3918aab4757SVinicius Costa Gomes 			     res);
3928aab4757SVinicius Costa Gomes 	if (ret) {
3938aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3948aab4757SVinicius Costa Gomes 		goto error;
3958aab4757SVinicius Costa Gomes 	}
3968aab4757SVinicius Costa Gomes 
3972b64d153SBrian Gix 	clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
3982b64d153SBrian Gix 
3998aab4757SVinicius Costa Gomes 	swap128(res, cp.confirm_val);
4008aab4757SVinicius Costa Gomes 	smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
4018aab4757SVinicius Costa Gomes 
4028aab4757SVinicius Costa Gomes 	return;
4038aab4757SVinicius Costa Gomes 
4048aab4757SVinicius Costa Gomes error:
4054f957a76SBrian Gix 	smp_failure(conn, reason, 1);
4068aab4757SVinicius Costa Gomes }
4078aab4757SVinicius Costa Gomes 
4088aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work)
4098aab4757SVinicius Costa Gomes {
4108aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, random);
4118aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
4128aab4757SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
4138aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm = smp->tfm;
4148aab4757SVinicius Costa Gomes 	u8 reason, confirm[16], res[16], key[16];
4158aab4757SVinicius Costa Gomes 	int ret;
4168aab4757SVinicius Costa Gomes 
4178aab4757SVinicius Costa Gomes 	if (IS_ERR_OR_NULL(tfm)) {
4188aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
4198aab4757SVinicius Costa Gomes 		goto error;
4208aab4757SVinicius Costa Gomes 	}
4218aab4757SVinicius Costa Gomes 
4228aab4757SVinicius Costa Gomes 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
4238aab4757SVinicius Costa Gomes 
4248aab4757SVinicius Costa Gomes 	if (hcon->out)
4258aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
42604124681SGustavo F. Padovan 			     conn->src, hcon->dst_type, conn->dst, res);
4278aab4757SVinicius Costa Gomes 	else
4288aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
42904124681SGustavo F. Padovan 			     hcon->dst_type, conn->dst, 0, conn->src, res);
4308aab4757SVinicius Costa Gomes 	if (ret) {
4318aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
4328aab4757SVinicius Costa Gomes 		goto error;
4338aab4757SVinicius Costa Gomes 	}
4348aab4757SVinicius Costa Gomes 
4358aab4757SVinicius Costa Gomes 	swap128(res, confirm);
4368aab4757SVinicius Costa Gomes 
4378aab4757SVinicius Costa Gomes 	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
4388aab4757SVinicius Costa Gomes 		BT_ERR("Pairing failed (confirmation values mismatch)");
4398aab4757SVinicius Costa Gomes 		reason = SMP_CONFIRM_FAILED;
4408aab4757SVinicius Costa Gomes 		goto error;
4418aab4757SVinicius Costa Gomes 	}
4428aab4757SVinicius Costa Gomes 
4438aab4757SVinicius Costa Gomes 	if (hcon->out) {
4448aab4757SVinicius Costa Gomes 		u8 stk[16], rand[8];
4458aab4757SVinicius Costa Gomes 		__le16 ediv;
4468aab4757SVinicius Costa Gomes 
4478aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
4488aab4757SVinicius Costa Gomes 		ediv = 0;
4498aab4757SVinicius Costa Gomes 
4508aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
4518aab4757SVinicius Costa Gomes 		swap128(key, stk);
4528aab4757SVinicius Costa Gomes 
453f7aa611aSVinicius Costa Gomes 		memset(stk + smp->enc_key_size, 0,
454f7aa611aSVinicius Costa Gomes 		       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
4558aab4757SVinicius Costa Gomes 
45651a8efd7SJohan Hedberg 		if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
4578aab4757SVinicius Costa Gomes 			reason = SMP_UNSPECIFIED;
4588aab4757SVinicius Costa Gomes 			goto error;
4598aab4757SVinicius Costa Gomes 		}
4608aab4757SVinicius Costa Gomes 
4618aab4757SVinicius Costa Gomes 		hci_le_start_enc(hcon, ediv, rand, stk);
462f7aa611aSVinicius Costa Gomes 		hcon->enc_key_size = smp->enc_key_size;
4638aab4757SVinicius Costa Gomes 	} else {
4648aab4757SVinicius Costa Gomes 		u8 stk[16], r[16], rand[8];
4658aab4757SVinicius Costa Gomes 		__le16 ediv;
4668aab4757SVinicius Costa Gomes 
4678aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
4688aab4757SVinicius Costa Gomes 		ediv = 0;
4698aab4757SVinicius Costa Gomes 
4708aab4757SVinicius Costa Gomes 		swap128(smp->prnd, r);
4718aab4757SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
4728aab4757SVinicius Costa Gomes 
4738aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
4748aab4757SVinicius Costa Gomes 		swap128(key, stk);
4758aab4757SVinicius Costa Gomes 
476f7aa611aSVinicius Costa Gomes 		memset(stk + smp->enc_key_size, 0,
477f7aa611aSVinicius Costa Gomes 				SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
4788aab4757SVinicius Costa Gomes 
479c9839a11SVinicius Costa Gomes 		hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
48004124681SGustavo F. Padovan 			    HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
48104124681SGustavo F. Padovan 			    ediv, rand);
4828aab4757SVinicius Costa Gomes 	}
4838aab4757SVinicius Costa Gomes 
4848aab4757SVinicius Costa Gomes 	return;
4858aab4757SVinicius Costa Gomes 
4868aab4757SVinicius Costa Gomes error:
4874f957a76SBrian Gix 	smp_failure(conn, reason, 1);
4888aab4757SVinicius Costa Gomes }
4898aab4757SVinicius Costa Gomes 
4908aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
4918aab4757SVinicius Costa Gomes {
4928aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
4938aab4757SVinicius Costa Gomes 
4948aab4757SVinicius Costa Gomes 	smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
4958aab4757SVinicius Costa Gomes 	if (!smp)
4968aab4757SVinicius Costa Gomes 		return NULL;
4978aab4757SVinicius Costa Gomes 
4988aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->confirm, confirm_work);
4998aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->random, random_work);
5008aab4757SVinicius Costa Gomes 
5018aab4757SVinicius Costa Gomes 	smp->conn = conn;
5028aab4757SVinicius Costa Gomes 	conn->smp_chan = smp;
5032b64d153SBrian Gix 	conn->hcon->smp_conn = conn;
5048aab4757SVinicius Costa Gomes 
5058aab4757SVinicius Costa Gomes 	hci_conn_hold(conn->hcon);
5068aab4757SVinicius Costa Gomes 
5078aab4757SVinicius Costa Gomes 	return smp;
5088aab4757SVinicius Costa Gomes }
5098aab4757SVinicius Costa Gomes 
5108aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn)
5118aab4757SVinicius Costa Gomes {
512c8eb9690SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
513c8eb9690SBrian Gix 
514f1c09c07SVinicius Costa Gomes 	BUG_ON(!smp);
515c8eb9690SBrian Gix 
516c8eb9690SBrian Gix 	if (smp->tfm)
517c8eb9690SBrian Gix 		crypto_free_blkcipher(smp->tfm);
518c8eb9690SBrian Gix 
519c8eb9690SBrian Gix 	kfree(smp);
520c8eb9690SBrian Gix 	conn->smp_chan = NULL;
5212b64d153SBrian Gix 	conn->hcon->smp_conn = NULL;
5228aab4757SVinicius Costa Gomes 	hci_conn_put(conn->hcon);
5238aab4757SVinicius Costa Gomes }
5248aab4757SVinicius Costa Gomes 
5252b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
5262b64d153SBrian Gix {
5272b64d153SBrian Gix 	struct l2cap_conn *conn = hcon->smp_conn;
5282b64d153SBrian Gix 	struct smp_chan *smp;
5292b64d153SBrian Gix 	u32 value;
5302b64d153SBrian Gix 	u8 key[16];
5312b64d153SBrian Gix 
5322b64d153SBrian Gix 	BT_DBG("");
5332b64d153SBrian Gix 
5342b64d153SBrian Gix 	if (!conn)
5352b64d153SBrian Gix 		return -ENOTCONN;
5362b64d153SBrian Gix 
5372b64d153SBrian Gix 	smp = conn->smp_chan;
5382b64d153SBrian Gix 
5392b64d153SBrian Gix 	switch (mgmt_op) {
5402b64d153SBrian Gix 	case MGMT_OP_USER_PASSKEY_REPLY:
5412b64d153SBrian Gix 		value = le32_to_cpu(passkey);
5422b64d153SBrian Gix 		memset(key, 0, sizeof(key));
5432b64d153SBrian Gix 		BT_DBG("PassKey: %d", value);
5442b64d153SBrian Gix 		put_unaligned_le32(value, key);
5452b64d153SBrian Gix 		swap128(key, smp->tk);
5462b64d153SBrian Gix 		/* Fall Through */
5472b64d153SBrian Gix 	case MGMT_OP_USER_CONFIRM_REPLY:
5482b64d153SBrian Gix 		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
5492b64d153SBrian Gix 		break;
5502b64d153SBrian Gix 	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
5512b64d153SBrian Gix 	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
5522b64d153SBrian Gix 		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
5532b64d153SBrian Gix 		return 0;
5542b64d153SBrian Gix 	default:
5552b64d153SBrian Gix 		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
5562b64d153SBrian Gix 		return -EOPNOTSUPP;
5572b64d153SBrian Gix 	}
5582b64d153SBrian Gix 
5592b64d153SBrian Gix 	/* If it is our turn to send Pairing Confirm, do so now */
5602b64d153SBrian Gix 	if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
5612b64d153SBrian Gix 		queue_work(hcon->hdev->workqueue, &smp->confirm);
5622b64d153SBrian Gix 
5632b64d153SBrian Gix 	return 0;
5642b64d153SBrian Gix }
5652b64d153SBrian Gix 
566da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
56788ba43b6SAnderson Briglia {
5683158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
5698aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
5703158c50cSVinicius Costa Gomes 	u8 key_size;
5712b64d153SBrian Gix 	u8 auth = SMP_AUTH_NONE;
5728aab4757SVinicius Costa Gomes 	int ret;
57388ba43b6SAnderson Briglia 
57488ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
57588ba43b6SAnderson Briglia 
5762b64d153SBrian Gix 	if (conn->hcon->link_mode & HCI_LM_MASTER)
5772b64d153SBrian Gix 		return SMP_CMD_NOTSUPP;
5782b64d153SBrian Gix 
57951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
5808aab4757SVinicius Costa Gomes 		smp = smp_chan_create(conn);
5818aab4757SVinicius Costa Gomes 
5828aab4757SVinicius Costa Gomes 	smp = conn->smp_chan;
583d26a2345SVinicius Costa Gomes 
5841c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
5851c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], req, sizeof(*req));
5863158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*req));
58788ba43b6SAnderson Briglia 
5882b64d153SBrian Gix 	/* We didn't start the pairing, so match remote */
5892b64d153SBrian Gix 	if (req->auth_req & SMP_AUTH_BONDING)
5902b64d153SBrian Gix 		auth = req->auth_req;
591da85e5e5SVinicius Costa Gomes 
5922b64d153SBrian Gix 	build_pairing_cmd(conn, req, &rsp, auth);
5933158c50cSVinicius Costa Gomes 
5943158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp.max_key_size);
5953158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
5963158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
59788ba43b6SAnderson Briglia 
5988aab4757SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
5998aab4757SVinicius Costa Gomes 	if (ret)
6008aab4757SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
6018aab4757SVinicius Costa Gomes 
6021c1def09SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
6031c1def09SVinicius Costa Gomes 	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
604f01ead31SAnderson Briglia 
6053158c50cSVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
606da85e5e5SVinicius Costa Gomes 
6072b64d153SBrian Gix 	/* Request setup of TK */
6082b64d153SBrian Gix 	ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
6092b64d153SBrian Gix 	if (ret)
6102b64d153SBrian Gix 		return SMP_UNSPECIFIED;
6112b64d153SBrian Gix 
612da85e5e5SVinicius Costa Gomes 	return 0;
61388ba43b6SAnderson Briglia }
61488ba43b6SAnderson Briglia 
615da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
61688ba43b6SAnderson Briglia {
6173158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
6181c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6198aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6202b64d153SBrian Gix 	u8 key_size, auth = SMP_AUTH_NONE;
6217d24ddccSAnderson Briglia 	int ret;
62288ba43b6SAnderson Briglia 
62388ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
62488ba43b6SAnderson Briglia 
6252b64d153SBrian Gix 	if (!(conn->hcon->link_mode & HCI_LM_MASTER))
6262b64d153SBrian Gix 		return SMP_CMD_NOTSUPP;
6272b64d153SBrian Gix 
6283158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*rsp));
629da85e5e5SVinicius Costa Gomes 
6301c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
6313158c50cSVinicius Costa Gomes 
6323158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp->max_key_size);
6333158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
6343158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
6353158c50cSVinicius Costa Gomes 
6361c1def09SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
6377d24ddccSAnderson Briglia 	if (ret)
638da85e5e5SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
6397d24ddccSAnderson Briglia 
6408aab4757SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
6418aab4757SVinicius Costa Gomes 	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
6427d24ddccSAnderson Briglia 
6432b64d153SBrian Gix 	if ((req->auth_req & SMP_AUTH_BONDING) &&
6442b64d153SBrian Gix 			(rsp->auth_req & SMP_AUTH_BONDING))
6452b64d153SBrian Gix 		auth = SMP_AUTH_BONDING;
6462b64d153SBrian Gix 
6472b64d153SBrian Gix 	auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
6482b64d153SBrian Gix 
6492b64d153SBrian Gix 	ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
6502b64d153SBrian Gix 	if (ret)
6512b64d153SBrian Gix 		return SMP_UNSPECIFIED;
6522b64d153SBrian Gix 
6532b64d153SBrian Gix 	set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
6542b64d153SBrian Gix 
6552b64d153SBrian Gix 	/* Can't compose response until we have been confirmed */
6562b64d153SBrian Gix 	if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
6572b64d153SBrian Gix 		return 0;
6582b64d153SBrian Gix 
6598aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->confirm);
660da85e5e5SVinicius Costa Gomes 
661da85e5e5SVinicius Costa Gomes 	return 0;
66288ba43b6SAnderson Briglia }
66388ba43b6SAnderson Briglia 
664da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
66588ba43b6SAnderson Briglia {
6661c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6678aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6687d24ddccSAnderson Briglia 
66988ba43b6SAnderson Briglia 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
67088ba43b6SAnderson Briglia 
6711c1def09SVinicius Costa Gomes 	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
6721c1def09SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->pcnf));
6737d24ddccSAnderson Briglia 
67488ba43b6SAnderson Briglia 	if (conn->hcon->out) {
6757d24ddccSAnderson Briglia 		u8 random[16];
67688ba43b6SAnderson Briglia 
6771c1def09SVinicius Costa Gomes 		swap128(smp->prnd, random);
67888ba43b6SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
6797d24ddccSAnderson Briglia 								random);
6802b64d153SBrian Gix 	} else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
6818aab4757SVinicius Costa Gomes 		queue_work(hdev->workqueue, &smp->confirm);
6822b64d153SBrian Gix 	} else {
6832b64d153SBrian Gix 		set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
68488ba43b6SAnderson Briglia 	}
685da85e5e5SVinicius Costa Gomes 
686da85e5e5SVinicius Costa Gomes 	return 0;
68788ba43b6SAnderson Briglia }
68888ba43b6SAnderson Briglia 
689da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
69088ba43b6SAnderson Briglia {
6911c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6928aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6937d24ddccSAnderson Briglia 
6948aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
6957d24ddccSAnderson Briglia 
6968aab4757SVinicius Costa Gomes 	swap128(skb->data, smp->rrnd);
6978aab4757SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->rrnd));
69888ba43b6SAnderson Briglia 
6998aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->random);
700da85e5e5SVinicius Costa Gomes 
701da85e5e5SVinicius Costa Gomes 	return 0;
70288ba43b6SAnderson Briglia }
70388ba43b6SAnderson Briglia 
704988c5997SVinicius Costa Gomes static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
705988c5997SVinicius Costa Gomes {
706c9839a11SVinicius Costa Gomes 	struct smp_ltk *key;
707988c5997SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
708988c5997SVinicius Costa Gomes 
709c9839a11SVinicius Costa Gomes 	key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
710988c5997SVinicius Costa Gomes 	if (!key)
711988c5997SVinicius Costa Gomes 		return 0;
712988c5997SVinicius Costa Gomes 
71351a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
714988c5997SVinicius Costa Gomes 		return 1;
715988c5997SVinicius Costa Gomes 
716c9839a11SVinicius Costa Gomes 	hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
717c9839a11SVinicius Costa Gomes 	hcon->enc_key_size = key->enc_size;
718988c5997SVinicius Costa Gomes 
719988c5997SVinicius Costa Gomes 	return 1;
720988c5997SVinicius Costa Gomes 
721988c5997SVinicius Costa Gomes }
722da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
72388ba43b6SAnderson Briglia {
72488ba43b6SAnderson Briglia 	struct smp_cmd_security_req *rp = (void *) skb->data;
72588ba43b6SAnderson Briglia 	struct smp_cmd_pairing cp;
726f1cb9af5SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
7278aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
72888ba43b6SAnderson Briglia 
72988ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
73088ba43b6SAnderson Briglia 
7312b64d153SBrian Gix 	hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
732feb45eb5SVinicius Costa Gomes 
733988c5997SVinicius Costa Gomes 	if (smp_ltk_encrypt(conn))
734988c5997SVinicius Costa Gomes 		return 0;
735988c5997SVinicius Costa Gomes 
73651a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
737da85e5e5SVinicius Costa Gomes 		return 0;
738f1cb9af5SVinicius Costa Gomes 
7398aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
740d26a2345SVinicius Costa Gomes 
74188ba43b6SAnderson Briglia 	skb_pull(skb, sizeof(*rp));
74288ba43b6SAnderson Briglia 
743da85e5e5SVinicius Costa Gomes 	memset(&cp, 0, sizeof(cp));
74454790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
74588ba43b6SAnderson Briglia 
7461c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
7471c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], &cp, sizeof(cp));
748f01ead31SAnderson Briglia 
74988ba43b6SAnderson Briglia 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
750f1cb9af5SVinicius Costa Gomes 
751da85e5e5SVinicius Costa Gomes 	return 0;
75288ba43b6SAnderson Briglia }
75388ba43b6SAnderson Briglia 
754eb492e01SAnderson Briglia int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
755eb492e01SAnderson Briglia {
7563a0259bbSVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
7571c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7582b64d153SBrian Gix 	__u8 authreq;
759eb492e01SAnderson Briglia 
7603a0259bbSVinicius Costa Gomes 	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
7613a0259bbSVinicius Costa Gomes 
7622e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(hcon->hdev))
7632e65c9d2SAndre Guedes 		return 1;
7642e65c9d2SAndre Guedes 
765f1cb9af5SVinicius Costa Gomes 	if (sec_level == BT_SECURITY_LOW)
766eb492e01SAnderson Briglia 		return 1;
767f1cb9af5SVinicius Costa Gomes 
768f1cb9af5SVinicius Costa Gomes 	if (hcon->sec_level >= sec_level)
769f1cb9af5SVinicius Costa Gomes 		return 1;
770f1cb9af5SVinicius Costa Gomes 
771988c5997SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER)
772988c5997SVinicius Costa Gomes 		if (smp_ltk_encrypt(conn))
773d26a2345SVinicius Costa Gomes 			goto done;
774d26a2345SVinicius Costa Gomes 
77551a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
776d26a2345SVinicius Costa Gomes 		return 0;
777d26a2345SVinicius Costa Gomes 
7788aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
7792b64d153SBrian Gix 	if (!smp)
7802b64d153SBrian Gix 		return 1;
7812b64d153SBrian Gix 
7822b64d153SBrian Gix 	authreq = seclevel_to_authreq(sec_level);
783d26a2345SVinicius Costa Gomes 
784d26a2345SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER) {
785d26a2345SVinicius Costa Gomes 		struct smp_cmd_pairing cp;
786f01ead31SAnderson Briglia 
7872b64d153SBrian Gix 		build_pairing_cmd(conn, &cp, NULL, authreq);
7881c1def09SVinicius Costa Gomes 		smp->preq[0] = SMP_CMD_PAIRING_REQ;
7891c1def09SVinicius Costa Gomes 		memcpy(&smp->preq[1], &cp, sizeof(cp));
790f01ead31SAnderson Briglia 
791eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
792eb492e01SAnderson Briglia 	} else {
793eb492e01SAnderson Briglia 		struct smp_cmd_security_req cp;
7942b64d153SBrian Gix 		cp.auth_req = authreq;
795eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
796eb492e01SAnderson Briglia 	}
797eb492e01SAnderson Briglia 
79802bc7455SVinicius Costa Gomes done:
799f1cb9af5SVinicius Costa Gomes 	hcon->pending_sec_level = sec_level;
800f1cb9af5SVinicius Costa Gomes 
801eb492e01SAnderson Briglia 	return 0;
802eb492e01SAnderson Briglia }
803eb492e01SAnderson Briglia 
8047034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
8057034b911SVinicius Costa Gomes {
80616b90839SVinicius Costa Gomes 	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
8071c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
80816b90839SVinicius Costa Gomes 
80916b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
81016b90839SVinicius Costa Gomes 
8111c1def09SVinicius Costa Gomes 	memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
81216b90839SVinicius Costa Gomes 
8137034b911SVinicius Costa Gomes 	return 0;
8147034b911SVinicius Costa Gomes }
8157034b911SVinicius Costa Gomes 
8167034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
8177034b911SVinicius Costa Gomes {
81816b90839SVinicius Costa Gomes 	struct smp_cmd_master_ident *rp = (void *) skb->data;
8191c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
820c9839a11SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
821c9839a11SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
822c9839a11SVinicius Costa Gomes 	u8 authenticated;
8237034b911SVinicius Costa Gomes 
82416b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
82516b90839SVinicius Costa Gomes 
826c9839a11SVinicius Costa Gomes 	hci_dev_lock(hdev);
827c9839a11SVinicius Costa Gomes 	authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
828c9839a11SVinicius Costa Gomes 	hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
82904124681SGustavo F. Padovan 		    HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
83004124681SGustavo F. Padovan 		    rp->ediv, rp->rand);
8317034b911SVinicius Costa Gomes 	smp_distribute_keys(conn, 1);
832c9839a11SVinicius Costa Gomes 	hci_dev_unlock(hdev);
8337034b911SVinicius Costa Gomes 
8347034b911SVinicius Costa Gomes 	return 0;
8357034b911SVinicius Costa Gomes }
8367034b911SVinicius Costa Gomes 
837eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
838eb492e01SAnderson Briglia {
839eb492e01SAnderson Briglia 	__u8 code = skb->data[0];
840eb492e01SAnderson Briglia 	__u8 reason;
841eb492e01SAnderson Briglia 	int err = 0;
842eb492e01SAnderson Briglia 
8432e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(conn->hcon->hdev)) {
8442e65c9d2SAndre Guedes 		err = -ENOTSUPP;
8452e65c9d2SAndre Guedes 		reason = SMP_PAIRING_NOTSUPP;
8462e65c9d2SAndre Guedes 		goto done;
8472e65c9d2SAndre Guedes 	}
8482e65c9d2SAndre Guedes 
849eb492e01SAnderson Briglia 	skb_pull(skb, sizeof(code));
850eb492e01SAnderson Briglia 
851eb492e01SAnderson Briglia 	switch (code) {
852eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_REQ:
853da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_req(conn, skb);
854eb492e01SAnderson Briglia 		break;
855eb492e01SAnderson Briglia 
856eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_FAIL:
8574f957a76SBrian Gix 		smp_failure(conn, skb->data[0], 0);
858da85e5e5SVinicius Costa Gomes 		reason = 0;
859da85e5e5SVinicius Costa Gomes 		err = -EPERM;
860eb492e01SAnderson Briglia 		break;
861eb492e01SAnderson Briglia 
862eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RSP:
863da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_rsp(conn, skb);
86488ba43b6SAnderson Briglia 		break;
86588ba43b6SAnderson Briglia 
86688ba43b6SAnderson Briglia 	case SMP_CMD_SECURITY_REQ:
867da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_security_req(conn, skb);
86888ba43b6SAnderson Briglia 		break;
86988ba43b6SAnderson Briglia 
870eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_CONFIRM:
871da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_confirm(conn, skb);
87288ba43b6SAnderson Briglia 		break;
87388ba43b6SAnderson Briglia 
874eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RANDOM:
875da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_random(conn, skb);
87688ba43b6SAnderson Briglia 		break;
87788ba43b6SAnderson Briglia 
878eb492e01SAnderson Briglia 	case SMP_CMD_ENCRYPT_INFO:
8797034b911SVinicius Costa Gomes 		reason = smp_cmd_encrypt_info(conn, skb);
8807034b911SVinicius Costa Gomes 		break;
8817034b911SVinicius Costa Gomes 
882eb492e01SAnderson Briglia 	case SMP_CMD_MASTER_IDENT:
8837034b911SVinicius Costa Gomes 		reason = smp_cmd_master_ident(conn, skb);
8847034b911SVinicius Costa Gomes 		break;
8857034b911SVinicius Costa Gomes 
886eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_INFO:
887eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_ADDR_INFO:
888eb492e01SAnderson Briglia 	case SMP_CMD_SIGN_INFO:
8897034b911SVinicius Costa Gomes 		/* Just ignored */
8907034b911SVinicius Costa Gomes 		reason = 0;
8917034b911SVinicius Costa Gomes 		break;
8927034b911SVinicius Costa Gomes 
893eb492e01SAnderson Briglia 	default:
894eb492e01SAnderson Briglia 		BT_DBG("Unknown command code 0x%2.2x", code);
895eb492e01SAnderson Briglia 
896eb492e01SAnderson Briglia 		reason = SMP_CMD_NOTSUPP;
8973a0259bbSVinicius Costa Gomes 		err = -EOPNOTSUPP;
8983a0259bbSVinicius Costa Gomes 		goto done;
8993a0259bbSVinicius Costa Gomes 	}
9003a0259bbSVinicius Costa Gomes 
9013a0259bbSVinicius Costa Gomes done:
9023a0259bbSVinicius Costa Gomes 	if (reason)
9034f957a76SBrian Gix 		smp_failure(conn, reason, 1);
904eb492e01SAnderson Briglia 
905eb492e01SAnderson Briglia 	kfree_skb(skb);
906eb492e01SAnderson Briglia 	return err;
907eb492e01SAnderson Briglia }
9087034b911SVinicius Costa Gomes 
9097034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
9107034b911SVinicius Costa Gomes {
9117034b911SVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp;
9121c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
9137034b911SVinicius Costa Gomes 	__u8 *keydist;
9147034b911SVinicius Costa Gomes 
9157034b911SVinicius Costa Gomes 	BT_DBG("conn %p force %d", conn, force);
9167034b911SVinicius Costa Gomes 
91751a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
918d26a2345SVinicius Costa Gomes 		return 0;
919d26a2345SVinicius Costa Gomes 
9201c1def09SVinicius Costa Gomes 	rsp = (void *) &smp->prsp[1];
9217034b911SVinicius Costa Gomes 
9227034b911SVinicius Costa Gomes 	/* The responder sends its keys first */
9237034b911SVinicius Costa Gomes 	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
9247034b911SVinicius Costa Gomes 		return 0;
9257034b911SVinicius Costa Gomes 
9261c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
9277034b911SVinicius Costa Gomes 
9287034b911SVinicius Costa Gomes 	if (conn->hcon->out) {
9297034b911SVinicius Costa Gomes 		keydist = &rsp->init_key_dist;
9307034b911SVinicius Costa Gomes 		*keydist &= req->init_key_dist;
9317034b911SVinicius Costa Gomes 	} else {
9327034b911SVinicius Costa Gomes 		keydist = &rsp->resp_key_dist;
9337034b911SVinicius Costa Gomes 		*keydist &= req->resp_key_dist;
9347034b911SVinicius Costa Gomes 	}
9357034b911SVinicius Costa Gomes 
9367034b911SVinicius Costa Gomes 
9377034b911SVinicius Costa Gomes 	BT_DBG("keydist 0x%x", *keydist);
9387034b911SVinicius Costa Gomes 
9397034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ENC_KEY) {
9407034b911SVinicius Costa Gomes 		struct smp_cmd_encrypt_info enc;
9417034b911SVinicius Costa Gomes 		struct smp_cmd_master_ident ident;
942c9839a11SVinicius Costa Gomes 		struct hci_conn *hcon = conn->hcon;
943c9839a11SVinicius Costa Gomes 		u8 authenticated;
9447034b911SVinicius Costa Gomes 		__le16 ediv;
9457034b911SVinicius Costa Gomes 
9467034b911SVinicius Costa Gomes 		get_random_bytes(enc.ltk, sizeof(enc.ltk));
9477034b911SVinicius Costa Gomes 		get_random_bytes(&ediv, sizeof(ediv));
9487034b911SVinicius Costa Gomes 		get_random_bytes(ident.rand, sizeof(ident.rand));
9497034b911SVinicius Costa Gomes 
9507034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
9517034b911SVinicius Costa Gomes 
952c9839a11SVinicius Costa Gomes 		authenticated = hcon->sec_level == BT_SECURITY_HIGH;
953c9839a11SVinicius Costa Gomes 		hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
954c9839a11SVinicius Costa Gomes 			    HCI_SMP_LTK_SLAVE, 1, authenticated,
95504124681SGustavo F. Padovan 			    enc.ltk, smp->enc_key_size, ediv, ident.rand);
95616b90839SVinicius Costa Gomes 
9577034b911SVinicius Costa Gomes 		ident.ediv = cpu_to_le16(ediv);
9587034b911SVinicius Costa Gomes 
9597034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
9607034b911SVinicius Costa Gomes 
9617034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ENC_KEY;
9627034b911SVinicius Costa Gomes 	}
9637034b911SVinicius Costa Gomes 
9647034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ID_KEY) {
9657034b911SVinicius Costa Gomes 		struct smp_cmd_ident_addr_info addrinfo;
9667034b911SVinicius Costa Gomes 		struct smp_cmd_ident_info idinfo;
9677034b911SVinicius Costa Gomes 
9687034b911SVinicius Costa Gomes 		/* Send a dummy key */
9697034b911SVinicius Costa Gomes 		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
9707034b911SVinicius Costa Gomes 
9717034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
9727034b911SVinicius Costa Gomes 
9737034b911SVinicius Costa Gomes 		/* Just public address */
9747034b911SVinicius Costa Gomes 		memset(&addrinfo, 0, sizeof(addrinfo));
9757034b911SVinicius Costa Gomes 		bacpy(&addrinfo.bdaddr, conn->src);
9767034b911SVinicius Costa Gomes 
9777034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
9787034b911SVinicius Costa Gomes 								&addrinfo);
9797034b911SVinicius Costa Gomes 
9807034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ID_KEY;
9817034b911SVinicius Costa Gomes 	}
9827034b911SVinicius Costa Gomes 
9837034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_SIGN) {
9847034b911SVinicius Costa Gomes 		struct smp_cmd_sign_info sign;
9857034b911SVinicius Costa Gomes 
9867034b911SVinicius Costa Gomes 		/* Send a dummy key */
9877034b911SVinicius Costa Gomes 		get_random_bytes(sign.csrk, sizeof(sign.csrk));
9887034b911SVinicius Costa Gomes 
9897034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
9907034b911SVinicius Costa Gomes 
9917034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_SIGN;
9927034b911SVinicius Costa Gomes 	}
9937034b911SVinicius Costa Gomes 
994d26a2345SVinicius Costa Gomes 	if (conn->hcon->out || force) {
99551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
9966c9d42a1SGustavo F. Padovan 		cancel_delayed_work_sync(&conn->security_timer);
9978aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
998d26a2345SVinicius Costa Gomes 	}
999d26a2345SVinicius Costa Gomes 
10007034b911SVinicius Costa Gomes 	return 0;
10017034b911SVinicius Costa Gomes }
1002