aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/smp.c
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-08-19 20:06:51 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-09-21 11:58:11 -0400
commitd26a23454813908a1bf0e2fd8c73233b22c6dbd7 (patch)
tree20a47fdba8e49371265684bc2ed2306d7c042195 /net/bluetooth/smp.c
parente2dcd113d15ef99d23498859e7006955b5367698 (diff)
Bluetooth: Add a flag to indicate that SMP is going on
Add HCI_CONN_LE_SMP_PEND flag to indicate that SMP is pending for that connection. This allows to have information that an SMP procedure is going on for that connection. We use the HCI_CONN_ENCRYPT_PEND to indicate that encryption (HCI_LE_Start_Encryption) is pending for that connection. While a SMP procedure is going on we hold an reference to the connection, to avoid disconnections. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r--net/bluetooth/smp.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 20c82c7000ac..f0c67f62a08e 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -248,6 +248,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
248 248
249 BT_DBG("conn %p", conn); 249 BT_DBG("conn %p", conn);
250 250
251 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
252 hci_conn_hold(conn->hcon);
253
251 conn->preq[0] = SMP_CMD_PAIRING_REQ; 254 conn->preq[0] = SMP_CMD_PAIRING_REQ;
252 memcpy(&conn->preq[1], req, sizeof(*req)); 255 memcpy(&conn->preq[1], req, sizeof(*req));
253 skb_pull(skb, sizeof(*req)); 256 skb_pull(skb, sizeof(*req));
@@ -397,6 +400,9 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
397 memset(stk + conn->smp_key_size, 0, 400 memset(stk + conn->smp_key_size, 0,
398 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size); 401 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
399 402
403 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
404 return SMP_UNSPECIFIED;
405
400 hci_le_start_enc(hcon, ediv, rand, stk); 406 hci_le_start_enc(hcon, ediv, rand, stk);
401 hcon->enc_key_size = conn->smp_key_size; 407 hcon->enc_key_size = conn->smp_key_size;
402 } else { 408 } else {
@@ -430,9 +436,11 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
430 436
431 BT_DBG("conn %p", conn); 437 BT_DBG("conn %p", conn);
432 438
433 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) 439 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
434 return 0; 440 return 0;
435 441
442 hci_conn_hold(hcon);
443
436 skb_pull(skb, sizeof(*rp)); 444 skb_pull(skb, sizeof(*rp));
437 445
438 memset(&cp, 0, sizeof(cp)); 446 memset(&cp, 0, sizeof(cp));
@@ -443,8 +451,6 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
443 451
444 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 452 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
445 453
446 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
447
448 return 0; 454 return 0;
449} 455}
450 456
@@ -461,19 +467,13 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
461 if (IS_ERR(hcon->hdev->tfm)) 467 if (IS_ERR(hcon->hdev->tfm))
462 return 1; 468 return 1;
463 469
464 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
465 return 0;
466
467 if (sec_level == BT_SECURITY_LOW) 470 if (sec_level == BT_SECURITY_LOW)
468 return 1; 471 return 1;
469 472
470 if (hcon->sec_level >= sec_level) 473 if (hcon->sec_level >= sec_level)
471 return 1; 474 return 1;
472 475
473 authreq = seclevel_to_authreq(sec_level);
474
475 if (hcon->link_mode & HCI_LM_MASTER) { 476 if (hcon->link_mode & HCI_LM_MASTER) {
476 struct smp_cmd_pairing cp;
477 struct link_key *key; 477 struct link_key *key;
478 478
479 key = hci_find_link_key_type(hcon->hdev, conn->dst, 479 key = hci_find_link_key_type(hcon->hdev, conn->dst,
@@ -481,12 +481,28 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
481 if (key) { 481 if (key) {
482 struct key_master_id *master = (void *) key->data; 482 struct key_master_id *master = (void *) key->data;
483 483
484 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
485 &hcon->pend))
486 goto done;
487
484 hci_le_start_enc(hcon, master->ediv, master->rand, 488 hci_le_start_enc(hcon, master->ediv, master->rand,
485 key->val); 489 key->val);
486 hcon->enc_key_size = key->pin_len; 490 hcon->enc_key_size = key->pin_len;
487 491
488 goto done; 492 goto done;
489 } 493 }
494 }
495
496 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
497 return 0;
498
499 /* While SMP is going on */
500 hci_conn_hold(hcon);
501
502 authreq = seclevel_to_authreq(sec_level);
503
504 if (hcon->link_mode & HCI_LM_MASTER) {
505 struct smp_cmd_pairing cp;
490 506
491 build_pairing_cmd(conn, &cp, NULL, authreq); 507 build_pairing_cmd(conn, &cp, NULL, authreq);
492 conn->preq[0] = SMP_CMD_PAIRING_REQ; 508 conn->preq[0] = SMP_CMD_PAIRING_REQ;
@@ -501,7 +517,6 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
501 517
502done: 518done:
503 hcon->pending_sec_level = sec_level; 519 hcon->pending_sec_level = sec_level;
504 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
505 520
506 return 0; 521 return 0;
507} 522}
@@ -619,6 +634,9 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
619 if (IS_ERR(conn->hcon->hdev->tfm)) 634 if (IS_ERR(conn->hcon->hdev->tfm))
620 return PTR_ERR(conn->hcon->hdev->tfm); 635 return PTR_ERR(conn->hcon->hdev->tfm);
621 636
637 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
638 return 0;
639
622 rsp = (void *) &conn->prsp[1]; 640 rsp = (void *) &conn->prsp[1];
623 641
624 /* The responder sends its keys first */ 642 /* The responder sends its keys first */
@@ -689,5 +707,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
689 *keydist &= ~SMP_DIST_SIGN; 707 *keydist &= ~SMP_DIST_SIGN;
690 } 708 }
691 709
710 if (conn->hcon->out || force) {
711 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
712 del_timer(&conn->security_timer);
713 hci_conn_put(conn->hcon);
714 }
715
692 return 0; 716 return 0;
693} 717}