Bluetooth: debugfs option to unset MITM flag
authorArchie Pusaka <apusaka@chromium.org>
Tue, 7 Apr 2020 04:26:27 +0000 (12:26 +0800)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 7 Apr 2020 16:32:21 +0000 (18:32 +0200)
The BT qualification test SM/MAS/PKE/BV-01-C needs us to turn off
the MITM flag when pairing, and at the same time also set the io
capability to something other than no input no output.

Currently the MITM flag is only unset when the io capability is set
to no input no output, therefore the test cannot be executed.

This patch introduces a debugfs option to force MITM flag to be
turned off.

Signed-off-by: Archie Pusaka <apusaka@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci.h
net/bluetooth/hci_debugfs.c
net/bluetooth/smp.c

index 79de2a659dd696ad308eff4fa346723a67308ef3..f4e8e2a0b7c15483a70aaea1e11f40acda46acd0 100644 (file)
@@ -298,6 +298,7 @@ enum {
        HCI_FORCE_STATIC_ADDR,
        HCI_LL_RPA_RESOLUTION,
        HCI_CMD_PENDING,
+       HCI_FORCE_NO_MITM,
 
        __HCI_NUM_FLAGS,
 };
index 6b1314c738b8e3729ac705c31900cd392550d757..5e8af2658e44a3d78f81192d9787149b0f8241d5 100644 (file)
@@ -1075,6 +1075,50 @@ DEFINE_SIMPLE_ATTRIBUTE(auth_payload_timeout_fops,
                        auth_payload_timeout_get,
                        auth_payload_timeout_set, "%llu\n");
 
+static ssize_t force_no_mitm_read(struct file *file,
+                                 char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct hci_dev *hdev = file->private_data;
+       char buf[3];
+
+       buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM) ? 'Y' : 'N';
+       buf[1] = '\n';
+       buf[2] = '\0';
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t force_no_mitm_write(struct file *file,
+                                  const char __user *user_buf,
+                                  size_t count, loff_t *ppos)
+{
+       struct hci_dev *hdev = file->private_data;
+       char buf[32];
+       size_t buf_size = min(count, (sizeof(buf) - 1));
+       bool enable;
+
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+       if (strtobool(buf, &enable))
+               return -EINVAL;
+
+       if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM))
+               return -EALREADY;
+
+       hci_dev_change_flag(hdev, HCI_FORCE_NO_MITM);
+
+       return count;
+}
+
+static const struct file_operations force_no_mitm_fops = {
+       .open           = simple_open,
+       .read           = force_no_mitm_read,
+       .write          = force_no_mitm_write,
+       .llseek         = default_llseek,
+};
+
 DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter,
                       HCI_QUIRK_STRICT_DUPLICATE_FILTER);
 DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery,
@@ -1134,6 +1178,8 @@ void hci_debugfs_create_le(struct hci_dev *hdev)
                            &max_key_size_fops);
        debugfs_create_file("auth_payload_timeout", 0644, hdev->debugfs, hdev,
                            &auth_payload_timeout_fops);
+       debugfs_create_file("force_no_mitm", 0644, hdev->debugfs, hdev,
+                           &force_no_mitm_fops);
 
        debugfs_create_file("quirk_strict_duplicate_filter", 0644,
                            hdev->debugfs, hdev,
index d0b695ee49f636eedc4abe631a0b4de1385293c6..a85e3e49cd0dace0395910d6f5c8db35d3de828f 100644 (file)
@@ -2393,12 +2393,17 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
                        authreq |= SMP_AUTH_CT2;
        }
 
-       /* Require MITM if IO Capability allows or the security level
-        * requires it.
+       /* Don't attempt to set MITM if setting is overridden by debugfs
+        * Needed to pass certification test SM/MAS/PKE/BV-01-C
         */
-       if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
-           hcon->pending_sec_level > BT_SECURITY_MEDIUM)
-               authreq |= SMP_AUTH_MITM;
+       if (!hci_dev_test_flag(hcon->hdev, HCI_FORCE_NO_MITM)) {
+               /* Require MITM if IO Capability allows or the security level
+                * requires it.
+                */
+               if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
+                   hcon->pending_sec_level > BT_SECURITY_MEDIUM)
+                       authreq |= SMP_AUTH_MITM;
+       }
 
        if (hcon->role == HCI_ROLE_MASTER) {
                struct smp_cmd_pairing cp;