summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-09-09 07:19:20 +0200
committerMarcel Holtmann <marcel@holtmann.org>2008-09-09 07:19:20 +0200
commit09ab6f4c2376a0fc31abde1e2991513f900ea825 (patch)
treef002d719a8a9a2c6344f06a5b9346bc053b4054d /net/bluetooth
parentf1c08ca559387ab30992055596d54061dfa022b1 (diff)
downloadlinux-09ab6f4c2376a0fc31abde1e2991513f900ea825.tar.gz
linux-09ab6f4c2376a0fc31abde1e2991513f900ea825.tar.bz2
linux-09ab6f4c2376a0fc31abde1e2991513f900ea825.zip
[Bluetooth] Enforce correct authentication requirements
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>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_conn.c8
-rw-r--r--net/bluetooth/l2cap.c19
-rw-r--r--net/bluetooth/sco.c2
3 files changed, 23 insertions, 6 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ca8d05245ca0..a2f9efaa3361 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -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;
}
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 3396d5bdef1c..a96d6de80d12 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -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;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index a16011fedc1d..0cc91e6da76d 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -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;