[Bluetooth] Enforce correct authentication requirements
authorMarcel Holtmann <marcel@holtmann.org>
Tue, 9 Sep 2008 05:19:20 +0000 (07:19 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 9 Sep 2008 05:19:20 +0000 (07:19 +0200)
With the introduction of Security Mode 4 and Simple Pairing from the
Bluetooth 2.1 specification it became mandatory that the initiator
requires authentication and encryption before any L2CAP channel can
be established. The only exception here is PSM 1 for the service
discovery protocol (SDP). It is meant to be used without any encryption
since it contains only public information. This is how Bluetooth 2.0
and before handle connections on PSM 1.

For Bluetooth 2.1 devices the pairing procedure differentiates between
no bonding, general bonding and dedicated bonding. The L2CAP layer
wrongly uses always general bonding when creating new connections, but it
should not do this for SDP connections. In this case the authentication
requirement should be no bonding and the just-works model should be used,
but in case of non-SDP connection it is required to use general bonding.

If the new connection requires man-in-the-middle (MITM) protection, it
also first wrongly creates an unauthenticated link key and then later on
requests an upgrade to an authenticated link key to provide full MITM
protection. With Simple Pairing the link key generation is an expensive
operation (compared to Bluetooth 2.0 and before) and doing this twice
during a connection setup causes a noticeable delay when establishing
a new connection. This should be avoided to not regress from the expected
Bluetooth 2.0 connection times. The authentication requirements are known
up-front and so enforce them.

To fulfill these requirements the hci_connect() function has been extended
with an authentication requirement parameter that will be stored inside
the connection information and can be retrieved by userspace at any
time. This allows the correct IO capabilities exchange and results in
the expected behavior.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_conn.c
net/bluetooth/l2cap.c
net/bluetooth/sco.c

index cbf751094688cfb024d7931c4ca755a70a33ab42..5e785b968e7eec9b12dd0ee1b2431a17f91ca589 100644 (file)
@@ -325,7 +325,7 @@ int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
 int hci_conn_auth(struct hci_conn *conn);
 int hci_conn_encrypt(struct hci_conn *conn);
 int hci_conn_change_link_key(struct hci_conn *conn);
index ca8d05245ca0cb9e27586cfdbdeb90e5afff81e3..a2f9efaa336143e5c74cde4db0294941220c7c22 100644 (file)
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route);
 
 /* Create SCO or ACL connection.
  * Device _must_ be locked */
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
 {
        struct hci_conn *acl;
        struct hci_conn *sco;
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        hci_conn_hold(acl);
 
-       if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
+       if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
+               acl->auth_type = auth_type;
                hci_acl_connect(acl);
+       }
 
        if (type == ACL_LINK)
                return acl;
@@ -381,7 +383,7 @@ int hci_conn_auth(struct hci_conn *conn)
 
        if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
                if (!(conn->auth_type & 0x01)) {
-                       conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
+                       conn->auth_type |= 0x01;
                        conn->link_mode &= ~HCI_LM_AUTH;
                }
        }
index 3396d5bdef1c3f8e0f24af0a64dd7b1eca7a333f..a96d6de80d12b1c5315703c8a38531151d041af2 100644 (file)
@@ -55,7 +55,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.10"
+#define VERSION "2.11"
 
 static u32 l2cap_feat_mask = 0x0000;
 
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
        struct l2cap_conn *conn;
        struct hci_conn *hcon;
        struct hci_dev *hdev;
+       __u8 auth_type;
        int err = 0;
 
        BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)
 
        err = -ENOMEM;
 
-       hcon = hci_connect(hdev, ACL_LINK, dst);
+       if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
+                       l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
+                               l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
+               if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+                       auth_type = HCI_AT_NO_BONDING_MITM;
+               else
+                       auth_type = HCI_AT_GENERAL_BONDING_MITM;
+       } else {
+               if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+                       auth_type = HCI_AT_NO_BONDING;
+               else
+                       auth_type = HCI_AT_GENERAL_BONDING;
+       }
+
+       hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
        if (!hcon)
                goto done;
 
index a16011fedc1d73d3adc24e66ff5e7ff24a37373c..0cc91e6da76d7f9d16983985f176ab1d7319eaab 100644 (file)
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk)
        else
                type = SCO_LINK;
 
-       hcon = hci_connect(hdev, type, dst);
+       hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING);
        if (!hcon)
                goto done;