blob: 32c47de303440846fce21b5c02e53c89e08e92d8 [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>
Brian Gix2b64d152011-12-21 16:12:12 -080026#include <net/bluetooth/mgmt.h>
Anderson Brigliaeb492e02011-06-09 18:50:40 -030027#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030028#include <linux/crypto.h>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100029#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030030#include <crypto/b128ops.h>
31
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030032#define SMP_TIMEOUT 30000 /* 30 seconds */
33
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030034static inline void swap128(u8 src[16], u8 dst[16])
35{
36 int i;
37 for (i = 0; i < 16; i++)
38 dst[15 - i] = src[i];
39}
40
41static inline void swap56(u8 src[7], u8 dst[7])
42{
43 int i;
44 for (i = 0; i < 7; i++)
45 dst[6 - i] = src[i];
46}
47
48static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
49{
50 struct blkcipher_desc desc;
51 struct scatterlist sg;
52 int err, iv_len;
53 unsigned char iv[128];
54
55 if (tfm == NULL) {
56 BT_ERR("tfm %p", tfm);
57 return -EINVAL;
58 }
59
60 desc.tfm = tfm;
61 desc.flags = 0;
62
63 err = crypto_blkcipher_setkey(tfm, k, 16);
64 if (err) {
65 BT_ERR("cipher setkey failed: %d", err);
66 return err;
67 }
68
69 sg_init_one(&sg, r, 16);
70
71 iv_len = crypto_blkcipher_ivsize(tfm);
72 if (iv_len) {
73 memset(&iv, 0xff, iv_len);
74 crypto_blkcipher_set_iv(tfm, iv, iv_len);
75 }
76
77 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
78 if (err)
79 BT_ERR("Encrypt data error %d", err);
80
81 return err;
82}
83
84static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
85 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
86 u8 _rat, bdaddr_t *ra, u8 res[16])
87{
88 u8 p1[16], p2[16];
89 int err;
90
91 memset(p1, 0, 16);
92
93 /* p1 = pres || preq || _rat || _iat */
94 swap56(pres, p1);
95 swap56(preq, p1 + 7);
96 p1[14] = _rat;
97 p1[15] = _iat;
98
99 memset(p2, 0, 16);
100
101 /* p2 = padding || ia || ra */
102 baswap((bdaddr_t *) (p2 + 4), ia);
103 baswap((bdaddr_t *) (p2 + 10), ra);
104
105 /* res = r XOR p1 */
106 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
107
108 /* res = e(k, res) */
109 err = smp_e(tfm, k, res);
110 if (err) {
111 BT_ERR("Encrypt data error");
112 return err;
113 }
114
115 /* res = res XOR p2 */
116 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
117
118 /* res = e(k, res) */
119 err = smp_e(tfm, k, res);
120 if (err)
121 BT_ERR("Encrypt data error");
122
123 return err;
124}
125
126static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
127 u8 r1[16], u8 r2[16], u8 _r[16])
128{
129 int err;
130
131 /* Just least significant octets from r1 and r2 are considered */
132 memcpy(_r, r1 + 8, 8);
133 memcpy(_r + 8, r2 + 8, 8);
134
135 err = smp_e(tfm, k, _r);
136 if (err)
137 BT_ERR("Encrypt data error");
138
139 return err;
140}
141
142static int smp_rand(u8 *buf)
143{
144 get_random_bytes(buf, 16);
145
146 return 0;
147}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300148
149static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
150 u16 dlen, void *data)
151{
152 struct sk_buff *skb;
153 struct l2cap_hdr *lh;
154 int len;
155
156 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
157
158 if (len > conn->mtu)
159 return NULL;
160
161 skb = bt_skb_alloc(len, GFP_ATOMIC);
162 if (!skb)
163 return NULL;
164
165 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
166 lh->len = cpu_to_le16(sizeof(code) + dlen);
167 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
168
169 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
170
171 memcpy(skb_put(skb, dlen), data, dlen);
172
173 return skb;
174}
175
176static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
177{
178 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
179
180 BT_DBG("code 0x%2.2x", code);
181
182 if (!skb)
183 return;
184
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200185 skb->priority = HCI_PRIO_MAX;
186 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300187
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200188 cancel_delayed_work_sync(&conn->security_timer);
189 schedule_delayed_work(&conn->security_timer,
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300190 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300191}
192
Brian Gix2b64d152011-12-21 16:12:12 -0800193static __u8 authreq_to_seclevel(__u8 authreq)
194{
195 if (authreq & SMP_AUTH_MITM)
196 return BT_SECURITY_HIGH;
197 else
198 return BT_SECURITY_MEDIUM;
199}
200
201static __u8 seclevel_to_authreq(__u8 sec_level)
202{
203 switch (sec_level) {
204 case BT_SECURITY_HIGH:
205 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
206 case BT_SECURITY_MEDIUM:
207 return SMP_AUTH_BONDING;
208 default:
209 return SMP_AUTH_NONE;
210 }
211}
212
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300213static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300214 struct smp_cmd_pairing *req,
215 struct smp_cmd_pairing *rsp,
216 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300217{
Brian Gix2b64d152011-12-21 16:12:12 -0800218 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300219
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300220 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300221 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300222 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800223 } else {
224 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300225 }
226
227 if (rsp == NULL) {
228 req->io_capability = conn->hcon->io_capability;
229 req->oob_flag = SMP_OOB_NOT_PRESENT;
230 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800231 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300232 req->resp_key_dist = dist_keys;
233 req->auth_req = authreq;
234 return;
235 }
236
237 rsp->io_capability = conn->hcon->io_capability;
238 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
239 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800240 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300241 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
242 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300243}
244
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300245static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
246{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300247 struct smp_chan *smp = conn->smp_chan;
248
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300249 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
250 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
251 return SMP_ENC_KEY_SIZE;
252
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300253 smp->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300254
255 return 0;
256}
257
Brian Gix4f957a72011-11-23 08:28:36 -0800258static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
259{
260 if (send)
261 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
262 &reason);
263
264 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
265 mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200266 cancel_delayed_work_sync(&conn->security_timer);
Brian Gix4f957a72011-11-23 08:28:36 -0800267 smp_chan_destroy(conn);
268}
269
Brian Gix2b64d152011-12-21 16:12:12 -0800270#define JUST_WORKS 0x00
271#define JUST_CFM 0x01
272#define REQ_PASSKEY 0x02
273#define CFM_PASSKEY 0x03
274#define REQ_OOB 0x04
275#define OVERLAP 0xFF
276
277static const u8 gen_method[5][5] = {
278 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
279 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
280 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
281 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
282 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
283};
284
285static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
286 u8 local_io, u8 remote_io)
287{
288 struct hci_conn *hcon = conn->hcon;
289 struct smp_chan *smp = conn->smp_chan;
290 u8 method;
291 u32 passkey = 0;
292 int ret = 0;
293
294 /* Initialize key for JUST WORKS */
295 memset(smp->tk, 0, sizeof(smp->tk));
296 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
297
298 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
299
300 /* If neither side wants MITM, use JUST WORKS */
301 /* If either side has unknown io_caps, use JUST WORKS */
302 /* Otherwise, look up method from the table */
303 if (!(auth & SMP_AUTH_MITM) ||
304 local_io > SMP_IO_KEYBOARD_DISPLAY ||
305 remote_io > SMP_IO_KEYBOARD_DISPLAY)
306 method = JUST_WORKS;
307 else
308 method = gen_method[local_io][remote_io];
309
310 /* If not bonding, don't ask user to confirm a Zero TK */
311 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
312 method = JUST_WORKS;
313
314 /* If Just Works, Continue with Zero TK */
315 if (method == JUST_WORKS) {
316 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
317 return 0;
318 }
319
320 /* Not Just Works/Confirm results in MITM Authentication */
321 if (method != JUST_CFM)
322 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
323
324 /* If both devices have Keyoard-Display I/O, the master
325 * Confirms and the slave Enters the passkey.
326 */
327 if (method == OVERLAP) {
328 if (hcon->link_mode & HCI_LM_MASTER)
329 method = CFM_PASSKEY;
330 else
331 method = REQ_PASSKEY;
332 }
333
334 /* Generate random passkey. Not valid until confirmed. */
335 if (method == CFM_PASSKEY) {
336 u8 key[16];
337
338 memset(key, 0, sizeof(key));
339 get_random_bytes(&passkey, sizeof(passkey));
340 passkey %= 1000000;
341 put_unaligned_le32(passkey, key);
342 swap128(key, smp->tk);
343 BT_DBG("PassKey: %d", passkey);
344 }
345
346 hci_dev_lock(hcon->hdev);
347
348 if (method == REQ_PASSKEY)
349 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst);
350 else
351 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
352 cpu_to_le32(passkey), 0);
353
354 hci_dev_unlock(hcon->hdev);
355
356 return ret;
357}
358
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300359static void confirm_work(struct work_struct *work)
360{
361 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
362 struct l2cap_conn *conn = smp->conn;
363 struct crypto_blkcipher *tfm;
364 struct smp_cmd_pairing_confirm cp;
365 int ret;
366 u8 res[16], reason;
367
368 BT_DBG("conn %p", conn);
369
370 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
371 if (IS_ERR(tfm)) {
372 reason = SMP_UNSPECIFIED;
373 goto error;
374 }
375
376 smp->tfm = tfm;
377
378 if (conn->hcon->out)
379 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
380 conn->src, conn->hcon->dst_type, conn->dst,
381 res);
382 else
383 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
384 conn->hcon->dst_type, conn->dst, 0, conn->src,
385 res);
386 if (ret) {
387 reason = SMP_UNSPECIFIED;
388 goto error;
389 }
390
Brian Gix2b64d152011-12-21 16:12:12 -0800391 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
392
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300393 swap128(res, cp.confirm_val);
394 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
395
396 return;
397
398error:
Brian Gix4f957a72011-11-23 08:28:36 -0800399 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300400}
401
402static void random_work(struct work_struct *work)
403{
404 struct smp_chan *smp = container_of(work, struct smp_chan, random);
405 struct l2cap_conn *conn = smp->conn;
406 struct hci_conn *hcon = conn->hcon;
407 struct crypto_blkcipher *tfm = smp->tfm;
408 u8 reason, confirm[16], res[16], key[16];
409 int ret;
410
411 if (IS_ERR_OR_NULL(tfm)) {
412 reason = SMP_UNSPECIFIED;
413 goto error;
414 }
415
416 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
417
418 if (hcon->out)
419 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
420 conn->src, hcon->dst_type, conn->dst,
421 res);
422 else
423 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
424 hcon->dst_type, conn->dst, 0, conn->src,
425 res);
426 if (ret) {
427 reason = SMP_UNSPECIFIED;
428 goto error;
429 }
430
431 swap128(res, confirm);
432
433 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
434 BT_ERR("Pairing failed (confirmation values mismatch)");
435 reason = SMP_CONFIRM_FAILED;
436 goto error;
437 }
438
439 if (hcon->out) {
440 u8 stk[16], rand[8];
441 __le16 ediv;
442
443 memset(rand, 0, sizeof(rand));
444 ediv = 0;
445
446 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
447 swap128(key, stk);
448
449 memset(stk + smp->smp_key_size, 0,
450 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
451
452 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
453 reason = SMP_UNSPECIFIED;
454 goto error;
455 }
456
457 hci_le_start_enc(hcon, ediv, rand, stk);
458 hcon->enc_key_size = smp->smp_key_size;
459 } else {
460 u8 stk[16], r[16], rand[8];
461 __le16 ediv;
462
463 memset(rand, 0, sizeof(rand));
464 ediv = 0;
465
466 swap128(smp->prnd, r);
467 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
468
469 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
470 swap128(key, stk);
471
472 memset(stk + smp->smp_key_size, 0,
473 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
474
475 hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
476 ediv, rand, stk);
477 }
478
479 return;
480
481error:
Brian Gix4f957a72011-11-23 08:28:36 -0800482 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300483}
484
485static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
486{
487 struct smp_chan *smp;
488
489 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
490 if (!smp)
491 return NULL;
492
493 INIT_WORK(&smp->confirm, confirm_work);
494 INIT_WORK(&smp->random, random_work);
495
496 smp->conn = conn;
497 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800498 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300499
500 hci_conn_hold(conn->hcon);
501
502 return smp;
503}
504
505void smp_chan_destroy(struct l2cap_conn *conn)
506{
Brian Gixc8eb9692011-11-23 08:28:35 -0800507 struct smp_chan *smp = conn->smp_chan;
508
509 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
510
511 if (smp->tfm)
512 crypto_free_blkcipher(smp->tfm);
513
514 kfree(smp);
515 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800516 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300517 hci_conn_put(conn->hcon);
518}
519
Brian Gix2b64d152011-12-21 16:12:12 -0800520int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
521{
522 struct l2cap_conn *conn = hcon->smp_conn;
523 struct smp_chan *smp;
524 u32 value;
525 u8 key[16];
526
527 BT_DBG("");
528
529 if (!conn)
530 return -ENOTCONN;
531
532 smp = conn->smp_chan;
533
534 switch (mgmt_op) {
535 case MGMT_OP_USER_PASSKEY_REPLY:
536 value = le32_to_cpu(passkey);
537 memset(key, 0, sizeof(key));
538 BT_DBG("PassKey: %d", value);
539 put_unaligned_le32(value, key);
540 swap128(key, smp->tk);
541 /* Fall Through */
542 case MGMT_OP_USER_CONFIRM_REPLY:
543 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
544 break;
545 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
546 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
547 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
548 return 0;
549 default:
550 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
551 return -EOPNOTSUPP;
552 }
553
554 /* If it is our turn to send Pairing Confirm, do so now */
555 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
556 queue_work(hcon->hdev->workqueue, &smp->confirm);
557
558 return 0;
559}
560
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300561static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300562{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300563 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300564 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300565 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800566 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300567 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300568
569 BT_DBG("conn %p", conn);
570
Brian Gix2b64d152011-12-21 16:12:12 -0800571 if (conn->hcon->link_mode & HCI_LM_MASTER)
572 return SMP_CMD_NOTSUPP;
573
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300574 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300575 smp = smp_chan_create(conn);
576
577 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300578
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300579 smp->preq[0] = SMP_CMD_PAIRING_REQ;
580 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300581 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300582
Brian Gix2b64d152011-12-21 16:12:12 -0800583 /* We didn't start the pairing, so match remote */
584 if (req->auth_req & SMP_AUTH_BONDING)
585 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300586
Brian Gix2b64d152011-12-21 16:12:12 -0800587 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300588
589 key_size = min(req->max_key_size, rsp.max_key_size);
590 if (check_enc_key_size(conn, key_size))
591 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300592
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300593 ret = smp_rand(smp->prnd);
594 if (ret)
595 return SMP_UNSPECIFIED;
596
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300597 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
598 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300599
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300600 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300601
Brian Gix2b64d152011-12-21 16:12:12 -0800602 /* Request setup of TK */
603 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
604 if (ret)
605 return SMP_UNSPECIFIED;
606
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300607 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300608}
609
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300610static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300611{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300612 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300613 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300614 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800615 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300616 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300617
618 BT_DBG("conn %p", conn);
619
Brian Gix2b64d152011-12-21 16:12:12 -0800620 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
621 return SMP_CMD_NOTSUPP;
622
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300623 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300624
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300625 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300626
627 key_size = min(req->max_key_size, rsp->max_key_size);
628 if (check_enc_key_size(conn, key_size))
629 return SMP_ENC_KEY_SIZE;
630
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300631 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300632 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300633 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300634
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300635 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
636 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300637
Brian Gix2b64d152011-12-21 16:12:12 -0800638 if ((req->auth_req & SMP_AUTH_BONDING) &&
639 (rsp->auth_req & SMP_AUTH_BONDING))
640 auth = SMP_AUTH_BONDING;
641
642 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
643
644 ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
645 if (ret)
646 return SMP_UNSPECIFIED;
647
648 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
649
650 /* Can't compose response until we have been confirmed */
651 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
652 return 0;
653
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300654 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300655
656 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300657}
658
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300659static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300660{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300661 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300662 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300663
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300664 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
665
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300666 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
667 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300668
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300669 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300670 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300671
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300672 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300673 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300674 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800675 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300676 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800677 } else {
678 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300679 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300680
681 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300682}
683
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300684static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300685{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300686 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300687 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300688
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300689 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300690
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300691 swap128(skb->data, smp->rrnd);
692 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300693
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300694 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300695
696 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300697}
698
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300699static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
700{
701 struct link_key *key;
702 struct key_master_id *master;
703 struct hci_conn *hcon = conn->hcon;
704
705 key = hci_find_link_key_type(hcon->hdev, conn->dst,
706 HCI_LK_SMP_LTK);
707 if (!key)
708 return 0;
709
710 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
711 &hcon->pend))
712 return 1;
713
714 master = (void *) key->data;
715 hci_le_start_enc(hcon, master->ediv, master->rand,
716 key->val);
717 hcon->enc_key_size = key->pin_len;
718
719 return 1;
720
721}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300722static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300723{
724 struct smp_cmd_security_req *rp = (void *) skb->data;
725 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300726 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300727 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300728
729 BT_DBG("conn %p", conn);
730
Brian Gix2b64d152011-12-21 16:12:12 -0800731 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300732
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300733 if (smp_ltk_encrypt(conn))
734 return 0;
735
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300736 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300737 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300738
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300739 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300740
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300741 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300742
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300743 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300744 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300745
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300746 smp->preq[0] = SMP_CMD_PAIRING_REQ;
747 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300748
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300749 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300750
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300751 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300752}
753
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300754int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
755{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300756 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300757 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800758 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300759
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300760 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
761
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300762 if (!lmp_host_le_capable(hcon->hdev))
763 return 1;
764
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300765 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300766 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300767
768 if (hcon->sec_level >= sec_level)
769 return 1;
770
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300771 if (hcon->link_mode & HCI_LM_MASTER)
772 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300773 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300774
775 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
776 return 0;
777
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300778 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800779 if (!smp)
780 return 1;
781
782 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300783
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300784 if (hcon->link_mode & HCI_LM_MASTER) {
785 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300786
Brian Gix2b64d152011-12-21 16:12:12 -0800787 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300788 smp->preq[0] = SMP_CMD_PAIRING_REQ;
789 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300790
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300791 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
792 } else {
793 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800794 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300795 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
796 }
797
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300798done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300799 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300800
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300801 return 0;
802}
803
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300804static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
805{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300806 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300807 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300808
809 skb_pull(skb, sizeof(*rp));
810
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300811 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300812
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300813 return 0;
814}
815
816static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
817{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300818 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300819 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300820
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300821 skb_pull(skb, sizeof(*rp));
822
Hemant Gupta3573b802011-12-23 11:07:24 +0530823 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300824 rp->ediv, rp->rand, smp->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300825
826 smp_distribute_keys(conn, 1);
827
828 return 0;
829}
830
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300831int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
832{
833 __u8 code = skb->data[0];
834 __u8 reason;
835 int err = 0;
836
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300837 if (!lmp_host_le_capable(conn->hcon->hdev)) {
838 err = -ENOTSUPP;
839 reason = SMP_PAIRING_NOTSUPP;
840 goto done;
841 }
842
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300843 skb_pull(skb, sizeof(code));
844
845 switch (code) {
846 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300847 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300848 break;
849
850 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800851 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300852 reason = 0;
853 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300854 break;
855
856 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300857 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300858 break;
859
860 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300861 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300862 break;
863
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300864 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300865 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300866 break;
867
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300868 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300869 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300870 break;
871
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300872 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300873 reason = smp_cmd_encrypt_info(conn, skb);
874 break;
875
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300876 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300877 reason = smp_cmd_master_ident(conn, skb);
878 break;
879
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300880 case SMP_CMD_IDENT_INFO:
881 case SMP_CMD_IDENT_ADDR_INFO:
882 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300883 /* Just ignored */
884 reason = 0;
885 break;
886
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300887 default:
888 BT_DBG("Unknown command code 0x%2.2x", code);
889
890 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300891 err = -EOPNOTSUPP;
892 goto done;
893 }
894
895done:
896 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800897 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300898
899 kfree_skb(skb);
900 return err;
901}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300902
903int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
904{
905 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300906 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300907 __u8 *keydist;
908
909 BT_DBG("conn %p force %d", conn, force);
910
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300911 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
912 return 0;
913
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300914 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300915
916 /* The responder sends its keys first */
917 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
918 return 0;
919
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300920 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300921
922 if (conn->hcon->out) {
923 keydist = &rsp->init_key_dist;
924 *keydist &= req->init_key_dist;
925 } else {
926 keydist = &rsp->resp_key_dist;
927 *keydist &= req->resp_key_dist;
928 }
929
930
931 BT_DBG("keydist 0x%x", *keydist);
932
933 if (*keydist & SMP_DIST_ENC_KEY) {
934 struct smp_cmd_encrypt_info enc;
935 struct smp_cmd_master_ident ident;
936 __le16 ediv;
937
938 get_random_bytes(enc.ltk, sizeof(enc.ltk));
939 get_random_bytes(&ediv, sizeof(ediv));
940 get_random_bytes(ident.rand, sizeof(ident.rand));
941
942 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
943
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300944 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300945 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300946
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300947 ident.ediv = cpu_to_le16(ediv);
948
949 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
950
951 *keydist &= ~SMP_DIST_ENC_KEY;
952 }
953
954 if (*keydist & SMP_DIST_ID_KEY) {
955 struct smp_cmd_ident_addr_info addrinfo;
956 struct smp_cmd_ident_info idinfo;
957
958 /* Send a dummy key */
959 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
960
961 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
962
963 /* Just public address */
964 memset(&addrinfo, 0, sizeof(addrinfo));
965 bacpy(&addrinfo.bdaddr, conn->src);
966
967 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
968 &addrinfo);
969
970 *keydist &= ~SMP_DIST_ID_KEY;
971 }
972
973 if (*keydist & SMP_DIST_SIGN) {
974 struct smp_cmd_sign_info sign;
975
976 /* Send a dummy key */
977 get_random_bytes(sign.csrk, sizeof(sign.csrk));
978
979 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
980
981 *keydist &= ~SMP_DIST_SIGN;
982 }
983
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300984 if (conn->hcon->out || force) {
985 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200986 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300987 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300988 }
989
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300990 return 0;
991}