diff options
author | Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> | 2011-04-28 06:07:55 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-28 14:02:12 -0400 |
commit | 13d39315c22b128f4796fc008b04914a7c32bb1a (patch) | |
tree | 81f6ed817d6814ba2af5c0bf8a6b7ede9999a395 /net/bluetooth | |
parent | 9003c4e220c2954a53c5da0d739ed15a46c13429 (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.c | 61 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 4 |
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 */ | ||
540 | static 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 */ |
539 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | 554 | int 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 | |||
593 | auth: | ||
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; | 600 | encrypt: |
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 | } |
566 | EXPORT_SYMBOL(hci_conn_security); | 607 | EXPORT_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 | ||