xref: /openbmc/linux/net/bluetooth/smp.c (revision 6c9d42a1)
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 
1876c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
1886c9d42a1SGustavo F. Padovan 	schedule_delayed_work(&conn->security_timer,
189e2dcd113SVinicius Costa Gomes 					msecs_to_jiffies(SMP_TIMEOUT));
190eb492e01SAnderson Briglia }
191eb492e01SAnderson Briglia 
192b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn,
19354790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *req,
19454790f73SVinicius Costa Gomes 				struct smp_cmd_pairing *rsp,
19554790f73SVinicius Costa Gomes 				__u8 authreq)
196b8e66eacSVinicius Costa Gomes {
19754790f73SVinicius Costa Gomes 	u8 dist_keys;
19854790f73SVinicius Costa Gomes 
19954790f73SVinicius Costa Gomes 	dist_keys = 0;
20054790f73SVinicius Costa Gomes 	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
201ca10b5eeSVinicius Costa Gomes 		dist_keys = SMP_DIST_ENC_KEY;
20254790f73SVinicius Costa Gomes 		authreq |= SMP_AUTH_BONDING;
20354790f73SVinicius Costa Gomes 	}
20454790f73SVinicius Costa Gomes 
20554790f73SVinicius Costa Gomes 	if (rsp == NULL) {
20654790f73SVinicius Costa Gomes 		req->io_capability = conn->hcon->io_capability;
20754790f73SVinicius Costa Gomes 		req->oob_flag = SMP_OOB_NOT_PRESENT;
20854790f73SVinicius Costa Gomes 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
20954790f73SVinicius Costa Gomes 		req->init_key_dist = dist_keys;
21054790f73SVinicius Costa Gomes 		req->resp_key_dist = dist_keys;
21154790f73SVinicius Costa Gomes 		req->auth_req = authreq;
21254790f73SVinicius Costa Gomes 		return;
21354790f73SVinicius Costa Gomes 	}
21454790f73SVinicius Costa Gomes 
21554790f73SVinicius Costa Gomes 	rsp->io_capability = conn->hcon->io_capability;
21654790f73SVinicius Costa Gomes 	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
21754790f73SVinicius Costa Gomes 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
21854790f73SVinicius Costa Gomes 	rsp->init_key_dist = req->init_key_dist & dist_keys;
21954790f73SVinicius Costa Gomes 	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
22054790f73SVinicius Costa Gomes 	rsp->auth_req = authreq;
221b8e66eacSVinicius Costa Gomes }
222b8e66eacSVinicius Costa Gomes 
2233158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
2243158c50cSVinicius Costa Gomes {
2251c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
2261c1def09SVinicius Costa Gomes 
2273158c50cSVinicius Costa Gomes 	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
2283158c50cSVinicius Costa Gomes 			(max_key_size < SMP_MIN_ENC_KEY_SIZE))
2293158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
2303158c50cSVinicius Costa Gomes 
2311c1def09SVinicius Costa Gomes 	smp->smp_key_size = max_key_size;
2323158c50cSVinicius Costa Gomes 
2333158c50cSVinicius Costa Gomes 	return 0;
2343158c50cSVinicius Costa Gomes }
2353158c50cSVinicius Costa Gomes 
2364f957a76SBrian Gix static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
2374f957a76SBrian Gix {
2384f957a76SBrian Gix 	if (send)
2394f957a76SBrian Gix 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
2404f957a76SBrian Gix 								&reason);
2414f957a76SBrian Gix 
2424f957a76SBrian Gix 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
2434f957a76SBrian Gix 	mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason);
2446c9d42a1SGustavo F. Padovan 	cancel_delayed_work_sync(&conn->security_timer);
2454f957a76SBrian Gix 	smp_chan_destroy(conn);
2464f957a76SBrian Gix }
2474f957a76SBrian Gix 
2488aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work)
2498aab4757SVinicius Costa Gomes {
2508aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
2518aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
2528aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm;
2538aab4757SVinicius Costa Gomes 	struct smp_cmd_pairing_confirm cp;
2548aab4757SVinicius Costa Gomes 	int ret;
2558aab4757SVinicius Costa Gomes 	u8 res[16], reason;
2568aab4757SVinicius Costa Gomes 
2578aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
2588aab4757SVinicius Costa Gomes 
2598aab4757SVinicius Costa Gomes 	tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
2608aab4757SVinicius Costa Gomes 	if (IS_ERR(tfm)) {
2618aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
2628aab4757SVinicius Costa Gomes 		goto error;
2638aab4757SVinicius Costa Gomes 	}
2648aab4757SVinicius Costa Gomes 
2658aab4757SVinicius Costa Gomes 	smp->tfm = tfm;
2668aab4757SVinicius Costa Gomes 
2678aab4757SVinicius Costa Gomes 	if (conn->hcon->out)
2688aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
2698aab4757SVinicius Costa Gomes 				conn->src, conn->hcon->dst_type, conn->dst,
2708aab4757SVinicius Costa Gomes 				res);
2718aab4757SVinicius Costa Gomes 	else
2728aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
2738aab4757SVinicius Costa Gomes 				conn->hcon->dst_type, conn->dst, 0, conn->src,
2748aab4757SVinicius Costa Gomes 				res);
2758aab4757SVinicius Costa Gomes 	if (ret) {
2768aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
2778aab4757SVinicius Costa Gomes 		goto error;
2788aab4757SVinicius Costa Gomes 	}
2798aab4757SVinicius Costa Gomes 
2808aab4757SVinicius Costa Gomes 	swap128(res, cp.confirm_val);
2818aab4757SVinicius Costa Gomes 	smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
2828aab4757SVinicius Costa Gomes 
2838aab4757SVinicius Costa Gomes 	return;
2848aab4757SVinicius Costa Gomes 
2858aab4757SVinicius Costa Gomes error:
2864f957a76SBrian Gix 	smp_failure(conn, reason, 1);
2878aab4757SVinicius Costa Gomes }
2888aab4757SVinicius Costa Gomes 
2898aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work)
2908aab4757SVinicius Costa Gomes {
2918aab4757SVinicius Costa Gomes 	struct smp_chan *smp = container_of(work, struct smp_chan, random);
2928aab4757SVinicius Costa Gomes 	struct l2cap_conn *conn = smp->conn;
2938aab4757SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
2948aab4757SVinicius Costa Gomes 	struct crypto_blkcipher *tfm = smp->tfm;
2958aab4757SVinicius Costa Gomes 	u8 reason, confirm[16], res[16], key[16];
2968aab4757SVinicius Costa Gomes 	int ret;
2978aab4757SVinicius Costa Gomes 
2988aab4757SVinicius Costa Gomes 	if (IS_ERR_OR_NULL(tfm)) {
2998aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3008aab4757SVinicius Costa Gomes 		goto error;
3018aab4757SVinicius Costa Gomes 	}
3028aab4757SVinicius Costa Gomes 
3038aab4757SVinicius Costa Gomes 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
3048aab4757SVinicius Costa Gomes 
3058aab4757SVinicius Costa Gomes 	if (hcon->out)
3068aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
3078aab4757SVinicius Costa Gomes 				conn->src, hcon->dst_type, conn->dst,
3088aab4757SVinicius Costa Gomes 				res);
3098aab4757SVinicius Costa Gomes 	else
3108aab4757SVinicius Costa Gomes 		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
3118aab4757SVinicius Costa Gomes 				hcon->dst_type, conn->dst, 0, conn->src,
3128aab4757SVinicius Costa Gomes 				res);
3138aab4757SVinicius Costa Gomes 	if (ret) {
3148aab4757SVinicius Costa Gomes 		reason = SMP_UNSPECIFIED;
3158aab4757SVinicius Costa Gomes 		goto error;
3168aab4757SVinicius Costa Gomes 	}
3178aab4757SVinicius Costa Gomes 
3188aab4757SVinicius Costa Gomes 	swap128(res, confirm);
3198aab4757SVinicius Costa Gomes 
3208aab4757SVinicius Costa Gomes 	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
3218aab4757SVinicius Costa Gomes 		BT_ERR("Pairing failed (confirmation values mismatch)");
3228aab4757SVinicius Costa Gomes 		reason = SMP_CONFIRM_FAILED;
3238aab4757SVinicius Costa Gomes 		goto error;
3248aab4757SVinicius Costa Gomes 	}
3258aab4757SVinicius Costa Gomes 
3268aab4757SVinicius Costa Gomes 	if (hcon->out) {
3278aab4757SVinicius Costa Gomes 		u8 stk[16], rand[8];
3288aab4757SVinicius Costa Gomes 		__le16 ediv;
3298aab4757SVinicius Costa Gomes 
3308aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
3318aab4757SVinicius Costa Gomes 		ediv = 0;
3328aab4757SVinicius Costa Gomes 
3338aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
3348aab4757SVinicius Costa Gomes 		swap128(key, stk);
3358aab4757SVinicius Costa Gomes 
3368aab4757SVinicius Costa Gomes 		memset(stk + smp->smp_key_size, 0,
3378aab4757SVinicius Costa Gomes 				SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
3388aab4757SVinicius Costa Gomes 
3398aab4757SVinicius Costa Gomes 		if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
3408aab4757SVinicius Costa Gomes 			reason = SMP_UNSPECIFIED;
3418aab4757SVinicius Costa Gomes 			goto error;
3428aab4757SVinicius Costa Gomes 		}
3438aab4757SVinicius Costa Gomes 
3448aab4757SVinicius Costa Gomes 		hci_le_start_enc(hcon, ediv, rand, stk);
3458aab4757SVinicius Costa Gomes 		hcon->enc_key_size = smp->smp_key_size;
3468aab4757SVinicius Costa Gomes 	} else {
3478aab4757SVinicius Costa Gomes 		u8 stk[16], r[16], rand[8];
3488aab4757SVinicius Costa Gomes 		__le16 ediv;
3498aab4757SVinicius Costa Gomes 
3508aab4757SVinicius Costa Gomes 		memset(rand, 0, sizeof(rand));
3518aab4757SVinicius Costa Gomes 		ediv = 0;
3528aab4757SVinicius Costa Gomes 
3538aab4757SVinicius Costa Gomes 		swap128(smp->prnd, r);
3548aab4757SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
3558aab4757SVinicius Costa Gomes 
3568aab4757SVinicius Costa Gomes 		smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
3578aab4757SVinicius Costa Gomes 		swap128(key, stk);
3588aab4757SVinicius Costa Gomes 
3598aab4757SVinicius Costa Gomes 		memset(stk + smp->smp_key_size, 0,
3608aab4757SVinicius Costa Gomes 				SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
3618aab4757SVinicius Costa Gomes 
3628aab4757SVinicius Costa Gomes 		hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
3638aab4757SVinicius Costa Gomes 							ediv, rand, stk);
3648aab4757SVinicius Costa Gomes 	}
3658aab4757SVinicius Costa Gomes 
3668aab4757SVinicius Costa Gomes 	return;
3678aab4757SVinicius Costa Gomes 
3688aab4757SVinicius Costa Gomes error:
3694f957a76SBrian Gix 	smp_failure(conn, reason, 1);
3708aab4757SVinicius Costa Gomes }
3718aab4757SVinicius Costa Gomes 
3728aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
3738aab4757SVinicius Costa Gomes {
3748aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
3758aab4757SVinicius Costa Gomes 
3768aab4757SVinicius Costa Gomes 	smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
3778aab4757SVinicius Costa Gomes 	if (!smp)
3788aab4757SVinicius Costa Gomes 		return NULL;
3798aab4757SVinicius Costa Gomes 
3808aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->confirm, confirm_work);
3818aab4757SVinicius Costa Gomes 	INIT_WORK(&smp->random, random_work);
3828aab4757SVinicius Costa Gomes 
3838aab4757SVinicius Costa Gomes 	smp->conn = conn;
3848aab4757SVinicius Costa Gomes 	conn->smp_chan = smp;
3858aab4757SVinicius Costa Gomes 
3868aab4757SVinicius Costa Gomes 	hci_conn_hold(conn->hcon);
3878aab4757SVinicius Costa Gomes 
3888aab4757SVinicius Costa Gomes 	return smp;
3898aab4757SVinicius Costa Gomes }
3908aab4757SVinicius Costa Gomes 
3918aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn)
3928aab4757SVinicius Costa Gomes {
393c8eb9690SBrian Gix 	struct smp_chan *smp = conn->smp_chan;
394c8eb9690SBrian Gix 
395c8eb9690SBrian Gix 	clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
396c8eb9690SBrian Gix 
397c8eb9690SBrian Gix 	if (smp->tfm)
398c8eb9690SBrian Gix 		crypto_free_blkcipher(smp->tfm);
399c8eb9690SBrian Gix 
400c8eb9690SBrian Gix 	kfree(smp);
401c8eb9690SBrian Gix 	conn->smp_chan = NULL;
4028aab4757SVinicius Costa Gomes 	hci_conn_put(conn->hcon);
4038aab4757SVinicius Costa Gomes }
4048aab4757SVinicius Costa Gomes 
405da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
40688ba43b6SAnderson Briglia {
4073158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
4088aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
4093158c50cSVinicius Costa Gomes 	u8 key_size;
4108aab4757SVinicius Costa Gomes 	int ret;
41188ba43b6SAnderson Briglia 
41288ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
41388ba43b6SAnderson Briglia 
414d26a2345SVinicius Costa Gomes 	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
4158aab4757SVinicius Costa Gomes 		smp = smp_chan_create(conn);
4168aab4757SVinicius Costa Gomes 
4178aab4757SVinicius Costa Gomes 	smp = conn->smp_chan;
418d26a2345SVinicius Costa Gomes 
4191c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
4201c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], req, sizeof(*req));
4213158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*req));
42288ba43b6SAnderson Briglia 
4233158c50cSVinicius Costa Gomes 	if (req->oob_flag)
424da85e5e5SVinicius Costa Gomes 		return SMP_OOB_NOT_AVAIL;
425da85e5e5SVinicius Costa Gomes 
426da85e5e5SVinicius Costa Gomes 	/* We didn't start the pairing, so no requirements */
42754790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
4283158c50cSVinicius Costa Gomes 
4293158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp.max_key_size);
4303158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
4313158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
43288ba43b6SAnderson Briglia 
4337d24ddccSAnderson Briglia 	/* Just works */
4341c1def09SVinicius Costa Gomes 	memset(smp->tk, 0, sizeof(smp->tk));
4357d24ddccSAnderson Briglia 
4368aab4757SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
4378aab4757SVinicius Costa Gomes 	if (ret)
4388aab4757SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
4398aab4757SVinicius Costa Gomes 
4401c1def09SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
4411c1def09SVinicius Costa Gomes 	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
442f01ead31SAnderson Briglia 
4433158c50cSVinicius Costa Gomes 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
444da85e5e5SVinicius Costa Gomes 
445da85e5e5SVinicius Costa Gomes 	return 0;
44688ba43b6SAnderson Briglia }
44788ba43b6SAnderson Briglia 
448da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
44988ba43b6SAnderson Briglia {
4503158c50cSVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
4511c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
4528aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
4538aab4757SVinicius Costa Gomes 	u8 key_size;
4547d24ddccSAnderson Briglia 	int ret;
45588ba43b6SAnderson Briglia 
45688ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
45788ba43b6SAnderson Briglia 
4583158c50cSVinicius Costa Gomes 	skb_pull(skb, sizeof(*rsp));
459da85e5e5SVinicius Costa Gomes 
4601c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
4613158c50cSVinicius Costa Gomes 
4623158c50cSVinicius Costa Gomes 	key_size = min(req->max_key_size, rsp->max_key_size);
4633158c50cSVinicius Costa Gomes 	if (check_enc_key_size(conn, key_size))
4643158c50cSVinicius Costa Gomes 		return SMP_ENC_KEY_SIZE;
4653158c50cSVinicius Costa Gomes 
4663158c50cSVinicius Costa Gomes 	if (rsp->oob_flag)
467da85e5e5SVinicius Costa Gomes 		return SMP_OOB_NOT_AVAIL;
468da85e5e5SVinicius Costa Gomes 
4697d24ddccSAnderson Briglia 	/* Just works */
4701c1def09SVinicius Costa Gomes 	memset(smp->tk, 0, sizeof(smp->tk));
47188ba43b6SAnderson Briglia 
4721c1def09SVinicius Costa Gomes 	ret = smp_rand(smp->prnd);
4737d24ddccSAnderson Briglia 	if (ret)
474da85e5e5SVinicius Costa Gomes 		return SMP_UNSPECIFIED;
4757d24ddccSAnderson Briglia 
4768aab4757SVinicius Costa Gomes 	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
4778aab4757SVinicius Costa Gomes 	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
4787d24ddccSAnderson Briglia 
4798aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->confirm);
480da85e5e5SVinicius Costa Gomes 
481da85e5e5SVinicius Costa Gomes 	return 0;
48288ba43b6SAnderson Briglia }
48388ba43b6SAnderson Briglia 
484da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
48588ba43b6SAnderson Briglia {
4861c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
4878aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
4887d24ddccSAnderson Briglia 
48988ba43b6SAnderson Briglia 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
49088ba43b6SAnderson Briglia 
4911c1def09SVinicius Costa Gomes 	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
4921c1def09SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->pcnf));
4937d24ddccSAnderson Briglia 
49488ba43b6SAnderson Briglia 	if (conn->hcon->out) {
4957d24ddccSAnderson Briglia 		u8 random[16];
49688ba43b6SAnderson Briglia 
4971c1def09SVinicius Costa Gomes 		swap128(smp->prnd, random);
49888ba43b6SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
4997d24ddccSAnderson Briglia 								random);
50088ba43b6SAnderson Briglia 	} else {
5018aab4757SVinicius Costa Gomes 		queue_work(hdev->workqueue, &smp->confirm);
50288ba43b6SAnderson Briglia 	}
503da85e5e5SVinicius Costa Gomes 
504da85e5e5SVinicius Costa Gomes 	return 0;
50588ba43b6SAnderson Briglia }
50688ba43b6SAnderson Briglia 
507da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
50888ba43b6SAnderson Briglia {
5091c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
5108aab4757SVinicius Costa Gomes 	struct hci_dev *hdev = conn->hcon->hdev;
5117d24ddccSAnderson Briglia 
5128aab4757SVinicius Costa Gomes 	BT_DBG("conn %p", conn);
5137d24ddccSAnderson Briglia 
5148aab4757SVinicius Costa Gomes 	swap128(skb->data, smp->rrnd);
5158aab4757SVinicius Costa Gomes 	skb_pull(skb, sizeof(smp->rrnd));
51688ba43b6SAnderson Briglia 
5178aab4757SVinicius Costa Gomes 	queue_work(hdev->workqueue, &smp->random);
518da85e5e5SVinicius Costa Gomes 
519da85e5e5SVinicius Costa Gomes 	return 0;
52088ba43b6SAnderson Briglia }
52188ba43b6SAnderson Briglia 
522988c5997SVinicius Costa Gomes static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
523988c5997SVinicius Costa Gomes {
524988c5997SVinicius Costa Gomes 	struct link_key *key;
525988c5997SVinicius Costa Gomes 	struct key_master_id *master;
526988c5997SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
527988c5997SVinicius Costa Gomes 
528988c5997SVinicius Costa Gomes 	key = hci_find_link_key_type(hcon->hdev, conn->dst,
529988c5997SVinicius Costa Gomes 						HCI_LK_SMP_LTK);
530988c5997SVinicius Costa Gomes 	if (!key)
531988c5997SVinicius Costa Gomes 		return 0;
532988c5997SVinicius Costa Gomes 
533988c5997SVinicius Costa Gomes 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
534988c5997SVinicius Costa Gomes 					&hcon->pend))
535988c5997SVinicius Costa Gomes 		return 1;
536988c5997SVinicius Costa Gomes 
537988c5997SVinicius Costa Gomes 	master = (void *) key->data;
538988c5997SVinicius Costa Gomes 	hci_le_start_enc(hcon, master->ediv, master->rand,
539988c5997SVinicius Costa Gomes 						key->val);
540988c5997SVinicius Costa Gomes 	hcon->enc_key_size = key->pin_len;
541988c5997SVinicius Costa Gomes 
542988c5997SVinicius Costa Gomes 	return 1;
543988c5997SVinicius Costa Gomes 
544988c5997SVinicius Costa Gomes }
545da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
54688ba43b6SAnderson Briglia {
54788ba43b6SAnderson Briglia 	struct smp_cmd_security_req *rp = (void *) skb->data;
54888ba43b6SAnderson Briglia 	struct smp_cmd_pairing cp;
549f1cb9af5SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
5508aab4757SVinicius Costa Gomes 	struct smp_chan *smp;
55188ba43b6SAnderson Briglia 
55288ba43b6SAnderson Briglia 	BT_DBG("conn %p", conn);
55388ba43b6SAnderson Briglia 
554feb45eb5SVinicius Costa Gomes 	hcon->pending_sec_level = BT_SECURITY_MEDIUM;
555feb45eb5SVinicius Costa Gomes 
556988c5997SVinicius Costa Gomes 	if (smp_ltk_encrypt(conn))
557988c5997SVinicius Costa Gomes 		return 0;
558988c5997SVinicius Costa Gomes 
559d26a2345SVinicius Costa Gomes 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
560da85e5e5SVinicius Costa Gomes 		return 0;
561f1cb9af5SVinicius Costa Gomes 
5628aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
563d26a2345SVinicius Costa Gomes 
56488ba43b6SAnderson Briglia 	skb_pull(skb, sizeof(*rp));
56588ba43b6SAnderson Briglia 
566da85e5e5SVinicius Costa Gomes 	memset(&cp, 0, sizeof(cp));
56754790f73SVinicius Costa Gomes 	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
56888ba43b6SAnderson Briglia 
5691c1def09SVinicius Costa Gomes 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
5701c1def09SVinicius Costa Gomes 	memcpy(&smp->preq[1], &cp, sizeof(cp));
571f01ead31SAnderson Briglia 
57288ba43b6SAnderson Briglia 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
573f1cb9af5SVinicius Costa Gomes 
574da85e5e5SVinicius Costa Gomes 	return 0;
57588ba43b6SAnderson Briglia }
57688ba43b6SAnderson Briglia 
577eb492e01SAnderson Briglia int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
578eb492e01SAnderson Briglia {
5793a0259bbSVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
5801c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
581eb492e01SAnderson Briglia 
5823a0259bbSVinicius Costa Gomes 	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
5833a0259bbSVinicius Costa Gomes 
5842e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(hcon->hdev))
5852e65c9d2SAndre Guedes 		return 1;
5862e65c9d2SAndre Guedes 
587f1cb9af5SVinicius Costa Gomes 	if (sec_level == BT_SECURITY_LOW)
588eb492e01SAnderson Briglia 		return 1;
589f1cb9af5SVinicius Costa Gomes 
590f1cb9af5SVinicius Costa Gomes 	if (hcon->sec_level >= sec_level)
591f1cb9af5SVinicius Costa Gomes 		return 1;
592f1cb9af5SVinicius Costa Gomes 
593988c5997SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER)
594988c5997SVinicius Costa Gomes 		if (smp_ltk_encrypt(conn))
595d26a2345SVinicius Costa Gomes 			goto done;
596d26a2345SVinicius Costa Gomes 
597d26a2345SVinicius Costa Gomes 	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
598d26a2345SVinicius Costa Gomes 		return 0;
599d26a2345SVinicius Costa Gomes 
6008aab4757SVinicius Costa Gomes 	smp = smp_chan_create(conn);
601d26a2345SVinicius Costa Gomes 
602d26a2345SVinicius Costa Gomes 	if (hcon->link_mode & HCI_LM_MASTER) {
603d26a2345SVinicius Costa Gomes 		struct smp_cmd_pairing cp;
604f01ead31SAnderson Briglia 
6050fb4eb6fSVinicius Costa Gomes 		build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE);
6061c1def09SVinicius Costa Gomes 		smp->preq[0] = SMP_CMD_PAIRING_REQ;
6071c1def09SVinicius Costa Gomes 		memcpy(&smp->preq[1], &cp, sizeof(cp));
608f01ead31SAnderson Briglia 
609eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
610eb492e01SAnderson Briglia 	} else {
611eb492e01SAnderson Briglia 		struct smp_cmd_security_req cp;
6120fb4eb6fSVinicius Costa Gomes 		cp.auth_req = SMP_AUTH_NONE;
613eb492e01SAnderson Briglia 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
614eb492e01SAnderson Briglia 	}
615eb492e01SAnderson Briglia 
61602bc7455SVinicius Costa Gomes done:
617f1cb9af5SVinicius Costa Gomes 	hcon->pending_sec_level = sec_level;
618f1cb9af5SVinicius Costa Gomes 
619eb492e01SAnderson Briglia 	return 0;
620eb492e01SAnderson Briglia }
621eb492e01SAnderson Briglia 
6227034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
6237034b911SVinicius Costa Gomes {
62416b90839SVinicius Costa Gomes 	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
6251c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
62616b90839SVinicius Costa Gomes 
62716b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
62816b90839SVinicius Costa Gomes 
6291c1def09SVinicius Costa Gomes 	memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
63016b90839SVinicius Costa Gomes 
6317034b911SVinicius Costa Gomes 	return 0;
6327034b911SVinicius Costa Gomes }
6337034b911SVinicius Costa Gomes 
6347034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
6357034b911SVinicius Costa Gomes {
63616b90839SVinicius Costa Gomes 	struct smp_cmd_master_ident *rp = (void *) skb->data;
6371c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
6387034b911SVinicius Costa Gomes 
63916b90839SVinicius Costa Gomes 	skb_pull(skb, sizeof(*rp));
64016b90839SVinicius Costa Gomes 
6411c1def09SVinicius Costa Gomes 	hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
6421c1def09SVinicius Costa Gomes 						rp->ediv, rp->rand, smp->tk);
6437034b911SVinicius Costa Gomes 
6447034b911SVinicius Costa Gomes 	smp_distribute_keys(conn, 1);
6457034b911SVinicius Costa Gomes 
6467034b911SVinicius Costa Gomes 	return 0;
6477034b911SVinicius Costa Gomes }
6487034b911SVinicius Costa Gomes 
649eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
650eb492e01SAnderson Briglia {
651eb492e01SAnderson Briglia 	__u8 code = skb->data[0];
652eb492e01SAnderson Briglia 	__u8 reason;
653eb492e01SAnderson Briglia 	int err = 0;
654eb492e01SAnderson Briglia 
6552e65c9d2SAndre Guedes 	if (!lmp_host_le_capable(conn->hcon->hdev)) {
6562e65c9d2SAndre Guedes 		err = -ENOTSUPP;
6572e65c9d2SAndre Guedes 		reason = SMP_PAIRING_NOTSUPP;
6582e65c9d2SAndre Guedes 		goto done;
6592e65c9d2SAndre Guedes 	}
6602e65c9d2SAndre Guedes 
661eb492e01SAnderson Briglia 	skb_pull(skb, sizeof(code));
662eb492e01SAnderson Briglia 
663eb492e01SAnderson Briglia 	switch (code) {
664eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_REQ:
665da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_req(conn, skb);
666eb492e01SAnderson Briglia 		break;
667eb492e01SAnderson Briglia 
668eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_FAIL:
6694f957a76SBrian Gix 		smp_failure(conn, skb->data[0], 0);
670da85e5e5SVinicius Costa Gomes 		reason = 0;
671da85e5e5SVinicius Costa Gomes 		err = -EPERM;
672eb492e01SAnderson Briglia 		break;
673eb492e01SAnderson Briglia 
674eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RSP:
675da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_rsp(conn, skb);
67688ba43b6SAnderson Briglia 		break;
67788ba43b6SAnderson Briglia 
67888ba43b6SAnderson Briglia 	case SMP_CMD_SECURITY_REQ:
679da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_security_req(conn, skb);
68088ba43b6SAnderson Briglia 		break;
68188ba43b6SAnderson Briglia 
682eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_CONFIRM:
683da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_confirm(conn, skb);
68488ba43b6SAnderson Briglia 		break;
68588ba43b6SAnderson Briglia 
686eb492e01SAnderson Briglia 	case SMP_CMD_PAIRING_RANDOM:
687da85e5e5SVinicius Costa Gomes 		reason = smp_cmd_pairing_random(conn, skb);
68888ba43b6SAnderson Briglia 		break;
68988ba43b6SAnderson Briglia 
690eb492e01SAnderson Briglia 	case SMP_CMD_ENCRYPT_INFO:
6917034b911SVinicius Costa Gomes 		reason = smp_cmd_encrypt_info(conn, skb);
6927034b911SVinicius Costa Gomes 		break;
6937034b911SVinicius Costa Gomes 
694eb492e01SAnderson Briglia 	case SMP_CMD_MASTER_IDENT:
6957034b911SVinicius Costa Gomes 		reason = smp_cmd_master_ident(conn, skb);
6967034b911SVinicius Costa Gomes 		break;
6977034b911SVinicius Costa Gomes 
698eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_INFO:
699eb492e01SAnderson Briglia 	case SMP_CMD_IDENT_ADDR_INFO:
700eb492e01SAnderson Briglia 	case SMP_CMD_SIGN_INFO:
7017034b911SVinicius Costa Gomes 		/* Just ignored */
7027034b911SVinicius Costa Gomes 		reason = 0;
7037034b911SVinicius Costa Gomes 		break;
7047034b911SVinicius Costa Gomes 
705eb492e01SAnderson Briglia 	default:
706eb492e01SAnderson Briglia 		BT_DBG("Unknown command code 0x%2.2x", code);
707eb492e01SAnderson Briglia 
708eb492e01SAnderson Briglia 		reason = SMP_CMD_NOTSUPP;
7093a0259bbSVinicius Costa Gomes 		err = -EOPNOTSUPP;
7103a0259bbSVinicius Costa Gomes 		goto done;
7113a0259bbSVinicius Costa Gomes 	}
7123a0259bbSVinicius Costa Gomes 
7133a0259bbSVinicius Costa Gomes done:
7143a0259bbSVinicius Costa Gomes 	if (reason)
7154f957a76SBrian Gix 		smp_failure(conn, reason, 1);
716eb492e01SAnderson Briglia 
717eb492e01SAnderson Briglia 	kfree_skb(skb);
718eb492e01SAnderson Briglia 	return err;
719eb492e01SAnderson Briglia }
7207034b911SVinicius Costa Gomes 
7217034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
7227034b911SVinicius Costa Gomes {
7237034b911SVinicius Costa Gomes 	struct smp_cmd_pairing *req, *rsp;
7241c1def09SVinicius Costa Gomes 	struct smp_chan *smp = conn->smp_chan;
7257034b911SVinicius Costa Gomes 	__u8 *keydist;
7267034b911SVinicius Costa Gomes 
7277034b911SVinicius Costa Gomes 	BT_DBG("conn %p force %d", conn, force);
7287034b911SVinicius Costa Gomes 
729d26a2345SVinicius Costa Gomes 	if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
730d26a2345SVinicius Costa Gomes 		return 0;
731d26a2345SVinicius Costa Gomes 
7321c1def09SVinicius Costa Gomes 	rsp = (void *) &smp->prsp[1];
7337034b911SVinicius Costa Gomes 
7347034b911SVinicius Costa Gomes 	/* The responder sends its keys first */
7357034b911SVinicius Costa Gomes 	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
7367034b911SVinicius Costa Gomes 		return 0;
7377034b911SVinicius Costa Gomes 
7381c1def09SVinicius Costa Gomes 	req = (void *) &smp->preq[1];
7397034b911SVinicius Costa Gomes 
7407034b911SVinicius Costa Gomes 	if (conn->hcon->out) {
7417034b911SVinicius Costa Gomes 		keydist = &rsp->init_key_dist;
7427034b911SVinicius Costa Gomes 		*keydist &= req->init_key_dist;
7437034b911SVinicius Costa Gomes 	} else {
7447034b911SVinicius Costa Gomes 		keydist = &rsp->resp_key_dist;
7457034b911SVinicius Costa Gomes 		*keydist &= req->resp_key_dist;
7467034b911SVinicius Costa Gomes 	}
7477034b911SVinicius Costa Gomes 
7487034b911SVinicius Costa Gomes 
7497034b911SVinicius Costa Gomes 	BT_DBG("keydist 0x%x", *keydist);
7507034b911SVinicius Costa Gomes 
7517034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ENC_KEY) {
7527034b911SVinicius Costa Gomes 		struct smp_cmd_encrypt_info enc;
7537034b911SVinicius Costa Gomes 		struct smp_cmd_master_ident ident;
7547034b911SVinicius Costa Gomes 		__le16 ediv;
7557034b911SVinicius Costa Gomes 
7567034b911SVinicius Costa Gomes 		get_random_bytes(enc.ltk, sizeof(enc.ltk));
7577034b911SVinicius Costa Gomes 		get_random_bytes(&ediv, sizeof(ediv));
7587034b911SVinicius Costa Gomes 		get_random_bytes(ident.rand, sizeof(ident.rand));
7597034b911SVinicius Costa Gomes 
7607034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
7617034b911SVinicius Costa Gomes 
7621c1def09SVinicius Costa Gomes 		hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
763726b4ffcSVinicius Costa Gomes 						ediv, ident.rand, enc.ltk);
76416b90839SVinicius Costa Gomes 
7657034b911SVinicius Costa Gomes 		ident.ediv = cpu_to_le16(ediv);
7667034b911SVinicius Costa Gomes 
7677034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
7687034b911SVinicius Costa Gomes 
7697034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ENC_KEY;
7707034b911SVinicius Costa Gomes 	}
7717034b911SVinicius Costa Gomes 
7727034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_ID_KEY) {
7737034b911SVinicius Costa Gomes 		struct smp_cmd_ident_addr_info addrinfo;
7747034b911SVinicius Costa Gomes 		struct smp_cmd_ident_info idinfo;
7757034b911SVinicius Costa Gomes 
7767034b911SVinicius Costa Gomes 		/* Send a dummy key */
7777034b911SVinicius Costa Gomes 		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
7787034b911SVinicius Costa Gomes 
7797034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
7807034b911SVinicius Costa Gomes 
7817034b911SVinicius Costa Gomes 		/* Just public address */
7827034b911SVinicius Costa Gomes 		memset(&addrinfo, 0, sizeof(addrinfo));
7837034b911SVinicius Costa Gomes 		bacpy(&addrinfo.bdaddr, conn->src);
7847034b911SVinicius Costa Gomes 
7857034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
7867034b911SVinicius Costa Gomes 								&addrinfo);
7877034b911SVinicius Costa Gomes 
7887034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_ID_KEY;
7897034b911SVinicius Costa Gomes 	}
7907034b911SVinicius Costa Gomes 
7917034b911SVinicius Costa Gomes 	if (*keydist & SMP_DIST_SIGN) {
7927034b911SVinicius Costa Gomes 		struct smp_cmd_sign_info sign;
7937034b911SVinicius Costa Gomes 
7947034b911SVinicius Costa Gomes 		/* Send a dummy key */
7957034b911SVinicius Costa Gomes 		get_random_bytes(sign.csrk, sizeof(sign.csrk));
7967034b911SVinicius Costa Gomes 
7977034b911SVinicius Costa Gomes 		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
7987034b911SVinicius Costa Gomes 
7997034b911SVinicius Costa Gomes 		*keydist &= ~SMP_DIST_SIGN;
8007034b911SVinicius Costa Gomes 	}
8017034b911SVinicius Costa Gomes 
802d26a2345SVinicius Costa Gomes 	if (conn->hcon->out || force) {
803d26a2345SVinicius Costa Gomes 		clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
8046c9d42a1SGustavo F. Padovan 		cancel_delayed_work_sync(&conn->security_timer);
8058aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
806d26a2345SVinicius Costa Gomes 	}
807d26a2345SVinicius Costa Gomes 
8087034b911SVinicius Costa Gomes 	return 0;
8097034b911SVinicius Costa Gomes }
810