Commit f8558555 authored by Marcel Holtmann's avatar Marcel Holtmann

[Bluetooth] Initiate authentication during connection establishment

With Bluetooth 2.1 and Simple Pairing the requirement is that any new
connection needs to be authenticated and that encryption has been
switched on before allowing L2CAP to use it. So make sure that all
the requirements are fulfilled and otherwise drop the connection with
a minimal disconnect timeout of 10 milliseconds.

This change only affects Bluetooth 2.1 devices and Simple Pairing
needs to be enabled locally and in the remote host stack. The previous
changes made sure that these information are discovered before any
kind of authentication and encryption is triggered.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 769be974
......@@ -619,6 +619,60 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_auth_requested *cp;
struct hci_conn *conn;
BT_DBG("%s status 0x%x", hdev->name, status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
hci_conn_put(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_set_conn_encrypt *cp;
struct hci_conn *conn;
BT_DBG("%s status 0x%x", hdev->name, status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
hci_conn_put(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
......@@ -643,7 +697,6 @@ static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, status);
hci_conn_put(conn);
}
......@@ -671,7 +724,6 @@ static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, status);
hci_conn_put(conn);
}
......@@ -982,15 +1034,29 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
if (conn->state == BT_CONFIG) {
if (!ev->status && hdev->ssp_mode > 0 &&
conn->ssp_mode > 0) {
struct hci_cp_set_conn_encrypt cp;
cp.handle = ev->handle;
cp.encrypt = 0x01;
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
sizeof(cp), &cp);
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
}
} else
hci_auth_cfm(conn, ev->status);
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
if (!ev->status) {
struct hci_cp_set_conn_encrypt cp;
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
hci_send_cmd(conn->hdev,
HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
cp.handle = ev->handle;
cp.encrypt = 0x01;
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
sizeof(cp), &cp);
} else {
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_encrypt_cfm(conn, ev->status, 0x00);
......@@ -1030,6 +1096,13 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
if (conn->state == BT_CONFIG) {
if (!ev->status)
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
} else
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
}
......@@ -1250,6 +1323,14 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_add_sco(hdev, ev->status);
break;
case HCI_OP_AUTH_REQUESTED:
hci_cs_auth_requested(hdev, ev->status);
break;
case HCI_OP_SET_CONN_ENCRYPT:
hci_cs_set_conn_encrypt(hdev, ev->status);
break;
case HCI_OP_REMOTE_NAME_REQ:
hci_cs_remote_name_req(hdev, ev->status);
break;
......@@ -1518,11 +1599,22 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
}
if (conn->state == BT_CONFIG) {
if (!ev->status && hdev->ssp_mode > 0 &&
conn->ssp_mode > 0) {
if (conn->out) {
struct hci_cp_auth_requested cp;
cp.handle = ev->handle;
hci_send_cmd(hdev,
HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
}
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
}
}
}
hci_dev_unlock(hdev);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment