xref: /openbmc/linux/net/bluetooth/smp.c (revision 06ae3314)
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>
31ac4b7236SMarcel Holtmann 
32ac4b7236SMarcel Holtmann #include "smp.h"
33d22ef0bcSAnderson Briglia 
3417b02e62SMarcel Holtmann #define SMP_TIMEOUT	msecs_to_jiffies(30000)
355d3de7dfSVinicius Costa Gomes 
36065a13e2SJohan Hedberg #define AUTH_REQ_MASK   0x07
37065a13e2SJohan Hedberg 
38d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16])
39d22ef0bcSAnderson Briglia {
40d22ef0bcSAnderson Briglia 	int i;
41d22ef0bcSAnderson Briglia 	for (i = 0; i < 16; i++)
42d22ef0bcSAnderson Briglia 		dst[15 - i] = src[i];
43d22ef0bcSAnderson Briglia }
44d22ef0bcSAnderson Briglia 
45d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7])
46d22ef0bcSAnderson Briglia {
47d22ef0bcSAnderson Briglia 	int i;
48d22ef0bcSAnderson Briglia 	for (i = 0; i < 7; i++)
49d22ef0bcSAnderson Briglia 		dst[6 - i] = src[i];
50d22ef0bcSAnderson Briglia }
51d22ef0bcSAnderson Briglia 
52d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
53d22ef0bcSAnderson Briglia {
54d22ef0bcSAnderson Briglia 	struct blkcipher_desc desc;
55d22ef0bcSAnderson Briglia 	struct scatterlist sg;
56d22ef0bcSAnderson Briglia 	int err, iv_len;
57d22ef0bcSAnderson Briglia 	unsigned char iv[128];
58d22ef0bcSAnderson Briglia 
59d22ef0bcSAnderson Briglia 	if (tfm == NULL) {
60d22ef0bcSAnderson Briglia 		BT_ERR("tfm %p", tfm);
61d22ef0bcSAnderson Briglia 		return -EINVAL;
62d22ef0bcSAnderson Briglia 	}
63d22ef0bcSAnderson Briglia 
64d22ef0bcSAnderson Briglia 	desc.tfm = tfm;
65d22ef0bcSAnderson Briglia 	desc.flags = 0;
66d22ef0bcSAnderson Briglia 
67d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_setkey(tfm, k, 16);
68d22ef0bcSAnderson Briglia 	if (err) {
69d22ef0bcSAnderson Briglia 		BT_ERR("cipher setkey failed: %d", err);
70d22ef0bcSAnderson Briglia 		return err;
71d22ef0bcSAnderson Briglia 	}
72d22ef0bcSAnderson Briglia 
73d22ef0bcSAnderson Briglia 	sg_init_one(&sg, r, 16);
74d22ef0bcSAnderson Briglia 
75d22ef0bcSAnderson Briglia 	iv_len = crypto_blkcipher_ivsize(tfm);
76d22ef0bcSAnderson Briglia 	if (iv_len) {
77d22ef0bcSAnderson Briglia 		memset(&iv, 0xff, iv_len);
78d22ef0bcSAnderson Briglia 		crypto_blkcipher_set_iv(tfm, iv, iv_len);
79d22ef0bcSAnderson Briglia 	}
80d22ef0bcSAnderson Briglia 
81d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
82d22ef0bcSAnderson Briglia 	if (err)
83d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error %d", err);
84d22ef0bcSAnderson Briglia 
85d22ef0bcSAnderson Briglia 	return err;
86d22ef0bcSAnderson Briglia }
87d22ef0bcSAnderson Briglia 
88d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
89d22ef0bcSAnderson Briglia 		  u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
90d22ef0bcSAnderson Briglia 		  u8 _rat, bdaddr_t *ra, u8 res[16])
91d22ef0bcSAnderson Briglia {
92d22ef0bcSAnderson Briglia 	u8 p1[16], p2[16];
93d22ef0bcSAnderson Briglia 	int err;
94d22ef0bcSAnderson Briglia 
95d22ef0bcSAnderson Briglia 	memset(p1, 0, 16);
96d22ef0bcSAnderson Briglia 
97d22ef0bcSAnderson Briglia 	/* p1 = pres || preq || _rat || _iat */
98d22ef0bcSAnderson Briglia 	swap56(pres, p1);
99d22ef0bcSAnderson Briglia 	swap56(preq, p1 + 7);
100d22ef0bcSAnderson Briglia 	p1[14] = _rat;
101d22ef0bcSAnderson Briglia 	p1[15] = _iat;
102d22ef0bcSAnderson Briglia 
103d22ef0bcSAnderson Briglia 	memset(p2, 0, 16);
104d22ef0bcSAnderson Briglia 
105d22ef0bcSAnderson Briglia 	/* p2 = padding || ia || ra */
106d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 4), ia);
107d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 10), ra);
108d22ef0bcSAnderson Briglia 
109d22ef0bcSAnderson Briglia 	/* res = r XOR p1 */
110d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
111d22ef0bcSAnderson Briglia 
112d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
113d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
114d22ef0bcSAnderson Briglia 	if (err) {
115d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
116d22ef0bcSAnderson Briglia 		return err;
117d22ef0bcSAnderson Briglia 	}
118d22ef0bcSAnderson Briglia 
119d22ef0bcSAnderson Briglia 	/* res = res XOR p2 */
120d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
121d22ef0bcSAnderson Briglia 
122d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
123d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
124d22ef0bcSAnderson Briglia 	if (err)
125d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
126d22ef0bcSAnderson Briglia 
127d22ef0bcSAnderson Briglia 	return err;
128d22ef0bcSAnderson Briglia }
129d22ef0bcSAnderson Briglia 
130f1560463SMarcel Holtmann static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
131f1560463SMarcel Holtmann 		  u8 r2[16], u8 _r[16])
132d22ef0bcSAnderson Briglia {
133d22ef0bcSAnderson Briglia 	int err;
134d22ef0bcSAnderson Briglia 
135d22ef0bcSAnderson Briglia 	/* Just least significant octets from r1 and r2 are considered */
136d22ef0bcSAnderson Briglia 	memcpy(_r, r1 + 8, 8);
137d22ef0bcSAnderson Briglia 	memcpy(_r + 8, r2 + 8, 8);
138d22ef0bcSAnderson Briglia 
139d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, _r);
140d22ef0bcSAnderson Briglia 	if (err)
141d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
142d22ef0bcSAnderson Briglia 
143d22ef0bcSAnderson Briglia 	return err;
144d22ef0bcSAnderson Briglia }
145d22ef0bcSAnderson Briglia 
146d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf)
147d22ef0bcSAnderson Briglia {
148d22ef0bcSAnderson Briglia 	get_random_bytes(buf, 16);
149d22ef0bcSAnderson Briglia 
150d22ef0bcSAnderson Briglia 	return 0;
151d22ef0bcSAnderson Briglia }
152eb492e01SAnderson Briglia 
153eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
154eb492e01SAnderson Briglia 				     u16 dlen, void *data)
155eb492e01SAnderson Briglia {
156eb492e01SAnderson Briglia 	struct sk_buff *skb;
157eb492e01SAnderson Briglia 	struct l2cap_hdr *lh;
158eb492e01SAnderson Briglia 	int len;
159eb492e01SAnderson Briglia 
160eb492e01SAnderson Briglia 	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
161eb492e01SAnderson Briglia 
162eb492e01SAnderson Briglia 	if (len > conn->mtu)
163eb492e01SAnderson Briglia 		return NULL;
164eb492e01SAnderson Briglia 
165eb492e01SAnderson Briglia 	skb = bt_skb_alloc(len, GFP_ATOMIC);
166eb492e01SAnderson Briglia 	if (!skb)
167eb492e01SAnderson Briglia 		return NULL;
168eb492e01SAnderson Briglia 
169eb492e01SAnderson Briglia 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
170eb492e01SAnderson Briglia 	lh->len = cpu_to_le16(sizeof(code) + dlen);
171d8aece2aSSyam Sidhardhan 	lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
172eb492e01SAnderson Briglia 
173eb492e01SAnderson Briglia 	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
174eb492e01SAnderson Briglia 
175eb492e01SAnderson Briglia 	memcpy(skb_put(skb, dlen), data, dlen);
176eb492e01SAnderson Briglia 
177eb492e01SAnderson Briglia 	return skb;
178eb492e01SAnderson Briglia }
179eb492e01SAnderson Briglia 
180eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
181eb492e01SAnderson Briglia {
182eb492e01SAnderson Briglia 	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
183eb492e01SAnderson Briglia 
184eb492e01SAnderson Briglia 	BT_DBG("code 0x%2.2x", code);
185eb492e01SAnderson Briglia 
186eb492e01SAnderson Briglia 	if (!skb)
187eb492e01SAnderson Briglia 		return;
188eb492e01SAnderson Briglia 
18973d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
19073d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, 0);
191e2dcd113SVinicius Costa Gomes 
1926c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
19317b02e62SMarcel Holtmann 	schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
194eb492e01SAnderson Briglia }
195eb492e01SAnderson Briglia 
1962b64d153SBrian Gix static __u8 authreq_to_seclevel(__u8 authreq)
1972b64d153SBrian Gix {
1982b64d153SBrian Gix 	if (authreq & SMP_AUTH_MITM)
1992b64d153SBrian Gix 		return BT_SECURITY_HIGH;
2002b64d153SBrian Gix 	else
2012b64d153SBrian Gix 		return BT_SECURITY_MEDIUM;
2022b64d153SBrian Gix }
2032b64d153SBrian Gix 
2042b64d153SBrian Gix static __u8 seclevel_to_authreq(__u8 sec_level)
2052b64d153SBrian Gix {
2062b64d153SBrian Gix 	switch (sec_level) {
2072b64d153SBrian Gix 	case BT_SECURITY_HIGH:
2082b64d153SBrian Gix 		return SMP_AUTH_MITM | SMP_AUTH_BONDING;
2092b64d153SBrian Gix 	case BT_SECURITY_MEDIUM:
2102b64d153SBrian Gix 		return SMP_AUTH_BONDING;
2112b64d153SBrian Gix 	default:
2122b64d153SBrian Gix 		return SMP_AUTH_NONE;
2132b64d153SBrian Gix 	}
2142b64d153SBrian Gix }
2152b64d153SBrian Gix 
216b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn,
21754790f73SVinicius Costa Gomes 			      struct smp_cmd_pairing *req,
218f1560463SMarcel Holtmann 			      struct smp_cmd_pairing *rsp, __u8 authreq)
219b8e66eacSVinicius Costa Gomes {
2202b64d153SBrian Gix 	u8 dist_keys = 0;
22154790f73SVinicius Costa Gomes 
222a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
223ca10b5eeSVinicius Costa Gomes 		dist_keys = SMP_DIST_ENC_KEY;
22454790f73SVinicius Costa Gomes 		authreq |= SMP_AUTH_BONDING;
2252b64d153SBrian Gix 	} else {
2262b64d153SBrian Gix 		authreq &= ~SMP_AUTH_BONDING;
22754790f73SVinicius Costa Gomes 	}
22854790f73SVinicius Costa Gomes 
22954790f73SVinicius Costa Gomes 	if (rsp == NULL) {
23054790f73SVinicius Costa Gomes 		req->io_capability = conn->hcon->io_capability;
23154790f73SVinicius Costa Gomes 		req->oob_flag = SMP_OOB_NOT_PRESENT;
23254790f73SVinicius Costa Gomes 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2332b64d153SBrian Gix 		req->init_key_dist = 0;
23454790f73SVinicius Costa Gomes 		req->resp_key_dist = dist_keys;
235065a13e2SJohan Hedberg 		req->auth_req = (authreq & AUTH_REQ_MASK);
23654790f73SVinicius Costa Gomes 		return;
23754790f73SVinicius Costa Gomes 	}
23854790f73SVinicius Costa Gomes 
23954790f73SVinicius Costa Gomes 	rsp->io_capability = conn->hcon->io_capability;
24054790f73SVinicius Costa Gomes 	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
24154790f73SVinicius Costa Gomes 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2422b64d153SBrian Gix 	rsp->init_key_dist = 0;
24354790f73SVinicius Costa Gomes 	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
244065a13e2SJohan Hedberg 	rsp->auth_req = (authreq & AUTH_REQ_MASK);
245b8e66eacSVinicius Costa Gomes }
246b8e66eacSVinicius Costa Gomes 
2473158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
2483158c50cSVinicius Costa Gomes {
2491c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
2501c1def09SVinicius Costa Gomes 
2513158c50cSVinicius Costa Gomes 	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
2523158c50cSVinicius Costa Gomes 	    (max_key_size < SMP_MIN_ENC_KEY_SIZE))
2533158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
2543158c50cSVinicius Costa Gomes 
255f7aa611aSVinicius Costa Gomes 	smp->enc_key_size = max_key_size;
2563158c50cSVinicius Costa Gomes 
2573158c50cSVinicius Costa Gomes 	return 0;
2583158c50cSVinicius Costa Gomes }
2593158c50cSVinicius Costa Gomes 
2604f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
2614f957a76SBrian Gix {
262bab73cb6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
263bab73cb6SJohan Hedberg 
2644f957a76SBrian Gix 	if (send)
2654f957a76SBrian Gix 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
2664f957a76SBrian Gix 			     &reason);
2674f957a76SBrian Gix 
268ce39fb4eSMarcel Holtmann 	clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
269ce39fb4eSMarcel Holtmann 	mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
270ce39fb4eSMarcel Holtmann 			 HCI_ERROR_AUTH_FAILURE);
271f1c09c07SVinicius Costa Gomes 
2726c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
27361a0cfb0SAndre Guedes 
274ce39fb4eSMarcel Holtmann 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
2754f957a76SBrian Gix 		smp_chan_destroy(conn);
2764f957a76SBrian Gix }
2774f957a76SBrian Gix 
2782b64d153SBrian Gix #define JUST_WORKS	0x00
2792b64d153SBrian Gix #define JUST_CFM	0x01
2802b64d153SBrian Gix #define REQ_PASSKEY	0x02
2812b64d153SBrian Gix #define CFM_PASSKEY	0x03
2822b64d153SBrian Gix #define REQ_OOB		0x04
2832b64d153SBrian Gix #define OVERLAP		0xFF
2842b64d153SBrian Gix 
2852b64d153SBrian Gix static const u8 gen_method[5][5] = {
2862b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
2872b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
2882b64d153SBrian Gix 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
2892b64d153SBrian Gix 	{ JUST_WORKS,  JUST_CFM,    JUST_WORKS,  JUST_WORKS, JUST_CFM    },
2902b64d153SBrian Gix 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP     },
2912b64d153SBrian Gix };
2922b64d153SBrian Gix 
2932b64d153SBrian Gix static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
2942b64d153SBrian Gix 						u8 local_io, u8 remote_io)
2952b64d153SBrian Gix {
2962b64d153SBrian Gix 	struct hci_conn *hcon = conn->hcon;
2972b64d153SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
2982b64d153SBrian Gix 	u8 method;
2992b64d153SBrian Gix 	u32 passkey = 0;
3002b64d153SBrian Gix 	int ret = 0;
3012b64d153SBrian Gix 
3022b64d153SBrian Gix 	/* Initialize key for JUST WORKS */
3032b64d153SBrian Gix 	memset(smp->tk, 0, sizeof(smp->tk));
3042b64d153SBrian Gix 	clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
3052b64d153SBrian Gix 
3062b64d153SBrian Gix 	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
3072b64d153SBrian Gix 
3082b64d153SBrian Gix 	/* If neither side wants MITM, use JUST WORKS */
3092b64d153SBrian Gix 	/* If either side has unknown io_caps, use JUST WORKS */
3102b64d153SBrian Gix 	/* Otherwise, look up method from the table */
3112b64d153SBrian Gix 	if (!(auth & SMP_AUTH_MITM) ||
3122b64d153SBrian Gix 	    local_io > SMP_IO_KEYBOARD_DISPLAY ||
3132b64d153SBrian Gix 	    remote_io > SMP_IO_KEYBOARD_DISPLAY)
3142b64d153SBrian Gix 		method = JUST_WORKS;
3152b64d153SBrian Gix 	else
316b3ff53ffSIdo Yariv 		method = gen_method[remote_io][local_io];
3172b64d153SBrian Gix 
3182b64d153SBrian Gix 	/* If not bonding, don't ask user to confirm a Zero TK */
3192b64d153SBrian Gix 	if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
3202b64d153SBrian Gix 		method = JUST_WORKS;
3212b64d153SBrian Gix 
3222b64d153SBrian Gix 	/* If Just Works, Continue with Zero TK */
3232b64d153SBrian Gix 	if (method == JUST_WORKS) {
3242b64d153SBrian Gix 		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
3252b64d153SBrian Gix 		return 0;
3262b64d153SBrian Gix 	}
3272b64d153SBrian Gix 
3282b64d153SBrian Gix 	/* Not Just Works/Confirm results in MITM Authentication */
3292b64d153SBrian Gix 	if (method != JUST_CFM)
3302b64d153SBrian Gix 		set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
3312b64d153SBrian Gix 
3322b64d153SBrian Gix 	/* If both devices have Keyoard-Display I/O, the master
3332b64d153SBrian Gix 	 * Confirms and the slave Enters the passkey.
3342b64d153SBrian Gix 	 */
3352b64d153SBrian Gix 	if (method == OVERLAP) {
3362b64d153SBrian Gix 		if (hcon->link_mode & HCI_LM_MASTER)
3372b64d153SBrian Gix 			method = CFM_PASSKEY;
3382b64d153SBrian Gix 		else
3392b64d153SBrian Gix 			method = REQ_PASSKEY;
3402b64d153SBrian Gix 	}
3412b64d153SBrian Gix 
3422b64d153SBrian Gix 	/* Generate random passkey. Not valid until confirmed. */
3432b64d153SBrian Gix 	if (method == CFM_PASSKEY) {
3442b64d153SBrian Gix 		u8 key[16];
3452b64d153SBrian Gix 
3462b64d153SBrian Gix 		memset(key, 0, sizeof(key));
3472b64d153SBrian Gix 		get_random_bytes(&passkey, sizeof(passkey));
3482b64d153SBrian Gix 		passkey %= 1000000;
3492b64d153SBrian Gix 		put_unaligned_le32(passkey, key);
3502b64d153SBrian Gix 		swap128(key, smp->tk);
3512b64d153SBrian Gix 		BT_DBG("PassKey: %d", passkey);
3522b64d153SBrian Gix 	}
3532b64d153SBrian Gix 
3542b64d153SBrian Gix 	hci_dev_lock(hcon->hdev);
3552b64d153SBrian Gix 
3562b64d153SBrian Gix 	if (method == REQ_PASSKEY)
357ce39fb4eSMarcel Holtmann 		ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
358272d90dfSJohan Hedberg 						hcon->type, hcon->dst_type);
3592b64d153SBrian Gix 	else
360ce39fb4eSMarcel Holtmann 		ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
361272d90dfSJohan Hedberg 						hcon->type, hcon->dst_type,
3622b64d153SBrian Gix 						cpu_to_le32(passkey), 0);
3632b64d153SBrian Gix 
3642b64d153SBrian Gix 	hci_dev_unlock(hcon->hdev);
3652b64d153SBrian Gix 
3662b64d153SBrian Gix 	return ret;
3672b64d153SBrian Gix }
3682b64d153SBrian Gix 
3698aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work)
3708aab4757SVinicius Costa Gomes {
3718aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
3728aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
3738aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm;
3748aab4757SVinicius Costa Gomes 	struct smp_cmd_pairing_confirm cp;
3758aab4757SVinicius Costa Gomes 	int ret;
3768aab4757SVinicius Costa Gomes 	u8 res[16], reason;
3778aab4757SVinicius Costa Gomes 
3788aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
3798aab4757SVinicius Costa Gomes 
3808aab4757SVinicius Costa Gomes 	tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
3818aab4757SVinicius Costa Gomes 	if (IS_ERR(tfm)) {
3828aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3838aab4757SVinicius Costa Gomes 		goto error;
3848aab4757SVinicius Costa Gomes 	}
3858aab4757SVinicius Costa Gomes 
3868aab4757SVinicius Costa Gomes 	smp->tfm = tfm;
3878aab4757SVinicius Costa Gomes 
3888aab4757SVinicius Costa Gomes 	if (conn->hcon->out)
389c8462ca6SMarcel Holtmann 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
390c8462ca6SMarcel Holtmann 			     conn->hcon->src_type, &conn->hcon->src,
391c8462ca6SMarcel Holtmann 			     conn->hcon->dst_type, &conn->hcon->dst, res);
3928aab4757SVinicius Costa Gomes 	else
3938aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
394c8462ca6SMarcel Holtmann 			     conn->hcon->dst_type, &conn->hcon->dst,
395c8462ca6SMarcel Holtmann 			     conn->hcon->src_type, &conn->hcon->src, res);
3968aab4757SVinicius Costa Gomes 	if (ret) {
3978aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3988aab4757SVinicius Costa Gomes 		goto error;
3998aab4757SVinicius Costa Gomes 	}
4008aab4757SVinicius Costa Gomes 
4012b64d153SBrian Gix 	clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
4022b64d153SBrian Gix 
4038aab4757SVinicius Costa Gomes 	swap128(res, cp.confirm_val);
4048aab4757SVinicius Costa Gomes 	smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
4058aab4757SVinicius Costa Gomes 
4068aab4757SVinicius Costa Gomes 	return;
4078aab4757SVinicius Costa Gomes 
4088aab4757SVinicius Costa Gomes error:
4094f957a76SBrian Gix 	smp_failure(conn, reason, 1);
4108aab4757SVinicius Costa Gomes }
4118aab4757SVinicius Costa Gomes 
4128aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work)
4138aab4757SVinicius Costa Gomes {
4148aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, random);
4158aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
4168aab4757SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
4178aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm = smp->tfm;
4188aab4757SVinicius Costa Gomes 	u8 reason, confirm[16], res[16], key[16];
4198aab4757SVinicius Costa Gomes 	int ret;
4208aab4757SVinicius Costa Gomes 
4218aab4757SVinicius Costa Gomes 	if (IS_ERR_OR_NULL(tfm)) {
4228aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
4238aab4757SVinicius Costa Gomes 		goto error;
4248aab4757SVinicius Costa Gomes 	}
4258aab4757SVinicius Costa Gomes 
4268aab4757SVinicius Costa Gomes 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
4278aab4757SVinicius Costa Gomes 
4288aab4757SVinicius Costa Gomes 	if (hcon->out)
429c8462ca6SMarcel Holtmann 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
430c8462ca6SMarcel Holtmann 			     hcon->src_type, &hcon->src,
431c8462ca6SMarcel Holtmann 			     hcon->dst_type, &hcon->dst, res);
4328aab4757SVinicius Costa Gomes 	else
4338aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
434c8462ca6SMarcel Holtmann 			     hcon->dst_type, &hcon->dst,
435c8462ca6SMarcel Holtmann 			     hcon->src_type, &hcon->src, res);
4368aab4757SVinicius Costa Gomes 	if (ret) {
4378aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
4388aab4757SVinicius Costa Gomes 		goto error;
4398aab4757SVinicius Costa Gomes 	}
4408aab4757SVinicius Costa Gomes 
4418aab4757SVinicius Costa Gomes 	swap128(res, confirm);
4428aab4757SVinicius Costa Gomes 
4438aab4757SVinicius Costa Gomes 	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
4448aab4757SVinicius Costa Gomes 		BT_ERR("Pairing failed (confirmation values mismatch)");
4458aab4757SVinicius Costa Gomes 		reason = SMP_CONFIRM_FAILED;
4468aab4757SVinicius Costa Gomes 		goto error;
4478aab4757SVinicius Costa Gomes 	}
4488aab4757SVinicius Costa Gomes 
4498aab4757SVinicius Costa Gomes 	if (hcon->out) {
4508aab4757SVinicius Costa Gomes 		u8 stk[16], rand[8];
4518aab4757SVinicius Costa Gomes 		__le16 ediv;
4528aab4757SVinicius Costa Gomes 
4538aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
4548aab4757SVinicius Costa Gomes 		ediv = 0;
4558aab4757SVinicius Costa Gomes 
4568aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
4578aab4757SVinicius Costa Gomes 		swap128(key, stk);
4588aab4757SVinicius Costa Gomes 
459f7aa611aSVinicius Costa Gomes 		memset(stk + smp->enc_key_size, 0,
460f7aa611aSVinicius Costa Gomes 		       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
4618aab4757SVinicius Costa Gomes 
46251a8efd7SJohan Hedberg 		if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
4638aab4757SVinicius Costa Gomes 			reason = SMP_UNSPECIFIED;
4648aab4757SVinicius Costa Gomes 			goto error;
4658aab4757SVinicius Costa Gomes 		}
4668aab4757SVinicius Costa Gomes 
4678aab4757SVinicius Costa Gomes 		hci_le_start_enc(hcon, ediv, rand, stk);
468f7aa611aSVinicius Costa Gomes 		hcon->enc_key_size = smp->enc_key_size;
4698aab4757SVinicius Costa Gomes 	} else {
4708aab4757SVinicius Costa Gomes 		u8 stk[16], r[16], rand[8];
4718aab4757SVinicius Costa Gomes 		__le16 ediv;
4728aab4757SVinicius Costa Gomes 
4738aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
4748aab4757SVinicius Costa Gomes 		ediv = 0;
4758aab4757SVinicius Costa Gomes 
4768aab4757SVinicius Costa Gomes 		swap128(smp->prnd, r);
4778aab4757SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
4788aab4757SVinicius Costa Gomes 
4798aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
4808aab4757SVinicius Costa Gomes 		swap128(key, stk);
4818aab4757SVinicius Costa Gomes 
482f7aa611aSVinicius Costa Gomes 		memset(stk + smp->enc_key_size, 0,
483f7aa611aSVinicius Costa Gomes 		       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
4848aab4757SVinicius Costa Gomes 
485ce39fb4eSMarcel Holtmann 		hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
48604124681SGustavo F. Padovan 			    HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
48704124681SGustavo F. Padovan 			    ediv, rand);
4888aab4757SVinicius Costa Gomes 	}
4898aab4757SVinicius Costa Gomes 
4908aab4757SVinicius Costa Gomes 	return;
4918aab4757SVinicius Costa Gomes 
4928aab4757SVinicius Costa Gomes error:
4934f957a76SBrian Gix 	smp_failure(conn, reason, 1);
4948aab4757SVinicius Costa Gomes }
4958aab4757SVinicius Costa Gomes 
4968aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
4978aab4757SVinicius Costa Gomes {
4988aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
4998aab4757SVinicius Costa Gomes 
500f1560463SMarcel Holtmann 	smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
5018aab4757SVinicius Costa Gomes 	if (!smp)
5028aab4757SVinicius Costa Gomes 		return NULL;
5038aab4757SVinicius Costa Gomes 
5048aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->confirm, confirm_work);
5058aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->random, random_work);
5068aab4757SVinicius Costa Gomes 
5078aab4757SVinicius Costa Gomes 	smp->conn = conn;
5088aab4757SVinicius Costa Gomes 	conn->smp_chan = smp;
5092b64d153SBrian Gix 	conn->hcon->smp_conn = conn;
5108aab4757SVinicius Costa Gomes 
5118aab4757SVinicius Costa Gomes 	hci_conn_hold(conn->hcon);
5128aab4757SVinicius Costa Gomes 
5138aab4757SVinicius Costa Gomes 	return smp;
5148aab4757SVinicius Costa Gomes }
5158aab4757SVinicius Costa Gomes 
5168aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn)
5178aab4757SVinicius Costa Gomes {
518c8eb9690SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
519c8eb9690SBrian Gix 
520f1c09c07SVinicius Costa Gomes 	BUG_ON(!smp);
521c8eb9690SBrian Gix 
522c8eb9690SBrian Gix 	if (smp->tfm)
523c8eb9690SBrian Gix 		crypto_free_blkcipher(smp->tfm);
524c8eb9690SBrian Gix 
525c8eb9690SBrian Gix 	kfree(smp);
526c8eb9690SBrian Gix 	conn->smp_chan = NULL;
5272b64d153SBrian Gix 	conn->hcon->smp_conn = NULL;
52876a68ba0SDavid Herrmann 	hci_conn_drop(conn->hcon);
5298aab4757SVinicius Costa Gomes }
5308aab4757SVinicius Costa Gomes 
5312b64d153SBrian Gix int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
5322b64d153SBrian Gix {
5332b64d153SBrian Gix 	struct l2cap_conn *conn = hcon->smp_conn;
5342b64d153SBrian Gix 	struct smp_chan *smp;
5352b64d153SBrian Gix 	u32 value;
5362b64d153SBrian Gix 	u8 key[16];
5372b64d153SBrian Gix 
5382b64d153SBrian Gix 	BT_DBG("");
5392b64d153SBrian Gix 
5402b64d153SBrian Gix 	if (!conn)
5412b64d153SBrian Gix 		return -ENOTCONN;
5422b64d153SBrian Gix 
5432b64d153SBrian Gix 	smp = conn->smp_chan;
5442b64d153SBrian Gix 
5452b64d153SBrian Gix 	switch (mgmt_op) {
5462b64d153SBrian Gix 	case MGMT_OP_USER_PASSKEY_REPLY:
5472b64d153SBrian Gix 		value = le32_to_cpu(passkey);
5482b64d153SBrian Gix 		memset(key, 0, sizeof(key));
5492b64d153SBrian Gix 		BT_DBG("PassKey: %d", value);
5502b64d153SBrian Gix 		put_unaligned_le32(value, key);
5512b64d153SBrian Gix 		swap128(key, smp->tk);
5522b64d153SBrian Gix 		/* Fall Through */
5532b64d153SBrian Gix 	case MGMT_OP_USER_CONFIRM_REPLY:
5542b64d153SBrian Gix 		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
5552b64d153SBrian Gix 		break;
5562b64d153SBrian Gix 	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
5572b64d153SBrian Gix 	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
5582b64d153SBrian Gix 		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
5592b64d153SBrian Gix 		return 0;
5602b64d153SBrian Gix 	default:
5612b64d153SBrian Gix 		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
5622b64d153SBrian Gix 		return -EOPNOTSUPP;
5632b64d153SBrian Gix 	}
5642b64d153SBrian Gix 
5652b64d153SBrian Gix 	/* If it is our turn to send Pairing Confirm, do so now */
5662b64d153SBrian Gix 	if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
5672b64d153SBrian Gix 		queue_work(hcon->hdev->workqueue, &smp->confirm);
5682b64d153SBrian Gix 
5692b64d153SBrian Gix 	return 0;
5702b64d153SBrian Gix }
5712b64d153SBrian Gix 
572da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
57388ba43b6SAnderson Briglia {
5743158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
5758aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
5763158c50cSVinicius Costa Gomes 	u8 key_size;
5772b64d153SBrian Gix 	u8 auth = SMP_AUTH_NONE;
5788aab4757SVinicius Costa Gomes 	int ret;
57988ba43b6SAnderson Briglia 
58088ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
58188ba43b6SAnderson Briglia 
5822b64d153SBrian Gix 	if (conn->hcon->link_mode & HCI_LM_MASTER)
5832b64d153SBrian Gix 		return SMP_CMD_NOTSUPP;
5842b64d153SBrian Gix 
58551a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
5868aab4757SVinicius Costa Gomes 		smp = smp_chan_create(conn);
587d08fd0e7SAndrei Emeltchenko 	else
5888aab4757SVinicius Costa Gomes 		smp = conn->smp_chan;
589d26a2345SVinicius Costa Gomes 
590d08fd0e7SAndrei Emeltchenko 	if (!smp)
591d08fd0e7SAndrei Emeltchenko 		return SMP_UNSPECIFIED;
592d08fd0e7SAndrei Emeltchenko 
5931c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
5941c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], req, sizeof(*req));
5953158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*req));
59688ba43b6SAnderson Briglia 
5972b64d153SBrian Gix 	/* We didn't start the pairing, so match remote */
5982b64d153SBrian Gix 	if (req->auth_req & SMP_AUTH_BONDING)
5992b64d153SBrian Gix 		auth = req->auth_req;
600da85e5e5SVinicius Costa Gomes 
601fdde0a26SIdo Yariv 	conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
602fdde0a26SIdo Yariv 
6032b64d153SBrian Gix 	build_pairing_cmd(conn, req, &rsp, auth);
6043158c50cSVinicius Costa Gomes 
6053158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp.max_key_size);
6063158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
6073158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
60888ba43b6SAnderson Briglia 
6098aab4757SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
6108aab4757SVinicius Costa Gomes 	if (ret)
6118aab4757SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
6128aab4757SVinicius Costa Gomes 
6131c1def09SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
6141c1def09SVinicius Costa Gomes 	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
615f01ead31SAnderson Briglia 
6163158c50cSVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
617da85e5e5SVinicius Costa Gomes 
6182b64d153SBrian Gix 	/* Request setup of TK */
6192b64d153SBrian Gix 	ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
6202b64d153SBrian Gix 	if (ret)
6212b64d153SBrian Gix 		return SMP_UNSPECIFIED;
6222b64d153SBrian Gix 
623da85e5e5SVinicius Costa Gomes 	return 0;
62488ba43b6SAnderson Briglia }
62588ba43b6SAnderson Briglia 
626da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
62788ba43b6SAnderson Briglia {
6283158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
6291c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6308aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6312b64d153SBrian Gix 	u8 key_size, auth = SMP_AUTH_NONE;
6327d24ddccSAnderson Briglia 	int ret;
63388ba43b6SAnderson Briglia 
63488ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
63588ba43b6SAnderson Briglia 
6362b64d153SBrian Gix 	if (!(conn->hcon->link_mode & HCI_LM_MASTER))
6372b64d153SBrian Gix 		return SMP_CMD_NOTSUPP;
6382b64d153SBrian Gix 
6393158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*rsp));
640da85e5e5SVinicius Costa Gomes 
6411c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
6423158c50cSVinicius Costa Gomes 
6433158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp->max_key_size);
6443158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
6453158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
6463158c50cSVinicius Costa Gomes 
6471c1def09SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
6487d24ddccSAnderson Briglia 	if (ret)
649da85e5e5SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
6507d24ddccSAnderson Briglia 
6518aab4757SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
6528aab4757SVinicius Costa Gomes 	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
6537d24ddccSAnderson Briglia 
6542b64d153SBrian Gix 	if ((req->auth_req & SMP_AUTH_BONDING) &&
6552b64d153SBrian Gix 	    (rsp->auth_req & SMP_AUTH_BONDING))
6562b64d153SBrian Gix 		auth = SMP_AUTH_BONDING;
6572b64d153SBrian Gix 
6582b64d153SBrian Gix 	auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
6592b64d153SBrian Gix 
660476585ecSJohan Hedberg 	ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
6612b64d153SBrian Gix 	if (ret)
6622b64d153SBrian Gix 		return SMP_UNSPECIFIED;
6632b64d153SBrian Gix 
6642b64d153SBrian Gix 	set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
6652b64d153SBrian Gix 
6662b64d153SBrian Gix 	/* Can't compose response until we have been confirmed */
6672b64d153SBrian Gix 	if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
6682b64d153SBrian Gix 		return 0;
6692b64d153SBrian Gix 
6708aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->confirm);
671da85e5e5SVinicius Costa Gomes 
672da85e5e5SVinicius Costa Gomes 	return 0;
67388ba43b6SAnderson Briglia }
67488ba43b6SAnderson Briglia 
675da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
67688ba43b6SAnderson Briglia {
6771c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6788aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
6797d24ddccSAnderson Briglia 
68088ba43b6SAnderson Briglia 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
68188ba43b6SAnderson Briglia 
6821c1def09SVinicius Costa Gomes 	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
6831c1def09SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->pcnf));
6847d24ddccSAnderson Briglia 
68588ba43b6SAnderson Briglia 	if (conn->hcon->out) {
6867d24ddccSAnderson Briglia 		u8 random[16];
68788ba43b6SAnderson Briglia 
6881c1def09SVinicius Costa Gomes 		swap128(smp->prnd, random);
68988ba43b6SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
6907d24ddccSAnderson Briglia 			     random);
6912b64d153SBrian Gix 	} else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
6928aab4757SVinicius Costa Gomes 		queue_work(hdev->workqueue, &smp->confirm);
6932b64d153SBrian Gix 	} else {
6942b64d153SBrian Gix 		set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
69588ba43b6SAnderson Briglia 	}
696da85e5e5SVinicius Costa Gomes 
697da85e5e5SVinicius Costa Gomes 	return 0;
69888ba43b6SAnderson Briglia }
69988ba43b6SAnderson Briglia 
700da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
70188ba43b6SAnderson Briglia {
7021c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7038aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
7047d24ddccSAnderson Briglia 
7058aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
7067d24ddccSAnderson Briglia 
7078aab4757SVinicius Costa Gomes 	swap128(skb->data, smp->rrnd);
7088aab4757SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->rrnd));
70988ba43b6SAnderson Briglia 
7108aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->random);
711da85e5e5SVinicius Costa Gomes 
712da85e5e5SVinicius Costa Gomes 	return 0;
71388ba43b6SAnderson Briglia }
71488ba43b6SAnderson Briglia 
7154dab7864SJohan Hedberg static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
716988c5997SVinicius Costa Gomes {
717c9839a11SVinicius Costa Gomes 	struct smp_ltk *key;
718988c5997SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
719988c5997SVinicius Costa Gomes 
720ce39fb4eSMarcel Holtmann 	key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type);
721988c5997SVinicius Costa Gomes 	if (!key)
722988c5997SVinicius Costa Gomes 		return 0;
723988c5997SVinicius Costa Gomes 
7244dab7864SJohan Hedberg 	if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
7254dab7864SJohan Hedberg 		return 0;
7264dab7864SJohan Hedberg 
72751a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
728988c5997SVinicius Costa Gomes 		return 1;
729988c5997SVinicius Costa Gomes 
730c9839a11SVinicius Costa Gomes 	hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
731c9839a11SVinicius Costa Gomes 	hcon->enc_key_size = key->enc_size;
732988c5997SVinicius Costa Gomes 
733988c5997SVinicius Costa Gomes 	return 1;
734988c5997SVinicius Costa Gomes }
735f1560463SMarcel Holtmann 
736da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
73788ba43b6SAnderson Briglia {
73888ba43b6SAnderson Briglia 	struct smp_cmd_security_req *rp = (void *) skb->data;
73988ba43b6SAnderson Briglia 	struct smp_cmd_pairing cp;
740f1cb9af5SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
7418aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
74288ba43b6SAnderson Briglia 
74388ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
74488ba43b6SAnderson Briglia 
7452b64d153SBrian Gix 	hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
746feb45eb5SVinicius Costa Gomes 
7474dab7864SJohan Hedberg 	if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
748988c5997SVinicius Costa Gomes 		return 0;
749988c5997SVinicius Costa Gomes 
75051a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
751da85e5e5SVinicius Costa Gomes 		return 0;
752f1cb9af5SVinicius Costa Gomes 
7538aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
754d26a2345SVinicius Costa Gomes 
75588ba43b6SAnderson Briglia 	skb_pull(skb, sizeof(*rp));
75688ba43b6SAnderson Briglia 
757da85e5e5SVinicius Costa Gomes 	memset(&cp, 0, sizeof(cp));
75854790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
75988ba43b6SAnderson Briglia 
7601c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
7611c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], &cp, sizeof(cp));
762f01ead31SAnderson Briglia 
76388ba43b6SAnderson Briglia 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
764f1cb9af5SVinicius Costa Gomes 
765da85e5e5SVinicius Costa Gomes 	return 0;
76688ba43b6SAnderson Briglia }
76788ba43b6SAnderson Briglia 
768cc110922SVinicius Costa Gomes int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
769eb492e01SAnderson Briglia {
770cc110922SVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
7711c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7722b64d153SBrian Gix 	__u8 authreq;
773eb492e01SAnderson Briglia 
7743a0259bbSVinicius Costa Gomes 	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
7753a0259bbSVinicius Costa Gomes 
776757aee0fSJohan Hedberg 	if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
7772e65c9d2SAndre Guedes 		return 1;
7782e65c9d2SAndre Guedes 
779f1cb9af5SVinicius Costa Gomes 	if (sec_level == BT_SECURITY_LOW)
780eb492e01SAnderson Briglia 		return 1;
781f1cb9af5SVinicius Costa Gomes 
782f1cb9af5SVinicius Costa Gomes 	if (hcon->sec_level >= sec_level)
783f1cb9af5SVinicius Costa Gomes 		return 1;
784f1cb9af5SVinicius Costa Gomes 
785988c5997SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER)
7864dab7864SJohan Hedberg 		if (smp_ltk_encrypt(conn, sec_level))
787d26a2345SVinicius Costa Gomes 			goto done;
788d26a2345SVinicius Costa Gomes 
78951a8efd7SJohan Hedberg 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
790d26a2345SVinicius Costa Gomes 		return 0;
791d26a2345SVinicius Costa Gomes 
7928aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
7932b64d153SBrian Gix 	if (!smp)
7942b64d153SBrian Gix 		return 1;
7952b64d153SBrian Gix 
7962b64d153SBrian Gix 	authreq = seclevel_to_authreq(sec_level);
797d26a2345SVinicius Costa Gomes 
798d26a2345SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER) {
799d26a2345SVinicius Costa Gomes 		struct smp_cmd_pairing cp;
800f01ead31SAnderson Briglia 
8012b64d153SBrian Gix 		build_pairing_cmd(conn, &cp, NULL, authreq);
8021c1def09SVinicius Costa Gomes 		smp->preq[0] = SMP_CMD_PAIRING_REQ;
8031c1def09SVinicius Costa Gomes 		memcpy(&smp->preq[1], &cp, sizeof(cp));
804f01ead31SAnderson Briglia 
805eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
806eb492e01SAnderson Briglia 	} else {
807eb492e01SAnderson Briglia 		struct smp_cmd_security_req cp;
8082b64d153SBrian Gix 		cp.auth_req = authreq;
809eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
810eb492e01SAnderson Briglia 	}
811eb492e01SAnderson Briglia 
81202bc7455SVinicius Costa Gomes done:
813f1cb9af5SVinicius Costa Gomes 	hcon->pending_sec_level = sec_level;
814f1cb9af5SVinicius Costa Gomes 
815eb492e01SAnderson Briglia 	return 0;
816eb492e01SAnderson Briglia }
817eb492e01SAnderson Briglia 
8187034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
8197034b911SVinicius Costa Gomes {
82016b90839SVinicius Costa Gomes 	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
8211c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
82216b90839SVinicius Costa Gomes 
82316b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
82416b90839SVinicius Costa Gomes 
8251c1def09SVinicius Costa Gomes 	memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
82616b90839SVinicius Costa Gomes 
8277034b911SVinicius Costa Gomes 	return 0;
8287034b911SVinicius Costa Gomes }
8297034b911SVinicius Costa Gomes 
8307034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
8317034b911SVinicius Costa Gomes {
83216b90839SVinicius Costa Gomes 	struct smp_cmd_master_ident *rp = (void *) skb->data;
8331c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
834c9839a11SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
835c9839a11SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
836c9839a11SVinicius Costa Gomes 	u8 authenticated;
8377034b911SVinicius Costa Gomes 
83816b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
83916b90839SVinicius Costa Gomes 
840c9839a11SVinicius Costa Gomes 	hci_dev_lock(hdev);
841ce39fb4eSMarcel Holtmann 	authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
842ce39fb4eSMarcel Holtmann 	hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
843ce39fb4eSMarcel Holtmann 		    authenticated, smp->tk, smp->enc_key_size,
84404124681SGustavo F. Padovan 		    rp->ediv, rp->rand);
8457034b911SVinicius Costa Gomes 	smp_distribute_keys(conn, 1);
846c9839a11SVinicius Costa Gomes 	hci_dev_unlock(hdev);
8477034b911SVinicius Costa Gomes 
8487034b911SVinicius Costa Gomes 	return 0;
8497034b911SVinicius Costa Gomes }
8507034b911SVinicius Costa Gomes 
851eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
852eb492e01SAnderson Briglia {
8537b9899dbSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
85492381f5cSMarcel Holtmann 	__u8 code, reason;
855eb492e01SAnderson Briglia 	int err = 0;
856eb492e01SAnderson Briglia 
8577b9899dbSMarcel Holtmann 	if (hcon->type != LE_LINK) {
8587b9899dbSMarcel Holtmann 		kfree_skb(skb);
8593432711fSJohan Hedberg 		return 0;
8607b9899dbSMarcel Holtmann 	}
8617b9899dbSMarcel Holtmann 
86292381f5cSMarcel Holtmann 	if (skb->len < 1) {
86392381f5cSMarcel Holtmann 		kfree_skb(skb);
86492381f5cSMarcel Holtmann 		return -EILSEQ;
86592381f5cSMarcel Holtmann 	}
86692381f5cSMarcel Holtmann 
86706ae3314SMarcel Holtmann 	if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
8682e65c9d2SAndre Guedes 		err = -ENOTSUPP;
8692e65c9d2SAndre Guedes 		reason = SMP_PAIRING_NOTSUPP;
8702e65c9d2SAndre Guedes 		goto done;
8712e65c9d2SAndre Guedes 	}
8722e65c9d2SAndre Guedes 
87392381f5cSMarcel Holtmann 	code = skb->data[0];
874eb492e01SAnderson Briglia 	skb_pull(skb, sizeof(code));
875eb492e01SAnderson Briglia 
8768cf9fa12SJohan Hedberg 	/*
8778cf9fa12SJohan Hedberg 	 * The SMP context must be initialized for all other PDUs except
8788cf9fa12SJohan Hedberg 	 * pairing and security requests. If we get any other PDU when
8798cf9fa12SJohan Hedberg 	 * not initialized simply disconnect (done if this function
8808cf9fa12SJohan Hedberg 	 * returns an error).
8818cf9fa12SJohan Hedberg 	 */
8828cf9fa12SJohan Hedberg 	if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
8838cf9fa12SJohan Hedberg 	    !conn->smp_chan) {
8848cf9fa12SJohan Hedberg 		BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
8858cf9fa12SJohan Hedberg 		kfree_skb(skb);
8868cf9fa12SJohan Hedberg 		return -ENOTSUPP;
8878cf9fa12SJohan Hedberg 	}
8888cf9fa12SJohan Hedberg 
889eb492e01SAnderson Briglia 	switch (code) {
890eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_REQ:
891da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_req(conn, skb);
892eb492e01SAnderson Briglia 		break;
893eb492e01SAnderson Briglia 
894eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_FAIL:
8954f957a76SBrian Gix 		smp_failure(conn, skb->data[0], 0);
896da85e5e5SVinicius Costa Gomes 		reason = 0;
897da85e5e5SVinicius Costa Gomes 		err = -EPERM;
898eb492e01SAnderson Briglia 		break;
899eb492e01SAnderson Briglia 
900eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RSP:
901da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_rsp(conn, skb);
90288ba43b6SAnderson Briglia 		break;
90388ba43b6SAnderson Briglia 
90488ba43b6SAnderson Briglia 	case SMP_CMD_SECURITY_REQ:
905da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_security_req(conn, skb);
90688ba43b6SAnderson Briglia 		break;
90788ba43b6SAnderson Briglia 
908eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_CONFIRM:
909da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_confirm(conn, skb);
91088ba43b6SAnderson Briglia 		break;
91188ba43b6SAnderson Briglia 
912eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RANDOM:
913da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_random(conn, skb);
91488ba43b6SAnderson Briglia 		break;
91588ba43b6SAnderson Briglia 
916eb492e01SAnderson Briglia 	case SMP_CMD_ENCRYPT_INFO:
9177034b911SVinicius Costa Gomes 		reason = smp_cmd_encrypt_info(conn, skb);
9187034b911SVinicius Costa Gomes 		break;
9197034b911SVinicius Costa Gomes 
920eb492e01SAnderson Briglia 	case SMP_CMD_MASTER_IDENT:
9217034b911SVinicius Costa Gomes 		reason = smp_cmd_master_ident(conn, skb);
9227034b911SVinicius Costa Gomes 		break;
9237034b911SVinicius Costa Gomes 
924eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_INFO:
925eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_ADDR_INFO:
926eb492e01SAnderson Briglia 	case SMP_CMD_SIGN_INFO:
9277034b911SVinicius Costa Gomes 		/* Just ignored */
9287034b911SVinicius Costa Gomes 		reason = 0;
9297034b911SVinicius Costa Gomes 		break;
9307034b911SVinicius Costa Gomes 
931eb492e01SAnderson Briglia 	default:
932eb492e01SAnderson Briglia 		BT_DBG("Unknown command code 0x%2.2x", code);
933eb492e01SAnderson Briglia 
934eb492e01SAnderson Briglia 		reason = SMP_CMD_NOTSUPP;
9353a0259bbSVinicius Costa Gomes 		err = -EOPNOTSUPP;
9363a0259bbSVinicius Costa Gomes 		goto done;
9373a0259bbSVinicius Costa Gomes 	}
9383a0259bbSVinicius Costa Gomes 
9393a0259bbSVinicius Costa Gomes done:
9403a0259bbSVinicius Costa Gomes 	if (reason)
9414f957a76SBrian Gix 		smp_failure(conn, reason, 1);
942eb492e01SAnderson Briglia 
943eb492e01SAnderson Briglia 	kfree_skb(skb);
944eb492e01SAnderson Briglia 	return err;
945eb492e01SAnderson Briglia }
9467034b911SVinicius Costa Gomes 
9477034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
9487034b911SVinicius Costa Gomes {
9497034b911SVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp;
9501c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
9517034b911SVinicius Costa Gomes 	__u8 *keydist;
9527034b911SVinicius Costa Gomes 
9537034b911SVinicius Costa Gomes 	BT_DBG("conn %p force %d", conn, force);
9547034b911SVinicius Costa Gomes 
95551a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
956d26a2345SVinicius Costa Gomes 		return 0;
957d26a2345SVinicius Costa Gomes 
9581c1def09SVinicius Costa Gomes 	rsp = (void *) &smp->prsp[1];
9597034b911SVinicius Costa Gomes 
9607034b911SVinicius Costa Gomes 	/* The responder sends its keys first */
9617034b911SVinicius Costa Gomes 	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
9627034b911SVinicius Costa Gomes 		return 0;
9637034b911SVinicius Costa Gomes 
9641c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
9657034b911SVinicius Costa Gomes 
9667034b911SVinicius Costa Gomes 	if (conn->hcon->out) {
9677034b911SVinicius Costa Gomes 		keydist = &rsp->init_key_dist;
9687034b911SVinicius Costa Gomes 		*keydist &= req->init_key_dist;
9697034b911SVinicius Costa Gomes 	} else {
9707034b911SVinicius Costa Gomes 		keydist = &rsp->resp_key_dist;
9717034b911SVinicius Costa Gomes 		*keydist &= req->resp_key_dist;
9727034b911SVinicius Costa Gomes 	}
9737034b911SVinicius Costa Gomes 
9747034b911SVinicius Costa Gomes 
9757034b911SVinicius Costa Gomes 	BT_DBG("keydist 0x%x", *keydist);
9767034b911SVinicius Costa Gomes 
9777034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ENC_KEY) {
9787034b911SVinicius Costa Gomes 		struct smp_cmd_encrypt_info enc;
9797034b911SVinicius Costa Gomes 		struct smp_cmd_master_ident ident;
980c9839a11SVinicius Costa Gomes 		struct hci_conn *hcon = conn->hcon;
981c9839a11SVinicius Costa Gomes 		u8 authenticated;
9827034b911SVinicius Costa Gomes 		__le16 ediv;
9837034b911SVinicius Costa Gomes 
9847034b911SVinicius Costa Gomes 		get_random_bytes(enc.ltk, sizeof(enc.ltk));
9857034b911SVinicius Costa Gomes 		get_random_bytes(&ediv, sizeof(ediv));
9867034b911SVinicius Costa Gomes 		get_random_bytes(ident.rand, sizeof(ident.rand));
9877034b911SVinicius Costa Gomes 
9887034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
9897034b911SVinicius Costa Gomes 
990c9839a11SVinicius Costa Gomes 		authenticated = hcon->sec_level == BT_SECURITY_HIGH;
991ce39fb4eSMarcel Holtmann 		hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
992c9839a11SVinicius Costa Gomes 			    HCI_SMP_LTK_SLAVE, 1, authenticated,
99304124681SGustavo F. Padovan 			    enc.ltk, smp->enc_key_size, ediv, ident.rand);
99416b90839SVinicius Costa Gomes 
99558115373SAndrei Emeltchenko 		ident.ediv = ediv;
9967034b911SVinicius Costa Gomes 
9977034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
9987034b911SVinicius Costa Gomes 
9997034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ENC_KEY;
10007034b911SVinicius Costa Gomes 	}
10017034b911SVinicius Costa Gomes 
10027034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ID_KEY) {
10037034b911SVinicius Costa Gomes 		struct smp_cmd_ident_addr_info addrinfo;
10047034b911SVinicius Costa Gomes 		struct smp_cmd_ident_info idinfo;
10057034b911SVinicius Costa Gomes 
10067034b911SVinicius Costa Gomes 		/* Send a dummy key */
10077034b911SVinicius Costa Gomes 		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
10087034b911SVinicius Costa Gomes 
10097034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
10107034b911SVinicius Costa Gomes 
10117034b911SVinicius Costa Gomes 		/* Just public address */
10127034b911SVinicius Costa Gomes 		memset(&addrinfo, 0, sizeof(addrinfo));
10132b36a562SMarcel Holtmann 		bacpy(&addrinfo.bdaddr, &conn->hcon->src);
10147034b911SVinicius Costa Gomes 
10157034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
10167034b911SVinicius Costa Gomes 			     &addrinfo);
10177034b911SVinicius Costa Gomes 
10187034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ID_KEY;
10197034b911SVinicius Costa Gomes 	}
10207034b911SVinicius Costa Gomes 
10217034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_SIGN) {
10227034b911SVinicius Costa Gomes 		struct smp_cmd_sign_info sign;
10237034b911SVinicius Costa Gomes 
10247034b911SVinicius Costa Gomes 		/* Send a dummy key */
10257034b911SVinicius Costa Gomes 		get_random_bytes(sign.csrk, sizeof(sign.csrk));
10267034b911SVinicius Costa Gomes 
10277034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
10287034b911SVinicius Costa Gomes 
10297034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_SIGN;
10307034b911SVinicius Costa Gomes 	}
10317034b911SVinicius Costa Gomes 
1032d26a2345SVinicius Costa Gomes 	if (conn->hcon->out || force) {
103351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
10346c9d42a1SGustavo F. Padovan 		cancel_delayed_work_sync(&conn->security_timer);
10358aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1036d26a2345SVinicius Costa Gomes 	}
1037d26a2345SVinicius Costa Gomes 
10387034b911SVinicius Costa Gomes 	return 0;
10397034b911SVinicius Costa Gomes }
1040