diff options
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 235 |
1 files changed, 209 insertions, 26 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 0b96737d0ad3..32c47de30344 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <net/bluetooth/bluetooth.h> | 23 | #include <net/bluetooth/bluetooth.h> |
24 | #include <net/bluetooth/hci_core.h> | 24 | #include <net/bluetooth/hci_core.h> |
25 | #include <net/bluetooth/l2cap.h> | 25 | #include <net/bluetooth/l2cap.h> |
26 | #include <net/bluetooth/mgmt.h> | ||
26 | #include <net/bluetooth/smp.h> | 27 | #include <net/bluetooth/smp.h> |
27 | #include <linux/crypto.h> | 28 | #include <linux/crypto.h> |
28 | #include <linux/scatterlist.h> | 29 | #include <linux/scatterlist.h> |
@@ -184,28 +185,50 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) | |||
184 | skb->priority = HCI_PRIO_MAX; | 185 | skb->priority = HCI_PRIO_MAX; |
185 | hci_send_acl(conn->hchan, skb, 0); | 186 | hci_send_acl(conn->hchan, skb, 0); |
186 | 187 | ||
187 | mod_timer(&conn->security_timer, jiffies + | 188 | cancel_delayed_work_sync(&conn->security_timer); |
189 | schedule_delayed_work(&conn->security_timer, | ||
188 | msecs_to_jiffies(SMP_TIMEOUT)); | 190 | msecs_to_jiffies(SMP_TIMEOUT)); |
189 | } | 191 | } |
190 | 192 | ||
193 | static __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 | |||
201 | static __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 | |||
191 | static void build_pairing_cmd(struct l2cap_conn *conn, | 213 | static void build_pairing_cmd(struct l2cap_conn *conn, |
192 | struct smp_cmd_pairing *req, | 214 | struct smp_cmd_pairing *req, |
193 | struct smp_cmd_pairing *rsp, | 215 | struct smp_cmd_pairing *rsp, |
194 | __u8 authreq) | 216 | __u8 authreq) |
195 | { | 217 | { |
196 | u8 dist_keys; | 218 | u8 dist_keys = 0; |
197 | 219 | ||
198 | dist_keys = 0; | ||
199 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) { | 220 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) { |
200 | dist_keys = SMP_DIST_ENC_KEY; | 221 | dist_keys = SMP_DIST_ENC_KEY; |
201 | authreq |= SMP_AUTH_BONDING; | 222 | authreq |= SMP_AUTH_BONDING; |
223 | } else { | ||
224 | authreq &= ~SMP_AUTH_BONDING; | ||
202 | } | 225 | } |
203 | 226 | ||
204 | if (rsp == NULL) { | 227 | if (rsp == NULL) { |
205 | req->io_capability = conn->hcon->io_capability; | 228 | req->io_capability = conn->hcon->io_capability; |
206 | req->oob_flag = SMP_OOB_NOT_PRESENT; | 229 | req->oob_flag = SMP_OOB_NOT_PRESENT; |
207 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 230 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
208 | req->init_key_dist = dist_keys; | 231 | req->init_key_dist = 0; |
209 | req->resp_key_dist = dist_keys; | 232 | req->resp_key_dist = dist_keys; |
210 | req->auth_req = authreq; | 233 | req->auth_req = authreq; |
211 | return; | 234 | return; |
@@ -214,7 +237,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
214 | rsp->io_capability = conn->hcon->io_capability; | 237 | rsp->io_capability = conn->hcon->io_capability; |
215 | rsp->oob_flag = SMP_OOB_NOT_PRESENT; | 238 | rsp->oob_flag = SMP_OOB_NOT_PRESENT; |
216 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 239 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
217 | rsp->init_key_dist = req->init_key_dist & dist_keys; | 240 | rsp->init_key_dist = 0; |
218 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; | 241 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; |
219 | rsp->auth_req = authreq; | 242 | rsp->auth_req = authreq; |
220 | } | 243 | } |
@@ -240,10 +263,99 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) | |||
240 | 263 | ||
241 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); | 264 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); |
242 | mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason); | 265 | mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason); |
243 | del_timer(&conn->security_timer); | 266 | cancel_delayed_work_sync(&conn->security_timer); |
244 | smp_chan_destroy(conn); | 267 | smp_chan_destroy(conn); |
245 | } | 268 | } |
246 | 269 | ||
270 | #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 | |||
277 | static 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 | |||
285 | static 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 | |||
247 | static void confirm_work(struct work_struct *work) | 359 | static void confirm_work(struct work_struct *work) |
248 | { | 360 | { |
249 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); | 361 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); |
@@ -276,6 +388,8 @@ static void confirm_work(struct work_struct *work) | |||
276 | goto error; | 388 | goto error; |
277 | } | 389 | } |
278 | 390 | ||
391 | clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | ||
392 | |||
279 | swap128(res, cp.confirm_val); | 393 | swap128(res, cp.confirm_val); |
280 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | 394 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); |
281 | 395 | ||
@@ -381,6 +495,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | |||
381 | 495 | ||
382 | smp->conn = conn; | 496 | smp->conn = conn; |
383 | conn->smp_chan = smp; | 497 | conn->smp_chan = smp; |
498 | conn->hcon->smp_conn = conn; | ||
384 | 499 | ||
385 | hci_conn_hold(conn->hcon); | 500 | hci_conn_hold(conn->hcon); |
386 | 501 | ||
@@ -398,18 +513,64 @@ void smp_chan_destroy(struct l2cap_conn *conn) | |||
398 | 513 | ||
399 | kfree(smp); | 514 | kfree(smp); |
400 | conn->smp_chan = NULL; | 515 | conn->smp_chan = NULL; |
516 | conn->hcon->smp_conn = NULL; | ||
401 | hci_conn_put(conn->hcon); | 517 | hci_conn_put(conn->hcon); |
402 | } | 518 | } |
403 | 519 | ||
520 | int 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 | |||
404 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | 561 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) |
405 | { | 562 | { |
406 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 563 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
407 | struct smp_chan *smp; | 564 | struct smp_chan *smp; |
408 | u8 key_size; | 565 | u8 key_size; |
566 | u8 auth = SMP_AUTH_NONE; | ||
409 | int ret; | 567 | int ret; |
410 | 568 | ||
411 | BT_DBG("conn %p", conn); | 569 | BT_DBG("conn %p", conn); |
412 | 570 | ||
571 | if (conn->hcon->link_mode & HCI_LM_MASTER) | ||
572 | return SMP_CMD_NOTSUPP; | ||
573 | |||
413 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) | 574 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) |
414 | smp = smp_chan_create(conn); | 575 | smp = smp_chan_create(conn); |
415 | 576 | ||
@@ -419,19 +580,16 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
419 | memcpy(&smp->preq[1], req, sizeof(*req)); | 580 | memcpy(&smp->preq[1], req, sizeof(*req)); |
420 | skb_pull(skb, sizeof(*req)); | 581 | skb_pull(skb, sizeof(*req)); |
421 | 582 | ||
422 | if (req->oob_flag) | 583 | /* We didn't start the pairing, so match remote */ |
423 | return SMP_OOB_NOT_AVAIL; | 584 | if (req->auth_req & SMP_AUTH_BONDING) |
585 | auth = req->auth_req; | ||
424 | 586 | ||
425 | /* We didn't start the pairing, so no requirements */ | 587 | build_pairing_cmd(conn, req, &rsp, auth); |
426 | build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE); | ||
427 | 588 | ||
428 | key_size = min(req->max_key_size, rsp.max_key_size); | 589 | key_size = min(req->max_key_size, rsp.max_key_size); |
429 | if (check_enc_key_size(conn, key_size)) | 590 | if (check_enc_key_size(conn, key_size)) |
430 | return SMP_ENC_KEY_SIZE; | 591 | return SMP_ENC_KEY_SIZE; |
431 | 592 | ||
432 | /* Just works */ | ||
433 | memset(smp->tk, 0, sizeof(smp->tk)); | ||
434 | |||
435 | ret = smp_rand(smp->prnd); | 593 | ret = smp_rand(smp->prnd); |
436 | if (ret) | 594 | if (ret) |
437 | return SMP_UNSPECIFIED; | 595 | return SMP_UNSPECIFIED; |
@@ -441,6 +599,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
441 | 599 | ||
442 | smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); | 600 | smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); |
443 | 601 | ||
602 | /* 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 | |||
444 | return 0; | 607 | return 0; |
445 | } | 608 | } |
446 | 609 | ||
@@ -449,11 +612,14 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
449 | struct smp_cmd_pairing *req, *rsp = (void *) skb->data; | 612 | struct smp_cmd_pairing *req, *rsp = (void *) skb->data; |
450 | struct smp_chan *smp = conn->smp_chan; | 613 | struct smp_chan *smp = conn->smp_chan; |
451 | struct hci_dev *hdev = conn->hcon->hdev; | 614 | struct hci_dev *hdev = conn->hcon->hdev; |
452 | u8 key_size; | 615 | u8 key_size, auth = SMP_AUTH_NONE; |
453 | int ret; | 616 | int ret; |
454 | 617 | ||
455 | BT_DBG("conn %p", conn); | 618 | BT_DBG("conn %p", conn); |
456 | 619 | ||
620 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) | ||
621 | return SMP_CMD_NOTSUPP; | ||
622 | |||
457 | skb_pull(skb, sizeof(*rsp)); | 623 | skb_pull(skb, sizeof(*rsp)); |
458 | 624 | ||
459 | req = (void *) &smp->preq[1]; | 625 | req = (void *) &smp->preq[1]; |
@@ -462,12 +628,6 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
462 | if (check_enc_key_size(conn, key_size)) | 628 | if (check_enc_key_size(conn, key_size)) |
463 | return SMP_ENC_KEY_SIZE; | 629 | return SMP_ENC_KEY_SIZE; |
464 | 630 | ||
465 | if (rsp->oob_flag) | ||
466 | return SMP_OOB_NOT_AVAIL; | ||
467 | |||
468 | /* Just works */ | ||
469 | memset(smp->tk, 0, sizeof(smp->tk)); | ||
470 | |||
471 | ret = smp_rand(smp->prnd); | 631 | ret = smp_rand(smp->prnd); |
472 | if (ret) | 632 | if (ret) |
473 | return SMP_UNSPECIFIED; | 633 | return SMP_UNSPECIFIED; |
@@ -475,6 +635,22 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
475 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; | 635 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
476 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); | 636 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); |
477 | 637 | ||
638 | 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 | |||
478 | queue_work(hdev->workqueue, &smp->confirm); | 654 | queue_work(hdev->workqueue, &smp->confirm); |
479 | 655 | ||
480 | return 0; | 656 | return 0; |
@@ -496,8 +672,10 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | |||
496 | swap128(smp->prnd, random); | 672 | swap128(smp->prnd, random); |
497 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), | 673 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), |
498 | random); | 674 | random); |
499 | } else { | 675 | } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { |
500 | queue_work(hdev->workqueue, &smp->confirm); | 676 | queue_work(hdev->workqueue, &smp->confirm); |
677 | } else { | ||
678 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | ||
501 | } | 679 | } |
502 | 680 | ||
503 | return 0; | 681 | return 0; |
@@ -550,7 +728,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
550 | 728 | ||
551 | BT_DBG("conn %p", conn); | 729 | BT_DBG("conn %p", conn); |
552 | 730 | ||
553 | hcon->pending_sec_level = BT_SECURITY_MEDIUM; | 731 | hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); |
554 | 732 | ||
555 | if (smp_ltk_encrypt(conn)) | 733 | if (smp_ltk_encrypt(conn)) |
556 | return 0; | 734 | return 0; |
@@ -577,6 +755,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
577 | { | 755 | { |
578 | struct hci_conn *hcon = conn->hcon; | 756 | struct hci_conn *hcon = conn->hcon; |
579 | struct smp_chan *smp = conn->smp_chan; | 757 | struct smp_chan *smp = conn->smp_chan; |
758 | __u8 authreq; | ||
580 | 759 | ||
581 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); | 760 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); |
582 | 761 | ||
@@ -597,18 +776,22 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
597 | return 0; | 776 | return 0; |
598 | 777 | ||
599 | smp = smp_chan_create(conn); | 778 | smp = smp_chan_create(conn); |
779 | if (!smp) | ||
780 | return 1; | ||
781 | |||
782 | authreq = seclevel_to_authreq(sec_level); | ||
600 | 783 | ||
601 | if (hcon->link_mode & HCI_LM_MASTER) { | 784 | if (hcon->link_mode & HCI_LM_MASTER) { |
602 | struct smp_cmd_pairing cp; | 785 | struct smp_cmd_pairing cp; |
603 | 786 | ||
604 | build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE); | 787 | build_pairing_cmd(conn, &cp, NULL, authreq); |
605 | smp->preq[0] = SMP_CMD_PAIRING_REQ; | 788 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
606 | memcpy(&smp->preq[1], &cp, sizeof(cp)); | 789 | memcpy(&smp->preq[1], &cp, sizeof(cp)); |
607 | 790 | ||
608 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 791 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
609 | } else { | 792 | } else { |
610 | struct smp_cmd_security_req cp; | 793 | struct smp_cmd_security_req cp; |
611 | cp.auth_req = SMP_AUTH_NONE; | 794 | cp.auth_req = authreq; |
612 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); | 795 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); |
613 | } | 796 | } |
614 | 797 | ||
@@ -637,7 +820,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) | |||
637 | 820 | ||
638 | skb_pull(skb, sizeof(*rp)); | 821 | skb_pull(skb, sizeof(*rp)); |
639 | 822 | ||
640 | hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size, | 823 | hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size, |
641 | rp->ediv, rp->rand, smp->tk); | 824 | rp->ediv, rp->rand, smp->tk); |
642 | 825 | ||
643 | smp_distribute_keys(conn, 1); | 826 | smp_distribute_keys(conn, 1); |
@@ -800,7 +983,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
800 | 983 | ||
801 | if (conn->hcon->out || force) { | 984 | if (conn->hcon->out || force) { |
802 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); | 985 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); |
803 | del_timer(&conn->security_timer); | 986 | cancel_delayed_work_sync(&conn->security_timer); |
804 | smp_chan_destroy(conn); | 987 | smp_chan_destroy(conn); |
805 | } | 988 | } |
806 | 989 | ||