xref: /openbmc/linux/net/bluetooth/smp.c (revision 73d80deb)
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>
26eb492e01SAnderson Briglia #include <net/bluetooth/smp.h>
27d22ef0bcSAnderson Briglia #include <linux/crypto.h>
28f70490e6SStephen Rothwell #include <linux/scatterlist.h>
29d22ef0bcSAnderson Briglia #include <crypto/b128ops.h>
30d22ef0bcSAnderson Briglia 
315d3de7dfSVinicius Costa Gomes #define SMP_TIMEOUT 30000 /* 30 seconds */
325d3de7dfSVinicius Costa Gomes 
33d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16])
34d22ef0bcSAnderson Briglia {
35d22ef0bcSAnderson Briglia 	int i;
36d22ef0bcSAnderson Briglia 	for (i = 0; i < 16; i++)
37d22ef0bcSAnderson Briglia 		dst[15 - i] = src[i];
38d22ef0bcSAnderson Briglia }
39d22ef0bcSAnderson Briglia 
40d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7])
41d22ef0bcSAnderson Briglia {
42d22ef0bcSAnderson Briglia 	int i;
43d22ef0bcSAnderson Briglia 	for (i = 0; i < 7; i++)
44d22ef0bcSAnderson Briglia 		dst[6 - i] = src[i];
45d22ef0bcSAnderson Briglia }
46d22ef0bcSAnderson Briglia 
47d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
48d22ef0bcSAnderson Briglia {
49d22ef0bcSAnderson Briglia 	struct blkcipher_desc desc;
50d22ef0bcSAnderson Briglia 	struct scatterlist sg;
51d22ef0bcSAnderson Briglia 	int err, iv_len;
52d22ef0bcSAnderson Briglia 	unsigned char iv[128];
53d22ef0bcSAnderson Briglia 
54d22ef0bcSAnderson Briglia 	if (tfm == NULL) {
55d22ef0bcSAnderson Briglia 		BT_ERR("tfm %p", tfm);
56d22ef0bcSAnderson Briglia 		return -EINVAL;
57d22ef0bcSAnderson Briglia 	}
58d22ef0bcSAnderson Briglia 
59d22ef0bcSAnderson Briglia 	desc.tfm = tfm;
60d22ef0bcSAnderson Briglia 	desc.flags = 0;
61d22ef0bcSAnderson Briglia 
62d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_setkey(tfm, k, 16);
63d22ef0bcSAnderson Briglia 	if (err) {
64d22ef0bcSAnderson Briglia 		BT_ERR("cipher setkey failed: %d", err);
65d22ef0bcSAnderson Briglia 		return err;
66d22ef0bcSAnderson Briglia 	}
67d22ef0bcSAnderson Briglia 
68d22ef0bcSAnderson Briglia 	sg_init_one(&sg, r, 16);
69d22ef0bcSAnderson Briglia 
70d22ef0bcSAnderson Briglia 	iv_len = crypto_blkcipher_ivsize(tfm);
71d22ef0bcSAnderson Briglia 	if (iv_len) {
72d22ef0bcSAnderson Briglia 		memset(&iv, 0xff, iv_len);
73d22ef0bcSAnderson Briglia 		crypto_blkcipher_set_iv(tfm, iv, iv_len);
74d22ef0bcSAnderson Briglia 	}
75d22ef0bcSAnderson Briglia 
76d22ef0bcSAnderson Briglia 	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
77d22ef0bcSAnderson Briglia 	if (err)
78d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error %d", err);
79d22ef0bcSAnderson Briglia 
80d22ef0bcSAnderson Briglia 	return err;
81d22ef0bcSAnderson Briglia }
82d22ef0bcSAnderson Briglia 
83d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
84d22ef0bcSAnderson Briglia 		u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
85d22ef0bcSAnderson Briglia 		u8 _rat, bdaddr_t *ra, u8 res[16])
86d22ef0bcSAnderson Briglia {
87d22ef0bcSAnderson Briglia 	u8 p1[16], p2[16];
88d22ef0bcSAnderson Briglia 	int err;
89d22ef0bcSAnderson Briglia 
90d22ef0bcSAnderson Briglia 	memset(p1, 0, 16);
91d22ef0bcSAnderson Briglia 
92d22ef0bcSAnderson Briglia 	/* p1 = pres || preq || _rat || _iat */
93d22ef0bcSAnderson Briglia 	swap56(pres, p1);
94d22ef0bcSAnderson Briglia 	swap56(preq, p1 + 7);
95d22ef0bcSAnderson Briglia 	p1[14] = _rat;
96d22ef0bcSAnderson Briglia 	p1[15] = _iat;
97d22ef0bcSAnderson Briglia 
98d22ef0bcSAnderson Briglia 	memset(p2, 0, 16);
99d22ef0bcSAnderson Briglia 
100d22ef0bcSAnderson Briglia 	/* p2 = padding || ia || ra */
101d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 4), ia);
102d22ef0bcSAnderson Briglia 	baswap((bdaddr_t *) (p2 + 10), ra);
103d22ef0bcSAnderson Briglia 
104d22ef0bcSAnderson Briglia 	/* res = r XOR p1 */
105d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
106d22ef0bcSAnderson Briglia 
107d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
108d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
109d22ef0bcSAnderson Briglia 	if (err) {
110d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
111d22ef0bcSAnderson Briglia 		return err;
112d22ef0bcSAnderson Briglia 	}
113d22ef0bcSAnderson Briglia 
114d22ef0bcSAnderson Briglia 	/* res = res XOR p2 */
115d22ef0bcSAnderson Briglia 	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
116d22ef0bcSAnderson Briglia 
117d22ef0bcSAnderson Briglia 	/* res = e(k, res) */
118d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, res);
119d22ef0bcSAnderson Briglia 	if (err)
120d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
121d22ef0bcSAnderson Briglia 
122d22ef0bcSAnderson Briglia 	return err;
123d22ef0bcSAnderson Briglia }
124d22ef0bcSAnderson Briglia 
125d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
126d22ef0bcSAnderson Briglia 			u8 r1[16], u8 r2[16], u8 _r[16])
127d22ef0bcSAnderson Briglia {
128d22ef0bcSAnderson Briglia 	int err;
129d22ef0bcSAnderson Briglia 
130d22ef0bcSAnderson Briglia 	/* Just least significant octets from r1 and r2 are considered */
131d22ef0bcSAnderson Briglia 	memcpy(_r, r1 + 8, 8);
132d22ef0bcSAnderson Briglia 	memcpy(_r + 8, r2 + 8, 8);
133d22ef0bcSAnderson Briglia 
134d22ef0bcSAnderson Briglia 	err = smp_e(tfm, k, _r);
135d22ef0bcSAnderson Briglia 	if (err)
136d22ef0bcSAnderson Briglia 		BT_ERR("Encrypt data error");
137d22ef0bcSAnderson Briglia 
138d22ef0bcSAnderson Briglia 	return err;
139d22ef0bcSAnderson Briglia }
140d22ef0bcSAnderson Briglia 
141d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf)
142d22ef0bcSAnderson Briglia {
143d22ef0bcSAnderson Briglia 	get_random_bytes(buf, 16);
144d22ef0bcSAnderson Briglia 
145d22ef0bcSAnderson Briglia 	return 0;
146d22ef0bcSAnderson Briglia }
147eb492e01SAnderson Briglia 
148eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
149eb492e01SAnderson Briglia 						u16 dlen, void *data)
150eb492e01SAnderson Briglia {
151eb492e01SAnderson Briglia 	struct sk_buff *skb;
152eb492e01SAnderson Briglia 	struct l2cap_hdr *lh;
153eb492e01SAnderson Briglia 	int len;
154eb492e01SAnderson Briglia 
155eb492e01SAnderson Briglia 	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
156eb492e01SAnderson Briglia 
157eb492e01SAnderson Briglia 	if (len > conn->mtu)
158eb492e01SAnderson Briglia 		return NULL;
159eb492e01SAnderson Briglia 
160eb492e01SAnderson Briglia 	skb = bt_skb_alloc(len, GFP_ATOMIC);
161eb492e01SAnderson Briglia 	if (!skb)
162eb492e01SAnderson Briglia 		return NULL;
163eb492e01SAnderson Briglia 
164eb492e01SAnderson Briglia 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
165eb492e01SAnderson Briglia 	lh->len = cpu_to_le16(sizeof(code) + dlen);
166eb492e01SAnderson Briglia 	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
167eb492e01SAnderson Briglia 
168eb492e01SAnderson Briglia 	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
169eb492e01SAnderson Briglia 
170eb492e01SAnderson Briglia 	memcpy(skb_put(skb, dlen), data, dlen);
171eb492e01SAnderson Briglia 
172eb492e01SAnderson Briglia 	return skb;
173eb492e01SAnderson Briglia }
174eb492e01SAnderson Briglia 
175eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
176eb492e01SAnderson Briglia {
177eb492e01SAnderson Briglia 	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
178eb492e01SAnderson Briglia 
179eb492e01SAnderson Briglia 	BT_DBG("code 0x%2.2x", code);
180eb492e01SAnderson Briglia 
181eb492e01SAnderson Briglia 	if (!skb)
182eb492e01SAnderson Briglia 		return;
183eb492e01SAnderson Briglia 
18473d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
18573d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, 0);
186e2dcd113SVinicius Costa Gomes 
187e2dcd113SVinicius Costa Gomes 	mod_timer(&conn->security_timer, jiffies +
188e2dcd113SVinicius Costa Gomes 					msecs_to_jiffies(SMP_TIMEOUT));
189eb492e01SAnderson Briglia }
190eb492e01SAnderson Briglia 
191b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn,
19254790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *req,
19354790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *rsp,
19454790f73SVinicius Costa Gomes 				__u8 authreq)
195b8e66eacSVinicius Costa Gomes {
19654790f73SVinicius Costa Gomes 	u8 dist_keys;
19754790f73SVinicius Costa Gomes 
19854790f73SVinicius Costa Gomes 	dist_keys = 0;
19954790f73SVinicius Costa Gomes 	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
200ca10b5eeSVinicius Costa Gomes 		dist_keys = SMP_DIST_ENC_KEY;
20154790f73SVinicius Costa Gomes 		authreq |= SMP_AUTH_BONDING;
20254790f73SVinicius Costa Gomes 	}
20354790f73SVinicius Costa Gomes 
20454790f73SVinicius Costa Gomes 	if (rsp == NULL) {
20554790f73SVinicius Costa Gomes 		req->io_capability = conn->hcon->io_capability;
20654790f73SVinicius Costa Gomes 		req->oob_flag = SMP_OOB_NOT_PRESENT;
20754790f73SVinicius Costa Gomes 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
20854790f73SVinicius Costa Gomes 		req->init_key_dist = dist_keys;
20954790f73SVinicius Costa Gomes 		req->resp_key_dist = dist_keys;
21054790f73SVinicius Costa Gomes 		req->auth_req = authreq;
21154790f73SVinicius Costa Gomes 		return;
21254790f73SVinicius Costa Gomes 	}
21354790f73SVinicius Costa Gomes 
21454790f73SVinicius Costa Gomes 	rsp->io_capability = conn->hcon->io_capability;
21554790f73SVinicius Costa Gomes 	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
21654790f73SVinicius Costa Gomes 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
21754790f73SVinicius Costa Gomes 	rsp->init_key_dist = req->init_key_dist & dist_keys;
21854790f73SVinicius Costa Gomes 	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
21954790f73SVinicius Costa Gomes 	rsp->auth_req = authreq;
220b8e66eacSVinicius Costa Gomes }
221b8e66eacSVinicius Costa Gomes 
2223158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
2233158c50cSVinicius Costa Gomes {
2241c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
2251c1def09SVinicius Costa Gomes 
2263158c50cSVinicius Costa Gomes 	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
2273158c50cSVinicius Costa Gomes 			(max_key_size < SMP_MIN_ENC_KEY_SIZE))
2283158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
2293158c50cSVinicius Costa Gomes 
2301c1def09SVinicius Costa Gomes 	smp->smp_key_size = max_key_size;
2313158c50cSVinicius Costa Gomes 
2323158c50cSVinicius Costa Gomes 	return 0;
2333158c50cSVinicius Costa Gomes }
2343158c50cSVinicius Costa Gomes 
2358aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work)
2368aab4757SVinicius Costa Gomes {
2378aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
2388aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
2398aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm;
2408aab4757SVinicius Costa Gomes 	struct smp_cmd_pairing_confirm cp;
2418aab4757SVinicius Costa Gomes 	int ret;
2428aab4757SVinicius Costa Gomes 	u8 res[16], reason;
2438aab4757SVinicius Costa Gomes 
2448aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
2458aab4757SVinicius Costa Gomes 
2468aab4757SVinicius Costa Gomes 	tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
2478aab4757SVinicius Costa Gomes 	if (IS_ERR(tfm)) {
2488aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
2498aab4757SVinicius Costa Gomes 		goto error;
2508aab4757SVinicius Costa Gomes 	}
2518aab4757SVinicius Costa Gomes 
2528aab4757SVinicius Costa Gomes 	smp->tfm = tfm;
2538aab4757SVinicius Costa Gomes 
2548aab4757SVinicius Costa Gomes 	if (conn->hcon->out)
2558aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
2568aab4757SVinicius Costa Gomes 				conn->src, conn->hcon->dst_type, conn->dst,
2578aab4757SVinicius Costa Gomes 				res);
2588aab4757SVinicius Costa Gomes 	else
2598aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
2608aab4757SVinicius Costa Gomes 				conn->hcon->dst_type, conn->dst, 0, conn->src,
2618aab4757SVinicius Costa Gomes 				res);
2628aab4757SVinicius Costa Gomes 	if (ret) {
2638aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
2648aab4757SVinicius Costa Gomes 		goto error;
2658aab4757SVinicius Costa Gomes 	}
2668aab4757SVinicius Costa Gomes 
2678aab4757SVinicius Costa Gomes 	swap128(res, cp.confirm_val);
2688aab4757SVinicius Costa Gomes 	smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
2698aab4757SVinicius Costa Gomes 
2708aab4757SVinicius Costa Gomes 	return;
2718aab4757SVinicius Costa Gomes 
2728aab4757SVinicius Costa Gomes error:
2738aab4757SVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
2748aab4757SVinicius Costa Gomes 	smp_chan_destroy(conn);
2758aab4757SVinicius Costa Gomes }
2768aab4757SVinicius Costa Gomes 
2778aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work)
2788aab4757SVinicius Costa Gomes {
2798aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, random);
2808aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
2818aab4757SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
2828aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm = smp->tfm;
2838aab4757SVinicius Costa Gomes 	u8 reason, confirm[16], res[16], key[16];
2848aab4757SVinicius Costa Gomes 	int ret;
2858aab4757SVinicius Costa Gomes 
2868aab4757SVinicius Costa Gomes 	if (IS_ERR_OR_NULL(tfm)) {
2878aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
2888aab4757SVinicius Costa Gomes 		goto error;
2898aab4757SVinicius Costa Gomes 	}
2908aab4757SVinicius Costa Gomes 
2918aab4757SVinicius Costa Gomes 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
2928aab4757SVinicius Costa Gomes 
2938aab4757SVinicius Costa Gomes 	if (hcon->out)
2948aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
2958aab4757SVinicius Costa Gomes 				conn->src, hcon->dst_type, conn->dst,
2968aab4757SVinicius Costa Gomes 				res);
2978aab4757SVinicius Costa Gomes 	else
2988aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
2998aab4757SVinicius Costa Gomes 				hcon->dst_type, conn->dst, 0, conn->src,
3008aab4757SVinicius Costa Gomes 				res);
3018aab4757SVinicius Costa Gomes 	if (ret) {
3028aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3038aab4757SVinicius Costa Gomes 		goto error;
3048aab4757SVinicius Costa Gomes 	}
3058aab4757SVinicius Costa Gomes 
3068aab4757SVinicius Costa Gomes 	swap128(res, confirm);
3078aab4757SVinicius Costa Gomes 
3088aab4757SVinicius Costa Gomes 	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
3098aab4757SVinicius Costa Gomes 		BT_ERR("Pairing failed (confirmation values mismatch)");
3108aab4757SVinicius Costa Gomes 		reason = SMP_CONFIRM_FAILED;
3118aab4757SVinicius Costa Gomes 		goto error;
3128aab4757SVinicius Costa Gomes 	}
3138aab4757SVinicius Costa Gomes 
3148aab4757SVinicius Costa Gomes 	if (hcon->out) {
3158aab4757SVinicius Costa Gomes 		u8 stk[16], rand[8];
3168aab4757SVinicius Costa Gomes 		__le16 ediv;
3178aab4757SVinicius Costa Gomes 
3188aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
3198aab4757SVinicius Costa Gomes 		ediv = 0;
3208aab4757SVinicius Costa Gomes 
3218aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
3228aab4757SVinicius Costa Gomes 		swap128(key, stk);
3238aab4757SVinicius Costa Gomes 
3248aab4757SVinicius Costa Gomes 		memset(stk + smp->smp_key_size, 0,
3258aab4757SVinicius Costa Gomes 				SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
3268aab4757SVinicius Costa Gomes 
3278aab4757SVinicius Costa Gomes 		if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
3288aab4757SVinicius Costa Gomes 			reason = SMP_UNSPECIFIED;
3298aab4757SVinicius Costa Gomes 			goto error;
3308aab4757SVinicius Costa Gomes 		}
3318aab4757SVinicius Costa Gomes 
3328aab4757SVinicius Costa Gomes 		hci_le_start_enc(hcon, ediv, rand, stk);
3338aab4757SVinicius Costa Gomes 		hcon->enc_key_size = smp->smp_key_size;
3348aab4757SVinicius Costa Gomes 	} else {
3358aab4757SVinicius Costa Gomes 		u8 stk[16], r[16], rand[8];
3368aab4757SVinicius Costa Gomes 		__le16 ediv;
3378aab4757SVinicius Costa Gomes 
3388aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
3398aab4757SVinicius Costa Gomes 		ediv = 0;
3408aab4757SVinicius Costa Gomes 
3418aab4757SVinicius Costa Gomes 		swap128(smp->prnd, r);
3428aab4757SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
3438aab4757SVinicius Costa Gomes 
3448aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
3458aab4757SVinicius Costa Gomes 		swap128(key, stk);
3468aab4757SVinicius Costa Gomes 
3478aab4757SVinicius Costa Gomes 		memset(stk + smp->smp_key_size, 0,
3488aab4757SVinicius Costa Gomes 				SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
3498aab4757SVinicius Costa Gomes 
3508aab4757SVinicius Costa Gomes 		hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
3518aab4757SVinicius Costa Gomes 							ediv, rand, stk);
3528aab4757SVinicius Costa Gomes 	}
3538aab4757SVinicius Costa Gomes 
3548aab4757SVinicius Costa Gomes 	return;
3558aab4757SVinicius Costa Gomes 
3568aab4757SVinicius Costa Gomes error:
3578aab4757SVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
3588aab4757SVinicius Costa Gomes 	smp_chan_destroy(conn);
3598aab4757SVinicius Costa Gomes }
3608aab4757SVinicius Costa Gomes 
3618aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
3628aab4757SVinicius Costa Gomes {
3638aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
3648aab4757SVinicius Costa Gomes 
3658aab4757SVinicius Costa Gomes 	smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
3668aab4757SVinicius Costa Gomes 	if (!smp)
3678aab4757SVinicius Costa Gomes 		return NULL;
3688aab4757SVinicius Costa Gomes 
3698aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->confirm, confirm_work);
3708aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->random, random_work);
3718aab4757SVinicius Costa Gomes 
3728aab4757SVinicius Costa Gomes 	smp->conn = conn;
3738aab4757SVinicius Costa Gomes 	conn->smp_chan = smp;
3748aab4757SVinicius Costa Gomes 
3758aab4757SVinicius Costa Gomes 	hci_conn_hold(conn->hcon);
3768aab4757SVinicius Costa Gomes 
3778aab4757SVinicius Costa Gomes 	return smp;
3788aab4757SVinicius Costa Gomes }
3798aab4757SVinicius Costa Gomes 
3808aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn)
3818aab4757SVinicius Costa Gomes {
3828aab4757SVinicius Costa Gomes 	kfree(conn->smp_chan);
3838aab4757SVinicius Costa Gomes 	hci_conn_put(conn->hcon);
3848aab4757SVinicius Costa Gomes }
3858aab4757SVinicius Costa Gomes 
386da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
38788ba43b6SAnderson Briglia {
3883158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
3898aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
3903158c50cSVinicius Costa Gomes 	u8 key_size;
3918aab4757SVinicius Costa Gomes 	int ret;
39288ba43b6SAnderson Briglia 
39388ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
39488ba43b6SAnderson Briglia 
395d26a2345SVinicius Costa Gomes 	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
3968aab4757SVinicius Costa Gomes 		smp = smp_chan_create(conn);
3978aab4757SVinicius Costa Gomes 
3988aab4757SVinicius Costa Gomes 	smp = conn->smp_chan;
399d26a2345SVinicius Costa Gomes 
4001c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
4011c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], req, sizeof(*req));
4023158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*req));
40388ba43b6SAnderson Briglia 
4043158c50cSVinicius Costa Gomes 	if (req->oob_flag)
405da85e5e5SVinicius Costa Gomes 		return SMP_OOB_NOT_AVAIL;
406da85e5e5SVinicius Costa Gomes 
407da85e5e5SVinicius Costa Gomes 	/* We didn't start the pairing, so no requirements */
40854790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
4093158c50cSVinicius Costa Gomes 
4103158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp.max_key_size);
4113158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
4123158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
41388ba43b6SAnderson Briglia 
4147d24ddccSAnderson Briglia 	/* Just works */
4151c1def09SVinicius Costa Gomes 	memset(smp->tk, 0, sizeof(smp->tk));
4167d24ddccSAnderson Briglia 
4178aab4757SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
4188aab4757SVinicius Costa Gomes 	if (ret)
4198aab4757SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
4208aab4757SVinicius Costa Gomes 
4211c1def09SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
4221c1def09SVinicius Costa Gomes 	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
423f01ead31SAnderson Briglia 
4243158c50cSVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
425da85e5e5SVinicius Costa Gomes 
426da85e5e5SVinicius Costa Gomes 	return 0;
42788ba43b6SAnderson Briglia }
42888ba43b6SAnderson Briglia 
429da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
43088ba43b6SAnderson Briglia {
4313158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
4321c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
4338aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
4348aab4757SVinicius Costa Gomes 	u8 key_size;
4357d24ddccSAnderson Briglia 	int ret;
43688ba43b6SAnderson Briglia 
43788ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
43888ba43b6SAnderson Briglia 
4393158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*rsp));
440da85e5e5SVinicius Costa Gomes 
4411c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
4423158c50cSVinicius Costa Gomes 
4433158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp->max_key_size);
4443158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
4453158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
4463158c50cSVinicius Costa Gomes 
4473158c50cSVinicius Costa Gomes 	if (rsp->oob_flag)
448da85e5e5SVinicius Costa Gomes 		return SMP_OOB_NOT_AVAIL;
449da85e5e5SVinicius Costa Gomes 
4507d24ddccSAnderson Briglia 	/* Just works */
4511c1def09SVinicius Costa Gomes 	memset(smp->tk, 0, sizeof(smp->tk));
45288ba43b6SAnderson Briglia 
4531c1def09SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
4547d24ddccSAnderson Briglia 	if (ret)
455da85e5e5SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
4567d24ddccSAnderson Briglia 
4578aab4757SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
4588aab4757SVinicius Costa Gomes 	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
4597d24ddccSAnderson Briglia 
4608aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->confirm);
461da85e5e5SVinicius Costa Gomes 
462da85e5e5SVinicius Costa Gomes 	return 0;
46388ba43b6SAnderson Briglia }
46488ba43b6SAnderson Briglia 
465da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
46688ba43b6SAnderson Briglia {
4671c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
4688aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
4697d24ddccSAnderson Briglia 
47088ba43b6SAnderson Briglia 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
47188ba43b6SAnderson Briglia 
4721c1def09SVinicius Costa Gomes 	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
4731c1def09SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->pcnf));
4747d24ddccSAnderson Briglia 
47588ba43b6SAnderson Briglia 	if (conn->hcon->out) {
4767d24ddccSAnderson Briglia 		u8 random[16];
47788ba43b6SAnderson Briglia 
4781c1def09SVinicius Costa Gomes 		swap128(smp->prnd, random);
47988ba43b6SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
4807d24ddccSAnderson Briglia 								random);
48188ba43b6SAnderson Briglia 	} else {
4828aab4757SVinicius Costa Gomes 		queue_work(hdev->workqueue, &smp->confirm);
48388ba43b6SAnderson Briglia 	}
484da85e5e5SVinicius Costa Gomes 
485da85e5e5SVinicius Costa Gomes 	return 0;
48688ba43b6SAnderson Briglia }
48788ba43b6SAnderson Briglia 
488da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
48988ba43b6SAnderson Briglia {
4901c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
4918aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
4927d24ddccSAnderson Briglia 
4938aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
4947d24ddccSAnderson Briglia 
4958aab4757SVinicius Costa Gomes 	swap128(skb->data, smp->rrnd);
4968aab4757SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->rrnd));
49788ba43b6SAnderson Briglia 
4988aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->random);
499da85e5e5SVinicius Costa Gomes 
500da85e5e5SVinicius Costa Gomes 	return 0;
50188ba43b6SAnderson Briglia }
50288ba43b6SAnderson Briglia 
503988c5997SVinicius Costa Gomes static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
504988c5997SVinicius Costa Gomes {
505988c5997SVinicius Costa Gomes 	struct link_key *key;
506988c5997SVinicius Costa Gomes 	struct key_master_id *master;
507988c5997SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
508988c5997SVinicius Costa Gomes 
509988c5997SVinicius Costa Gomes 	key = hci_find_link_key_type(hcon->hdev, conn->dst,
510988c5997SVinicius Costa Gomes 						HCI_LK_SMP_LTK);
511988c5997SVinicius Costa Gomes 	if (!key)
512988c5997SVinicius Costa Gomes 		return 0;
513988c5997SVinicius Costa Gomes 
514988c5997SVinicius Costa Gomes 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
515988c5997SVinicius Costa Gomes 					&hcon->pend))
516988c5997SVinicius Costa Gomes 		return 1;
517988c5997SVinicius Costa Gomes 
518988c5997SVinicius Costa Gomes 	master = (void *) key->data;
519988c5997SVinicius Costa Gomes 	hci_le_start_enc(hcon, master->ediv, master->rand,
520988c5997SVinicius Costa Gomes 						key->val);
521988c5997SVinicius Costa Gomes 	hcon->enc_key_size = key->pin_len;
522988c5997SVinicius Costa Gomes 
523988c5997SVinicius Costa Gomes 	return 1;
524988c5997SVinicius Costa Gomes 
525988c5997SVinicius Costa Gomes }
526da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
52788ba43b6SAnderson Briglia {
52888ba43b6SAnderson Briglia 	struct smp_cmd_security_req *rp = (void *) skb->data;
52988ba43b6SAnderson Briglia 	struct smp_cmd_pairing cp;
530f1cb9af5SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
5318aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
53288ba43b6SAnderson Briglia 
53388ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
53488ba43b6SAnderson Briglia 
535feb45eb5SVinicius Costa Gomes 	hcon->pending_sec_level = BT_SECURITY_MEDIUM;
536feb45eb5SVinicius Costa Gomes 
537988c5997SVinicius Costa Gomes 	if (smp_ltk_encrypt(conn))
538988c5997SVinicius Costa Gomes 		return 0;
539988c5997SVinicius Costa Gomes 
540d26a2345SVinicius Costa Gomes 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
541da85e5e5SVinicius Costa Gomes 		return 0;
542f1cb9af5SVinicius Costa Gomes 
5438aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
544d26a2345SVinicius Costa Gomes 
54588ba43b6SAnderson Briglia 	skb_pull(skb, sizeof(*rp));
54688ba43b6SAnderson Briglia 
547da85e5e5SVinicius Costa Gomes 	memset(&cp, 0, sizeof(cp));
54854790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
54988ba43b6SAnderson Briglia 
5501c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
5511c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], &cp, sizeof(cp));
552f01ead31SAnderson Briglia 
55388ba43b6SAnderson Briglia 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
554f1cb9af5SVinicius Costa Gomes 
555da85e5e5SVinicius Costa Gomes 	return 0;
55688ba43b6SAnderson Briglia }
55788ba43b6SAnderson Briglia 
558eb492e01SAnderson Briglia int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
559eb492e01SAnderson Briglia {
5603a0259bbSVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
5611c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
562eb492e01SAnderson Briglia 
5633a0259bbSVinicius Costa Gomes 	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
5643a0259bbSVinicius Costa Gomes 
5652e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(hcon->hdev))
5662e65c9d2SAndre Guedes 		return 1;
5672e65c9d2SAndre Guedes 
568f1cb9af5SVinicius Costa Gomes 	if (sec_level == BT_SECURITY_LOW)
569eb492e01SAnderson Briglia 		return 1;
570f1cb9af5SVinicius Costa Gomes 
571f1cb9af5SVinicius Costa Gomes 	if (hcon->sec_level >= sec_level)
572f1cb9af5SVinicius Costa Gomes 		return 1;
573f1cb9af5SVinicius Costa Gomes 
574988c5997SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER)
575988c5997SVinicius Costa Gomes 		if (smp_ltk_encrypt(conn))
576d26a2345SVinicius Costa Gomes 			goto done;
577d26a2345SVinicius Costa Gomes 
578d26a2345SVinicius Costa Gomes 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
579d26a2345SVinicius Costa Gomes 		return 0;
580d26a2345SVinicius Costa Gomes 
5818aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
582d26a2345SVinicius Costa Gomes 
583d26a2345SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER) {
584d26a2345SVinicius Costa Gomes 		struct smp_cmd_pairing cp;
585f01ead31SAnderson Briglia 
5860fb4eb6fSVinicius Costa Gomes 		build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE);
5871c1def09SVinicius Costa Gomes 		smp->preq[0] = SMP_CMD_PAIRING_REQ;
5881c1def09SVinicius Costa Gomes 		memcpy(&smp->preq[1], &cp, sizeof(cp));
589f01ead31SAnderson Briglia 
590eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
591eb492e01SAnderson Briglia 	} else {
592eb492e01SAnderson Briglia 		struct smp_cmd_security_req cp;
5930fb4eb6fSVinicius Costa Gomes 		cp.auth_req = SMP_AUTH_NONE;
594eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
595eb492e01SAnderson Briglia 	}
596eb492e01SAnderson Briglia 
59702bc7455SVinicius Costa Gomes done:
598f1cb9af5SVinicius Costa Gomes 	hcon->pending_sec_level = sec_level;
599f1cb9af5SVinicius Costa Gomes 
600eb492e01SAnderson Briglia 	return 0;
601eb492e01SAnderson Briglia }
602eb492e01SAnderson Briglia 
6037034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
6047034b911SVinicius Costa Gomes {
60516b90839SVinicius Costa Gomes 	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
6061c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
60716b90839SVinicius Costa Gomes 
60816b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
60916b90839SVinicius Costa Gomes 
6101c1def09SVinicius Costa Gomes 	memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
61116b90839SVinicius Costa Gomes 
6127034b911SVinicius Costa Gomes 	return 0;
6137034b911SVinicius Costa Gomes }
6147034b911SVinicius Costa Gomes 
6157034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
6167034b911SVinicius Costa Gomes {
61716b90839SVinicius Costa Gomes 	struct smp_cmd_master_ident *rp = (void *) skb->data;
6181c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6197034b911SVinicius Costa Gomes 
62016b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
62116b90839SVinicius Costa Gomes 
6221c1def09SVinicius Costa Gomes 	hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
6231c1def09SVinicius Costa Gomes 						rp->ediv, rp->rand, smp->tk);
6247034b911SVinicius Costa Gomes 
6257034b911SVinicius Costa Gomes 	smp_distribute_keys(conn, 1);
6267034b911SVinicius Costa Gomes 
6277034b911SVinicius Costa Gomes 	return 0;
6287034b911SVinicius Costa Gomes }
6297034b911SVinicius Costa Gomes 
630eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
631eb492e01SAnderson Briglia {
632eb492e01SAnderson Briglia 	__u8 code = skb->data[0];
633eb492e01SAnderson Briglia 	__u8 reason;
634eb492e01SAnderson Briglia 	int err = 0;
635eb492e01SAnderson Briglia 
6362e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(conn->hcon->hdev)) {
6372e65c9d2SAndre Guedes 		err = -ENOTSUPP;
6382e65c9d2SAndre Guedes 		reason = SMP_PAIRING_NOTSUPP;
6392e65c9d2SAndre Guedes 		goto done;
6402e65c9d2SAndre Guedes 	}
6412e65c9d2SAndre Guedes 
642eb492e01SAnderson Briglia 	skb_pull(skb, sizeof(code));
643eb492e01SAnderson Briglia 
644eb492e01SAnderson Briglia 	switch (code) {
645eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_REQ:
646da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_req(conn, skb);
647eb492e01SAnderson Briglia 		break;
648eb492e01SAnderson Briglia 
649eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_FAIL:
650da85e5e5SVinicius Costa Gomes 		reason = 0;
651da85e5e5SVinicius Costa Gomes 		err = -EPERM;
652eb492e01SAnderson Briglia 		break;
653eb492e01SAnderson Briglia 
654eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RSP:
655da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_rsp(conn, skb);
65688ba43b6SAnderson Briglia 		break;
65788ba43b6SAnderson Briglia 
65888ba43b6SAnderson Briglia 	case SMP_CMD_SECURITY_REQ:
659da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_security_req(conn, skb);
66088ba43b6SAnderson Briglia 		break;
66188ba43b6SAnderson Briglia 
662eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_CONFIRM:
663da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_confirm(conn, skb);
66488ba43b6SAnderson Briglia 		break;
66588ba43b6SAnderson Briglia 
666eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RANDOM:
667da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_random(conn, skb);
66888ba43b6SAnderson Briglia 		break;
66988ba43b6SAnderson Briglia 
670eb492e01SAnderson Briglia 	case SMP_CMD_ENCRYPT_INFO:
6717034b911SVinicius Costa Gomes 		reason = smp_cmd_encrypt_info(conn, skb);
6727034b911SVinicius Costa Gomes 		break;
6737034b911SVinicius Costa Gomes 
674eb492e01SAnderson Briglia 	case SMP_CMD_MASTER_IDENT:
6757034b911SVinicius Costa Gomes 		reason = smp_cmd_master_ident(conn, skb);
6767034b911SVinicius Costa Gomes 		break;
6777034b911SVinicius Costa Gomes 
678eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_INFO:
679eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_ADDR_INFO:
680eb492e01SAnderson Briglia 	case SMP_CMD_SIGN_INFO:
6817034b911SVinicius Costa Gomes 		/* Just ignored */
6827034b911SVinicius Costa Gomes 		reason = 0;
6837034b911SVinicius Costa Gomes 		break;
6847034b911SVinicius Costa Gomes 
685eb492e01SAnderson Briglia 	default:
686eb492e01SAnderson Briglia 		BT_DBG("Unknown command code 0x%2.2x", code);
687eb492e01SAnderson Briglia 
688eb492e01SAnderson Briglia 		reason = SMP_CMD_NOTSUPP;
6893a0259bbSVinicius Costa Gomes 		err = -EOPNOTSUPP;
6903a0259bbSVinicius Costa Gomes 		goto done;
6913a0259bbSVinicius Costa Gomes 	}
6923a0259bbSVinicius Costa Gomes 
6933a0259bbSVinicius Costa Gomes done:
6943a0259bbSVinicius Costa Gomes 	if (reason)
695eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
696eb492e01SAnderson Briglia 								&reason);
697eb492e01SAnderson Briglia 
698eb492e01SAnderson Briglia 	kfree_skb(skb);
699eb492e01SAnderson Briglia 	return err;
700eb492e01SAnderson Briglia }
7017034b911SVinicius Costa Gomes 
7027034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
7037034b911SVinicius Costa Gomes {
7047034b911SVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp;
7051c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7067034b911SVinicius Costa Gomes 	__u8 *keydist;
7077034b911SVinicius Costa Gomes 
7087034b911SVinicius Costa Gomes 	BT_DBG("conn %p force %d", conn, force);
7097034b911SVinicius Costa Gomes 
710d26a2345SVinicius Costa Gomes 	if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
711d26a2345SVinicius Costa Gomes 		return 0;
712d26a2345SVinicius Costa Gomes 
7131c1def09SVinicius Costa Gomes 	rsp = (void *) &smp->prsp[1];
7147034b911SVinicius Costa Gomes 
7157034b911SVinicius Costa Gomes 	/* The responder sends its keys first */
7167034b911SVinicius Costa Gomes 	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
7177034b911SVinicius Costa Gomes 		return 0;
7187034b911SVinicius Costa Gomes 
7191c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
7207034b911SVinicius Costa Gomes 
7217034b911SVinicius Costa Gomes 	if (conn->hcon->out) {
7227034b911SVinicius Costa Gomes 		keydist = &rsp->init_key_dist;
7237034b911SVinicius Costa Gomes 		*keydist &= req->init_key_dist;
7247034b911SVinicius Costa Gomes 	} else {
7257034b911SVinicius Costa Gomes 		keydist = &rsp->resp_key_dist;
7267034b911SVinicius Costa Gomes 		*keydist &= req->resp_key_dist;
7277034b911SVinicius Costa Gomes 	}
7287034b911SVinicius Costa Gomes 
7297034b911SVinicius Costa Gomes 
7307034b911SVinicius Costa Gomes 	BT_DBG("keydist 0x%x", *keydist);
7317034b911SVinicius Costa Gomes 
7327034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ENC_KEY) {
7337034b911SVinicius Costa Gomes 		struct smp_cmd_encrypt_info enc;
7347034b911SVinicius Costa Gomes 		struct smp_cmd_master_ident ident;
7357034b911SVinicius Costa Gomes 		__le16 ediv;
7367034b911SVinicius Costa Gomes 
7377034b911SVinicius Costa Gomes 		get_random_bytes(enc.ltk, sizeof(enc.ltk));
7387034b911SVinicius Costa Gomes 		get_random_bytes(&ediv, sizeof(ediv));
7397034b911SVinicius Costa Gomes 		get_random_bytes(ident.rand, sizeof(ident.rand));
7407034b911SVinicius Costa Gomes 
7417034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
7427034b911SVinicius Costa Gomes 
7431c1def09SVinicius Costa Gomes 		hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
744726b4ffcSVinicius Costa Gomes 						ediv, ident.rand, enc.ltk);
74516b90839SVinicius Costa Gomes 
7467034b911SVinicius Costa Gomes 		ident.ediv = cpu_to_le16(ediv);
7477034b911SVinicius Costa Gomes 
7487034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
7497034b911SVinicius Costa Gomes 
7507034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ENC_KEY;
7517034b911SVinicius Costa Gomes 	}
7527034b911SVinicius Costa Gomes 
7537034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ID_KEY) {
7547034b911SVinicius Costa Gomes 		struct smp_cmd_ident_addr_info addrinfo;
7557034b911SVinicius Costa Gomes 		struct smp_cmd_ident_info idinfo;
7567034b911SVinicius Costa Gomes 
7577034b911SVinicius Costa Gomes 		/* Send a dummy key */
7587034b911SVinicius Costa Gomes 		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
7597034b911SVinicius Costa Gomes 
7607034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
7617034b911SVinicius Costa Gomes 
7627034b911SVinicius Costa Gomes 		/* Just public address */
7637034b911SVinicius Costa Gomes 		memset(&addrinfo, 0, sizeof(addrinfo));
7647034b911SVinicius Costa Gomes 		bacpy(&addrinfo.bdaddr, conn->src);
7657034b911SVinicius Costa Gomes 
7667034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
7677034b911SVinicius Costa Gomes 								&addrinfo);
7687034b911SVinicius Costa Gomes 
7697034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ID_KEY;
7707034b911SVinicius Costa Gomes 	}
7717034b911SVinicius Costa Gomes 
7727034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_SIGN) {
7737034b911SVinicius Costa Gomes 		struct smp_cmd_sign_info sign;
7747034b911SVinicius Costa Gomes 
7757034b911SVinicius Costa Gomes 		/* Send a dummy key */
7767034b911SVinicius Costa Gomes 		get_random_bytes(sign.csrk, sizeof(sign.csrk));
7777034b911SVinicius Costa Gomes 
7787034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
7797034b911SVinicius Costa Gomes 
7807034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_SIGN;
7817034b911SVinicius Costa Gomes 	}
7827034b911SVinicius Costa Gomes 
783d26a2345SVinicius Costa Gomes 	if (conn->hcon->out || force) {
784d26a2345SVinicius Costa Gomes 		clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
785d26a2345SVinicius Costa Gomes 		del_timer(&conn->security_timer);
7868aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
787d26a2345SVinicius Costa Gomes 	}
788d26a2345SVinicius Costa Gomes 
7897034b911SVinicius Costa Gomes 	return 0;
7907034b911SVinicius Costa Gomes }
791