blob: 7e558465133f9782b10608e5783113ca4ec0eb2c [file] [log] [blame]
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23#include <net/bluetooth/bluetooth.h>
24#include <net/bluetooth/hci_core.h>
25#include <net/bluetooth/l2cap.h>
26#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030027#include <linux/crypto.h>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100028#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030029#include <crypto/b128ops.h>
30
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030031#define SMP_TIMEOUT 30000 /* 30 seconds */
32
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030033static inline void swap128(u8 src[16], u8 dst[16])
34{
35 int i;
36 for (i = 0; i < 16; i++)
37 dst[15 - i] = src[i];
38}
39
40static inline void swap56(u8 src[7], u8 dst[7])
41{
42 int i;
43 for (i = 0; i < 7; i++)
44 dst[6 - i] = src[i];
45}
46
47static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
48{
49 struct blkcipher_desc desc;
50 struct scatterlist sg;
51 int err, iv_len;
52 unsigned char iv[128];
53
54 if (tfm == NULL) {
55 BT_ERR("tfm %p", tfm);
56 return -EINVAL;
57 }
58
59 desc.tfm = tfm;
60 desc.flags = 0;
61
62 err = crypto_blkcipher_setkey(tfm, k, 16);
63 if (err) {
64 BT_ERR("cipher setkey failed: %d", err);
65 return err;
66 }
67
68 sg_init_one(&sg, r, 16);
69
70 iv_len = crypto_blkcipher_ivsize(tfm);
71 if (iv_len) {
72 memset(&iv, 0xff, iv_len);
73 crypto_blkcipher_set_iv(tfm, iv, iv_len);
74 }
75
76 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
77 if (err)
78 BT_ERR("Encrypt data error %d", err);
79
80 return err;
81}
82
83static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
84 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
85 u8 _rat, bdaddr_t *ra, u8 res[16])
86{
87 u8 p1[16], p2[16];
88 int err;
89
90 memset(p1, 0, 16);
91
92 /* p1 = pres || preq || _rat || _iat */
93 swap56(pres, p1);
94 swap56(preq, p1 + 7);
95 p1[14] = _rat;
96 p1[15] = _iat;
97
98 memset(p2, 0, 16);
99
100 /* p2 = padding || ia || ra */
101 baswap((bdaddr_t *) (p2 + 4), ia);
102 baswap((bdaddr_t *) (p2 + 10), ra);
103
104 /* res = r XOR p1 */
105 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
106
107 /* res = e(k, res) */
108 err = smp_e(tfm, k, res);
109 if (err) {
110 BT_ERR("Encrypt data error");
111 return err;
112 }
113
114 /* res = res XOR p2 */
115 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
116
117 /* res = e(k, res) */
118 err = smp_e(tfm, k, res);
119 if (err)
120 BT_ERR("Encrypt data error");
121
122 return err;
123}
124
125static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
126 u8 r1[16], u8 r2[16], u8 _r[16])
127{
128 int err;
129
130 /* Just least significant octets from r1 and r2 are considered */
131 memcpy(_r, r1 + 8, 8);
132 memcpy(_r + 8, r2 + 8, 8);
133
134 err = smp_e(tfm, k, _r);
135 if (err)
136 BT_ERR("Encrypt data error");
137
138 return err;
139}
140
141static int smp_rand(u8 *buf)
142{
143 get_random_bytes(buf, 16);
144
145 return 0;
146}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300147
148static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
149 u16 dlen, void *data)
150{
151 struct sk_buff *skb;
152 struct l2cap_hdr *lh;
153 int len;
154
155 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
156
157 if (len > conn->mtu)
158 return NULL;
159
160 skb = bt_skb_alloc(len, GFP_ATOMIC);
161 if (!skb)
162 return NULL;
163
164 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
165 lh->len = cpu_to_le16(sizeof(code) + dlen);
166 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
167
168 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
169
170 memcpy(skb_put(skb, dlen), data, dlen);
171
172 return skb;
173}
174
175static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
176{
177 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
178
179 BT_DBG("code 0x%2.2x", code);
180
181 if (!skb)
182 return;
183
184 hci_send_acl(conn->hcon, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300185
186 mod_timer(&conn->security_timer, jiffies +
187 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300188}
189
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300190static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300191 struct smp_cmd_pairing *req,
192 struct smp_cmd_pairing *rsp,
193 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300194{
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300195 u8 dist_keys;
196
197 dist_keys = 0;
198 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
199 dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
200 authreq |= SMP_AUTH_BONDING;
201 }
202
203 if (rsp == NULL) {
204 req->io_capability = conn->hcon->io_capability;
205 req->oob_flag = SMP_OOB_NOT_PRESENT;
206 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
207 req->init_key_dist = dist_keys;
208 req->resp_key_dist = dist_keys;
209 req->auth_req = authreq;
210 return;
211 }
212
213 rsp->io_capability = conn->hcon->io_capability;
214 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
215 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
216 rsp->init_key_dist = req->init_key_dist & dist_keys;
217 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
218 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300219}
220
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300221static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
222{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300223 struct smp_chan *smp = conn->smp_chan;
224
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300225 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
226 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
227 return SMP_ENC_KEY_SIZE;
228
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300229 smp->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300230
231 return 0;
232}
233
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300234static void confirm_work(struct work_struct *work)
235{
236 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
237 struct l2cap_conn *conn = smp->conn;
238 struct crypto_blkcipher *tfm;
239 struct smp_cmd_pairing_confirm cp;
240 int ret;
241 u8 res[16], reason;
242
243 BT_DBG("conn %p", conn);
244
245 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
246 if (IS_ERR(tfm)) {
247 reason = SMP_UNSPECIFIED;
248 goto error;
249 }
250
251 smp->tfm = tfm;
252
253 if (conn->hcon->out)
254 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
255 conn->src, conn->hcon->dst_type, conn->dst,
256 res);
257 else
258 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
259 conn->hcon->dst_type, conn->dst, 0, conn->src,
260 res);
261 if (ret) {
262 reason = SMP_UNSPECIFIED;
263 goto error;
264 }
265
266 swap128(res, cp.confirm_val);
267 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
268
269 return;
270
271error:
272 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
273 smp_chan_destroy(conn);
274}
275
276static void random_work(struct work_struct *work)
277{
278 struct smp_chan *smp = container_of(work, struct smp_chan, random);
279 struct l2cap_conn *conn = smp->conn;
280 struct hci_conn *hcon = conn->hcon;
281 struct crypto_blkcipher *tfm = smp->tfm;
282 u8 reason, confirm[16], res[16], key[16];
283 int ret;
284
285 if (IS_ERR_OR_NULL(tfm)) {
286 reason = SMP_UNSPECIFIED;
287 goto error;
288 }
289
290 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
291
292 if (hcon->out)
293 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
294 conn->src, hcon->dst_type, conn->dst,
295 res);
296 else
297 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
298 hcon->dst_type, conn->dst, 0, conn->src,
299 res);
300 if (ret) {
301 reason = SMP_UNSPECIFIED;
302 goto error;
303 }
304
305 swap128(res, confirm);
306
307 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
308 BT_ERR("Pairing failed (confirmation values mismatch)");
309 reason = SMP_CONFIRM_FAILED;
310 goto error;
311 }
312
313 if (hcon->out) {
314 u8 stk[16], rand[8];
315 __le16 ediv;
316
317 memset(rand, 0, sizeof(rand));
318 ediv = 0;
319
320 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
321 swap128(key, stk);
322
323 memset(stk + smp->smp_key_size, 0,
324 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
325
326 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
327 reason = SMP_UNSPECIFIED;
328 goto error;
329 }
330
331 hci_le_start_enc(hcon, ediv, rand, stk);
332 hcon->enc_key_size = smp->smp_key_size;
333 } else {
334 u8 stk[16], r[16], rand[8];
335 __le16 ediv;
336
337 memset(rand, 0, sizeof(rand));
338 ediv = 0;
339
340 swap128(smp->prnd, r);
341 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
342
343 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
344 swap128(key, stk);
345
346 memset(stk + smp->smp_key_size, 0,
347 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
348
349 hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
350 ediv, rand, stk);
351 }
352
353 return;
354
355error:
356 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
357 smp_chan_destroy(conn);
358}
359
360static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
361{
362 struct smp_chan *smp;
363
364 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
365 if (!smp)
366 return NULL;
367
368 INIT_WORK(&smp->confirm, confirm_work);
369 INIT_WORK(&smp->random, random_work);
370
371 smp->conn = conn;
372 conn->smp_chan = smp;
373
374 hci_conn_hold(conn->hcon);
375
376 return smp;
377}
378
379void smp_chan_destroy(struct l2cap_conn *conn)
380{
381 kfree(conn->smp_chan);
382 hci_conn_put(conn->hcon);
383}
384
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300385static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300386{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300387 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300388 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300389 u8 key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300390 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300391
392 BT_DBG("conn %p", conn);
393
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300394 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300395 smp = smp_chan_create(conn);
396
397 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300398
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300399 smp->preq[0] = SMP_CMD_PAIRING_REQ;
400 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300401 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300402
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300403 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300404 return SMP_OOB_NOT_AVAIL;
405
406 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300407 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300408
409 key_size = min(req->max_key_size, rsp.max_key_size);
410 if (check_enc_key_size(conn, key_size))
411 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300412
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300413 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300414 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300415
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300416 ret = smp_rand(smp->prnd);
417 if (ret)
418 return SMP_UNSPECIFIED;
419
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300420 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
421 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300422
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300423 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300424
425 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300426}
427
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300428static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300429{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300430 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300431 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300432 struct hci_dev *hdev = conn->hcon->hdev;
433 u8 key_size;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300434 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300435
436 BT_DBG("conn %p", conn);
437
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300438 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300439
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300440 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300441
442 key_size = min(req->max_key_size, rsp->max_key_size);
443 if (check_enc_key_size(conn, key_size))
444 return SMP_ENC_KEY_SIZE;
445
446 if (rsp->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300447 return SMP_OOB_NOT_AVAIL;
448
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300449 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300450 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300451
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300452 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300453 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300454 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300455
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300456 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
457 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300458
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300459 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300460
461 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300462}
463
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300464static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300465{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300466 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300467 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300468
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300469 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
470
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300471 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
472 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300473
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300474 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300475 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300476
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300477 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300478 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300479 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300480 } else {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300481 queue_work(hdev->workqueue, &smp->confirm);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300482 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300483
484 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300485}
486
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300487static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300488{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300489 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300490 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300491
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300492 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300493
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300494 swap128(skb->data, smp->rrnd);
495 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300496
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300497 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300498
499 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300500}
501
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300502static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300503{
504 struct smp_cmd_security_req *rp = (void *) skb->data;
505 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300506 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300507 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300508
509 BT_DBG("conn %p", conn);
510
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300511 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300512 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300513
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300514 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300515
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300516 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300517
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300518 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300519 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300520
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300521 smp->preq[0] = SMP_CMD_PAIRING_REQ;
522 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300523
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300524 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300525
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300526 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300527}
528
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300529int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
530{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300531 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300532 struct smp_chan *smp = conn->smp_chan;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300533
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300534 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
535
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300536 if (!lmp_host_le_capable(hcon->hdev))
537 return 1;
538
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300539 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300540 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300541
542 if (hcon->sec_level >= sec_level)
543 return 1;
544
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300545 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300546 struct link_key *key;
547
548 key = hci_find_link_key_type(hcon->hdev, conn->dst,
549 HCI_LK_SMP_LTK);
550 if (key) {
551 struct key_master_id *master = (void *) key->data;
552
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300553 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
554 &hcon->pend))
555 goto done;
556
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300557 hci_le_start_enc(hcon, master->ediv, master->rand,
558 key->val);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300559 hcon->enc_key_size = key->pin_len;
560
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300561 goto done;
562 }
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300563 }
564
565 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
566 return 0;
567
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300568 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300569
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300570 if (hcon->link_mode & HCI_LM_MASTER) {
571 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300572
Vinicius Costa Gomes0fb4eb62011-08-25 20:02:27 -0300573 build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300574 smp->preq[0] = SMP_CMD_PAIRING_REQ;
575 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300576
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300577 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
578 } else {
579 struct smp_cmd_security_req cp;
Vinicius Costa Gomes0fb4eb62011-08-25 20:02:27 -0300580 cp.auth_req = SMP_AUTH_NONE;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300581 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
582 }
583
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300584done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300585 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300586
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300587 return 0;
588}
589
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300590static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
591{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300592 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300593 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300594
595 skb_pull(skb, sizeof(*rp));
596
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300597 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300598
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300599 return 0;
600}
601
602static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
603{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300604 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300605 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300606
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300607 skb_pull(skb, sizeof(*rp));
608
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300609 hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
610 rp->ediv, rp->rand, smp->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300611
612 smp_distribute_keys(conn, 1);
613
614 return 0;
615}
616
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300617int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
618{
619 __u8 code = skb->data[0];
620 __u8 reason;
621 int err = 0;
622
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300623 if (!lmp_host_le_capable(conn->hcon->hdev)) {
624 err = -ENOTSUPP;
625 reason = SMP_PAIRING_NOTSUPP;
626 goto done;
627 }
628
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300629 skb_pull(skb, sizeof(code));
630
631 switch (code) {
632 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300633 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300634 break;
635
636 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300637 reason = 0;
638 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300639 break;
640
641 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300642 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300643 break;
644
645 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300646 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300647 break;
648
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300649 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300650 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300651 break;
652
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300653 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300654 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300655 break;
656
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300657 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300658 reason = smp_cmd_encrypt_info(conn, skb);
659 break;
660
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300661 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300662 reason = smp_cmd_master_ident(conn, skb);
663 break;
664
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300665 case SMP_CMD_IDENT_INFO:
666 case SMP_CMD_IDENT_ADDR_INFO:
667 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300668 /* Just ignored */
669 reason = 0;
670 break;
671
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300672 default:
673 BT_DBG("Unknown command code 0x%2.2x", code);
674
675 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300676 err = -EOPNOTSUPP;
677 goto done;
678 }
679
680done:
681 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300682 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
683 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300684
685 kfree_skb(skb);
686 return err;
687}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300688
689int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
690{
691 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300692 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300693 __u8 *keydist;
694
695 BT_DBG("conn %p force %d", conn, force);
696
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300697 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
698 return 0;
699
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300700 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300701
702 /* The responder sends its keys first */
703 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
704 return 0;
705
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300706 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300707
708 if (conn->hcon->out) {
709 keydist = &rsp->init_key_dist;
710 *keydist &= req->init_key_dist;
711 } else {
712 keydist = &rsp->resp_key_dist;
713 *keydist &= req->resp_key_dist;
714 }
715
716
717 BT_DBG("keydist 0x%x", *keydist);
718
719 if (*keydist & SMP_DIST_ENC_KEY) {
720 struct smp_cmd_encrypt_info enc;
721 struct smp_cmd_master_ident ident;
722 __le16 ediv;
723
724 get_random_bytes(enc.ltk, sizeof(enc.ltk));
725 get_random_bytes(&ediv, sizeof(ediv));
726 get_random_bytes(ident.rand, sizeof(ident.rand));
727
728 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
729
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300730 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300731 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300732
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300733 ident.ediv = cpu_to_le16(ediv);
734
735 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
736
737 *keydist &= ~SMP_DIST_ENC_KEY;
738 }
739
740 if (*keydist & SMP_DIST_ID_KEY) {
741 struct smp_cmd_ident_addr_info addrinfo;
742 struct smp_cmd_ident_info idinfo;
743
744 /* Send a dummy key */
745 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
746
747 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
748
749 /* Just public address */
750 memset(&addrinfo, 0, sizeof(addrinfo));
751 bacpy(&addrinfo.bdaddr, conn->src);
752
753 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
754 &addrinfo);
755
756 *keydist &= ~SMP_DIST_ID_KEY;
757 }
758
759 if (*keydist & SMP_DIST_SIGN) {
760 struct smp_cmd_sign_info sign;
761
762 /* Send a dummy key */
763 get_random_bytes(sign.csrk, sizeof(sign.csrk));
764
765 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
766
767 *keydist &= ~SMP_DIST_SIGN;
768 }
769
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300770 if (conn->hcon->out || force) {
771 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
772 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300773 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300774 }
775
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300776 return 0;
777}