aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-15 15:58:04 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:25 -0500
commit8c1b235594fbab9a13240a1dac12ea9fd99b6440 (patch)
treeeb137a23e0fd8199144a4c3e36902af411e44269 /include/net/bluetooth
parentc89b6e6bda4c8021195778f47567d0cc9dbfe7ec (diff)
Bluetooth: Add enhanced security model for Simple Pairing
The current security model is based around the flags AUTH, ENCRYPT and SECURE. Starting with support for the Bluetooth 2.1 specification this is no longer sufficient. The different security levels are now defined as SDP, LOW, MEDIUM and SECURE. Previously it was possible to set each security independently, but this actually doesn't make a lot of sense. For Bluetooth the encryption depends on a previous successful authentication. Also you can only update your existing link key if you successfully created at least one before. And of course the update of link keys without having proper encryption in place is a security issue. The new security levels from the Bluetooth 2.1 specification are now used internally. All old settings are mapped to the new values and this way it ensures that old applications still work. The only limitation is that it is no longer possible to set authentication without also enabling encryption. No application should have done this anyway since this is actually a security issue. Without encryption the integrity of the authentication can't be guaranteed. As default for a new L2CAP or RFCOMM connection, the LOW security level is used. The only exception here are the service discovery sessions on PSM 1 where SDP level is used. To have similar security strength as with a Bluetooth 2.0 and before combination key, the MEDIUM level should be used. This is according to the Bluetooth specification. The MEDIUM level will not require any kind of man-in-the-middle (MITM) protection. Only the HIGH security level will require this. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'include/net/bluetooth')
-rw-r--r--include/net/bluetooth/bluetooth.h9
-rw-r--r--include/net/bluetooth/hci_core.h56
2 files changed, 42 insertions, 23 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 847e9e6df08b..3ad5390a4dd5 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -53,6 +53,15 @@
53#define SOL_SCO 17 53#define SOL_SCO 17
54#define SOL_RFCOMM 18 54#define SOL_RFCOMM 18
55 55
56#define BT_SECURITY 4
57struct bt_security {
58 __u8 level;
59};
60#define BT_SECURITY_SDP 0
61#define BT_SECURITY_LOW 1
62#define BT_SECURITY_MEDIUM 2
63#define BT_SECURITY_HIGH 3
64
56#define BT_DEFER_SETUP 7 65#define BT_DEFER_SETUP 7
57 66
58#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg) 67#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 46a43b721dd6..4b14972c1694 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -169,6 +169,7 @@ struct hci_conn {
169 __u16 link_policy; 169 __u16 link_policy;
170 __u32 link_mode; 170 __u32 link_mode;
171 __u8 auth_type; 171 __u8 auth_type;
172 __u8 sec_level;
172 __u8 power_save; 173 __u8 power_save;
173 unsigned long pend; 174 unsigned long pend;
174 175
@@ -325,12 +326,11 @@ int hci_conn_del(struct hci_conn *conn);
325void hci_conn_hash_flush(struct hci_dev *hdev); 326void hci_conn_hash_flush(struct hci_dev *hdev);
326void hci_conn_check_pending(struct hci_dev *hdev); 327void hci_conn_check_pending(struct hci_dev *hdev);
327 328
328struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type); 329struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
329int hci_conn_check_link_mode(struct hci_conn *conn); 330int hci_conn_check_link_mode(struct hci_conn *conn);
330int hci_conn_auth(struct hci_conn *conn); 331int hci_conn_security(struct hci_conn *conn, __u8 sec_level);
331int hci_conn_encrypt(struct hci_conn *conn);
332int hci_conn_change_link_key(struct hci_conn *conn); 332int hci_conn_change_link_key(struct hci_conn *conn);
333int hci_conn_switch_role(struct hci_conn *conn, uint8_t role); 333int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
334 334
335void hci_conn_enter_active_mode(struct hci_conn *conn); 335void hci_conn_enter_active_mode(struct hci_conn *conn);
336void hci_conn_enter_sniff_mode(struct hci_conn *conn); 336void hci_conn_enter_sniff_mode(struct hci_conn *conn);
@@ -470,26 +470,25 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
470 470
471/* ----- HCI protocols ----- */ 471/* ----- HCI protocols ----- */
472struct hci_proto { 472struct hci_proto {
473 char *name; 473 char *name;
474 unsigned int id; 474 unsigned int id;
475 unsigned long flags; 475 unsigned long flags;
476 476
477 void *priv; 477 void *priv;
478 478
479 int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type); 479 int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
480 int (*connect_cfm) (struct hci_conn *conn, __u8 status); 480 int (*connect_cfm) (struct hci_conn *conn, __u8 status);
481 int (*disconn_ind) (struct hci_conn *conn, __u8 reason); 481 int (*disconn_ind) (struct hci_conn *conn, __u8 reason);
482 int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags); 482 int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
483 int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); 483 int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
484 int (*auth_cfm) (struct hci_conn *conn, __u8 status); 484 int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
485 int (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
486}; 485};
487 486
488static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) 487static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
489{ 488{
490 register struct hci_proto *hp; 489 register struct hci_proto *hp;
491 int mask = 0; 490 int mask = 0;
492 491
493 hp = hci_proto[HCI_PROTO_L2CAP]; 492 hp = hci_proto[HCI_PROTO_L2CAP];
494 if (hp && hp->connect_ind) 493 if (hp && hp->connect_ind)
495 mask |= hp->connect_ind(hdev, bdaddr, type); 494 mask |= hp->connect_ind(hdev, bdaddr, type);
@@ -530,14 +529,20 @@ static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason)
530static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) 529static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
531{ 530{
532 register struct hci_proto *hp; 531 register struct hci_proto *hp;
532 __u8 encrypt;
533
534 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
535 return;
536
537 encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
533 538
534 hp = hci_proto[HCI_PROTO_L2CAP]; 539 hp = hci_proto[HCI_PROTO_L2CAP];
535 if (hp && hp->auth_cfm) 540 if (hp && hp->security_cfm)
536 hp->auth_cfm(conn, status); 541 hp->security_cfm(conn, status, encrypt);
537 542
538 hp = hci_proto[HCI_PROTO_SCO]; 543 hp = hci_proto[HCI_PROTO_SCO];
539 if (hp && hp->auth_cfm) 544 if (hp && hp->security_cfm)
540 hp->auth_cfm(conn, status); 545 hp->security_cfm(conn, status, encrypt);
541} 546}
542 547
543static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt) 548static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
@@ -545,12 +550,12 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u
545 register struct hci_proto *hp; 550 register struct hci_proto *hp;
546 551
547 hp = hci_proto[HCI_PROTO_L2CAP]; 552 hp = hci_proto[HCI_PROTO_L2CAP];
548 if (hp && hp->encrypt_cfm) 553 if (hp && hp->security_cfm)
549 hp->encrypt_cfm(conn, status, encrypt); 554 hp->security_cfm(conn, status, encrypt);
550 555
551 hp = hci_proto[HCI_PROTO_SCO]; 556 hp = hci_proto[HCI_PROTO_SCO];
552 if (hp && hp->encrypt_cfm) 557 if (hp && hp->security_cfm)
553 hp->encrypt_cfm(conn, status, encrypt); 558 hp->security_cfm(conn, status, encrypt);
554} 559}
555 560
556int hci_register_proto(struct hci_proto *hproto); 561int hci_register_proto(struct hci_proto *hproto);
@@ -562,8 +567,7 @@ struct hci_cb {
562 567
563 char *name; 568 char *name;
564 569
565 void (*auth_cfm) (struct hci_conn *conn, __u8 status); 570 void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
566 void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
567 void (*key_change_cfm) (struct hci_conn *conn, __u8 status); 571 void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
568 void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); 572 void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
569}; 573};
@@ -571,14 +575,20 @@ struct hci_cb {
571static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) 575static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
572{ 576{
573 struct list_head *p; 577 struct list_head *p;
578 __u8 encrypt;
574 579
575 hci_proto_auth_cfm(conn, status); 580 hci_proto_auth_cfm(conn, status);
576 581
582 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
583 return;
584
585 encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
586
577 read_lock_bh(&hci_cb_list_lock); 587 read_lock_bh(&hci_cb_list_lock);
578 list_for_each(p, &hci_cb_list) { 588 list_for_each(p, &hci_cb_list) {
579 struct hci_cb *cb = list_entry(p, struct hci_cb, list); 589 struct hci_cb *cb = list_entry(p, struct hci_cb, list);
580 if (cb->auth_cfm) 590 if (cb->security_cfm)
581 cb->auth_cfm(conn, status); 591 cb->security_cfm(conn, status, encrypt);
582 } 592 }
583 read_unlock_bh(&hci_cb_list_lock); 593 read_unlock_bh(&hci_cb_list_lock);
584} 594}
@@ -592,8 +602,8 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
592 read_lock_bh(&hci_cb_list_lock); 602 read_lock_bh(&hci_cb_list_lock);
593 list_for_each(p, &hci_cb_list) { 603 list_for_each(p, &hci_cb_list) {
594 struct hci_cb *cb = list_entry(p, struct hci_cb, list); 604 struct hci_cb *cb = list_entry(p, struct hci_cb, list);
595 if (cb->encrypt_cfm) 605 if (cb->security_cfm)
596 cb->encrypt_cfm(conn, status, encrypt); 606 cb->security_cfm(conn, status, encrypt);
597 } 607 }
598 read_unlock_bh(&hci_cb_list_lock); 608 read_unlock_bh(&hci_cb_list_lock);
599} 609}