aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorWaldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>2011-04-28 06:07:55 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-04-28 14:02:12 -0400
commit13d39315c22b128f4796fc008b04914a7c32bb1a (patch)
tree81f6ed817d6814ba2af5c0bf8a6b7ede9999a395 /net/bluetooth
parent9003c4e220c2954a53c5da0d739ed15a46c13429 (diff)
Bluetooth: Map sec_level to link key requirements
Keep the link key type together with connection and use it to map security level to link key requirements. Authenticate and/or encrypt connection if the link is insufficiently secure. Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_conn.c61
-rw-r--r--net/bluetooth/hci_event.c4
2 files changed, 55 insertions, 10 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7a6f56b2f49d..74cd755b38a7 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -287,6 +287,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
287 conn->auth_type = HCI_AT_GENERAL_BONDING; 287 conn->auth_type = HCI_AT_GENERAL_BONDING;
288 conn->io_capability = hdev->io_capability; 288 conn->io_capability = hdev->io_capability;
289 conn->remote_auth = 0xff; 289 conn->remote_auth = 0xff;
290 conn->key_type = 0xff;
290 291
291 conn->power_save = 1; 292 conn->power_save = 1;
292 conn->disc_timeout = HCI_DISCONN_TIMEOUT; 293 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
@@ -535,32 +536,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
535 return 0; 536 return 0;
536} 537}
537 538
539/* Encrypt the the link */
540static void hci_conn_encrypt(struct hci_conn *conn)
541{
542 BT_DBG("conn %p", conn);
543
544 if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
545 struct hci_cp_set_conn_encrypt cp;
546 cp.handle = cpu_to_le16(conn->handle);
547 cp.encrypt = 0x01;
548 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
549 &cp);
550 }
551}
552
538/* Enable security */ 553/* Enable security */
539int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) 554int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
540{ 555{
541 BT_DBG("conn %p", conn); 556 BT_DBG("conn %p", conn);
542 557
558 /* For sdp we don't need the link key. */
543 if (sec_level == BT_SECURITY_SDP) 559 if (sec_level == BT_SECURITY_SDP)
544 return 1; 560 return 1;
545 561
562 /* For non 2.1 devices and low security level we don't need the link
563 key. */
546 if (sec_level == BT_SECURITY_LOW && 564 if (sec_level == BT_SECURITY_LOW &&
547 (!conn->ssp_mode || !conn->hdev->ssp_mode)) 565 (!conn->ssp_mode || !conn->hdev->ssp_mode))
548 return 1; 566 return 1;
549 567
550 if (conn->link_mode & HCI_LM_ENCRYPT) 568 /* For other security levels we need the link key. */
551 return hci_conn_auth(conn, sec_level, auth_type); 569 if (!(conn->link_mode & HCI_LM_AUTH))
552 570 goto auth;
571
572 /* An authenticated combination key has sufficient security for any
573 security level. */
574 if (conn->key_type == HCI_LK_AUTH_COMBINATION)
575 goto encrypt;
576
577 /* An unauthenticated combination key has sufficient security for
578 security level 1 and 2. */
579 if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
580 (sec_level == BT_SECURITY_MEDIUM ||
581 sec_level == BT_SECURITY_LOW))
582 goto encrypt;
583
584 /* A combination key has always sufficient security for the security
585 levels 1 or 2. High security level requires the combination key
586 is generated using maximum PIN code length (16).
587 For pre 2.1 units. */
588 if (conn->key_type == HCI_LK_COMBINATION &&
589 (sec_level != BT_SECURITY_HIGH ||
590 conn->pin_length == 16))
591 goto encrypt;
592
593auth:
553 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 594 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
554 return 0; 595 return 0;
555 596
556 if (hci_conn_auth(conn, sec_level, auth_type)) { 597 hci_conn_auth(conn, sec_level, auth_type);
557 struct hci_cp_set_conn_encrypt cp; 598 return 0;
558 cp.handle = cpu_to_le16(conn->handle); 599
559 cp.encrypt = 1; 600encrypt:
560 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, 601 if (conn->link_mode & HCI_LM_ENCRYPT)
561 sizeof(cp), &cp); 602 return 1;
562 }
563 603
604 hci_conn_encrypt(conn);
564 return 0; 605 return 0;
565} 606}
566EXPORT_SYMBOL(hci_conn_security); 607EXPORT_SYMBOL(hci_conn_security);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 35f98980070c..655af8bc60e2 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2095,6 +2095,10 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
2095 hci_conn_hold(conn); 2095 hci_conn_hold(conn);
2096 conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2096 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2097 pin_len = conn->pin_length; 2097 pin_len = conn->pin_length;
2098
2099 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2100 conn->key_type = ev->key_type;
2101
2098 hci_conn_put(conn); 2102 hci_conn_put(conn);
2099 } 2103 }
2100 2104