.. | .. |
---|
26 | 26 | #include <net/bluetooth/bluetooth.h> |
---|
27 | 27 | #include <net/bluetooth/hci_core.h> |
---|
28 | 28 | |
---|
| 29 | +#include "smp.h" |
---|
29 | 30 | #include "hci_debugfs.h" |
---|
30 | 31 | |
---|
31 | 32 | #define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk) \ |
---|
.. | .. |
---|
151 | 152 | } |
---|
152 | 153 | |
---|
153 | 154 | DEFINE_SHOW_ATTRIBUTE(blacklist); |
---|
| 155 | + |
---|
| 156 | +static int blocked_keys_show(struct seq_file *f, void *p) |
---|
| 157 | +{ |
---|
| 158 | + struct hci_dev *hdev = f->private; |
---|
| 159 | + struct blocked_key *key; |
---|
| 160 | + |
---|
| 161 | + rcu_read_lock(); |
---|
| 162 | + list_for_each_entry_rcu(key, &hdev->blocked_keys, list) |
---|
| 163 | + seq_printf(f, "%u %*phN\n", key->type, 16, key->val); |
---|
| 164 | + rcu_read_unlock(); |
---|
| 165 | + |
---|
| 166 | + return 0; |
---|
| 167 | +} |
---|
| 168 | + |
---|
| 169 | +DEFINE_SHOW_ATTRIBUTE(blocked_keys); |
---|
154 | 170 | |
---|
155 | 171 | static int uuids_show(struct seq_file *f, void *p) |
---|
156 | 172 | { |
---|
.. | .. |
---|
308 | 324 | &device_list_fops); |
---|
309 | 325 | debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, |
---|
310 | 326 | &blacklist_fops); |
---|
| 327 | + debugfs_create_file("blocked_keys", 0444, hdev->debugfs, hdev, |
---|
| 328 | + &blocked_keys_fops); |
---|
311 | 329 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); |
---|
312 | 330 | debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev, |
---|
313 | 331 | &remote_oob_fops); |
---|
.. | .. |
---|
433 | 451 | return 0; |
---|
434 | 452 | } |
---|
435 | 453 | |
---|
| 454 | +static int min_encrypt_key_size_set(void *data, u64 val) |
---|
| 455 | +{ |
---|
| 456 | + struct hci_dev *hdev = data; |
---|
| 457 | + |
---|
| 458 | + if (val < 1 || val > 16) |
---|
| 459 | + return -EINVAL; |
---|
| 460 | + |
---|
| 461 | + hci_dev_lock(hdev); |
---|
| 462 | + hdev->min_enc_key_size = val; |
---|
| 463 | + hci_dev_unlock(hdev); |
---|
| 464 | + |
---|
| 465 | + return 0; |
---|
| 466 | +} |
---|
| 467 | + |
---|
| 468 | +static int min_encrypt_key_size_get(void *data, u64 *val) |
---|
| 469 | +{ |
---|
| 470 | + struct hci_dev *hdev = data; |
---|
| 471 | + |
---|
| 472 | + hci_dev_lock(hdev); |
---|
| 473 | + *val = hdev->min_enc_key_size; |
---|
| 474 | + hci_dev_unlock(hdev); |
---|
| 475 | + |
---|
| 476 | + return 0; |
---|
| 477 | +} |
---|
| 478 | + |
---|
| 479 | +DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops, |
---|
| 480 | + min_encrypt_key_size_get, |
---|
| 481 | + min_encrypt_key_size_set, "%llu\n"); |
---|
| 482 | + |
---|
436 | 483 | static int auto_accept_delay_get(void *data, u64 *val) |
---|
437 | 484 | { |
---|
438 | 485 | struct hci_dev *hdev = data; |
---|
.. | .. |
---|
545 | 592 | if (lmp_ssp_capable(hdev)) { |
---|
546 | 593 | debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs, |
---|
547 | 594 | hdev, &ssp_debug_mode_fops); |
---|
| 595 | + debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs, |
---|
| 596 | + hdev, &min_encrypt_key_size_fops); |
---|
548 | 597 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, |
---|
549 | 598 | hdev, &auto_accept_delay_fops); |
---|
550 | 599 | } |
---|
.. | .. |
---|
941 | 990 | DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, |
---|
942 | 991 | adv_max_interval_set, "%llu\n"); |
---|
943 | 992 | |
---|
| 993 | +static int min_key_size_set(void *data, u64 val) |
---|
| 994 | +{ |
---|
| 995 | + struct hci_dev *hdev = data; |
---|
| 996 | + |
---|
| 997 | + if (val > hdev->le_max_key_size || val < SMP_MIN_ENC_KEY_SIZE) |
---|
| 998 | + return -EINVAL; |
---|
| 999 | + |
---|
| 1000 | + hci_dev_lock(hdev); |
---|
| 1001 | + hdev->le_min_key_size = val; |
---|
| 1002 | + hci_dev_unlock(hdev); |
---|
| 1003 | + |
---|
| 1004 | + return 0; |
---|
| 1005 | +} |
---|
| 1006 | + |
---|
| 1007 | +static int min_key_size_get(void *data, u64 *val) |
---|
| 1008 | +{ |
---|
| 1009 | + struct hci_dev *hdev = data; |
---|
| 1010 | + |
---|
| 1011 | + hci_dev_lock(hdev); |
---|
| 1012 | + *val = hdev->le_min_key_size; |
---|
| 1013 | + hci_dev_unlock(hdev); |
---|
| 1014 | + |
---|
| 1015 | + return 0; |
---|
| 1016 | +} |
---|
| 1017 | + |
---|
| 1018 | +DEFINE_SIMPLE_ATTRIBUTE(min_key_size_fops, min_key_size_get, |
---|
| 1019 | + min_key_size_set, "%llu\n"); |
---|
| 1020 | + |
---|
| 1021 | +static int max_key_size_set(void *data, u64 val) |
---|
| 1022 | +{ |
---|
| 1023 | + struct hci_dev *hdev = data; |
---|
| 1024 | + |
---|
| 1025 | + if (val > SMP_MAX_ENC_KEY_SIZE || val < hdev->le_min_key_size) |
---|
| 1026 | + return -EINVAL; |
---|
| 1027 | + |
---|
| 1028 | + hci_dev_lock(hdev); |
---|
| 1029 | + hdev->le_max_key_size = val; |
---|
| 1030 | + hci_dev_unlock(hdev); |
---|
| 1031 | + |
---|
| 1032 | + return 0; |
---|
| 1033 | +} |
---|
| 1034 | + |
---|
| 1035 | +static int max_key_size_get(void *data, u64 *val) |
---|
| 1036 | +{ |
---|
| 1037 | + struct hci_dev *hdev = data; |
---|
| 1038 | + |
---|
| 1039 | + hci_dev_lock(hdev); |
---|
| 1040 | + *val = hdev->le_max_key_size; |
---|
| 1041 | + hci_dev_unlock(hdev); |
---|
| 1042 | + |
---|
| 1043 | + return 0; |
---|
| 1044 | +} |
---|
| 1045 | + |
---|
| 1046 | +DEFINE_SIMPLE_ATTRIBUTE(max_key_size_fops, max_key_size_get, |
---|
| 1047 | + max_key_size_set, "%llu\n"); |
---|
| 1048 | + |
---|
| 1049 | +static int auth_payload_timeout_set(void *data, u64 val) |
---|
| 1050 | +{ |
---|
| 1051 | + struct hci_dev *hdev = data; |
---|
| 1052 | + |
---|
| 1053 | + if (val < 0x0001 || val > 0xffff) |
---|
| 1054 | + return -EINVAL; |
---|
| 1055 | + |
---|
| 1056 | + hci_dev_lock(hdev); |
---|
| 1057 | + hdev->auth_payload_timeout = val; |
---|
| 1058 | + hci_dev_unlock(hdev); |
---|
| 1059 | + |
---|
| 1060 | + return 0; |
---|
| 1061 | +} |
---|
| 1062 | + |
---|
| 1063 | +static int auth_payload_timeout_get(void *data, u64 *val) |
---|
| 1064 | +{ |
---|
| 1065 | + struct hci_dev *hdev = data; |
---|
| 1066 | + |
---|
| 1067 | + hci_dev_lock(hdev); |
---|
| 1068 | + *val = hdev->auth_payload_timeout; |
---|
| 1069 | + hci_dev_unlock(hdev); |
---|
| 1070 | + |
---|
| 1071 | + return 0; |
---|
| 1072 | +} |
---|
| 1073 | + |
---|
| 1074 | +DEFINE_SIMPLE_ATTRIBUTE(auth_payload_timeout_fops, |
---|
| 1075 | + auth_payload_timeout_get, |
---|
| 1076 | + auth_payload_timeout_set, "%llu\n"); |
---|
| 1077 | + |
---|
| 1078 | +static ssize_t force_no_mitm_read(struct file *file, |
---|
| 1079 | + char __user *user_buf, |
---|
| 1080 | + size_t count, loff_t *ppos) |
---|
| 1081 | +{ |
---|
| 1082 | + struct hci_dev *hdev = file->private_data; |
---|
| 1083 | + char buf[3]; |
---|
| 1084 | + |
---|
| 1085 | + buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM) ? 'Y' : 'N'; |
---|
| 1086 | + buf[1] = '\n'; |
---|
| 1087 | + buf[2] = '\0'; |
---|
| 1088 | + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
---|
| 1089 | +} |
---|
| 1090 | + |
---|
| 1091 | +static ssize_t force_no_mitm_write(struct file *file, |
---|
| 1092 | + const char __user *user_buf, |
---|
| 1093 | + size_t count, loff_t *ppos) |
---|
| 1094 | +{ |
---|
| 1095 | + struct hci_dev *hdev = file->private_data; |
---|
| 1096 | + char buf[32]; |
---|
| 1097 | + size_t buf_size = min(count, (sizeof(buf) - 1)); |
---|
| 1098 | + bool enable; |
---|
| 1099 | + |
---|
| 1100 | + if (copy_from_user(buf, user_buf, buf_size)) |
---|
| 1101 | + return -EFAULT; |
---|
| 1102 | + |
---|
| 1103 | + buf[buf_size] = '\0'; |
---|
| 1104 | + if (strtobool(buf, &enable)) |
---|
| 1105 | + return -EINVAL; |
---|
| 1106 | + |
---|
| 1107 | + if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM)) |
---|
| 1108 | + return -EALREADY; |
---|
| 1109 | + |
---|
| 1110 | + hci_dev_change_flag(hdev, HCI_FORCE_NO_MITM); |
---|
| 1111 | + |
---|
| 1112 | + return count; |
---|
| 1113 | +} |
---|
| 1114 | + |
---|
| 1115 | +static const struct file_operations force_no_mitm_fops = { |
---|
| 1116 | + .open = simple_open, |
---|
| 1117 | + .read = force_no_mitm_read, |
---|
| 1118 | + .write = force_no_mitm_write, |
---|
| 1119 | + .llseek = default_llseek, |
---|
| 1120 | +}; |
---|
| 1121 | + |
---|
944 | 1122 | DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter, |
---|
945 | 1123 | HCI_QUIRK_STRICT_DUPLICATE_FILTER); |
---|
946 | 1124 | DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery, |
---|
.. | .. |
---|
994 | 1172 | &adv_max_interval_fops); |
---|
995 | 1173 | debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, |
---|
996 | 1174 | &hdev->discov_interleaved_timeout); |
---|
| 1175 | + debugfs_create_file("min_key_size", 0644, hdev->debugfs, hdev, |
---|
| 1176 | + &min_key_size_fops); |
---|
| 1177 | + debugfs_create_file("max_key_size", 0644, hdev->debugfs, hdev, |
---|
| 1178 | + &max_key_size_fops); |
---|
| 1179 | + debugfs_create_file("auth_payload_timeout", 0644, hdev->debugfs, hdev, |
---|
| 1180 | + &auth_payload_timeout_fops); |
---|
| 1181 | + debugfs_create_file("force_no_mitm", 0644, hdev->debugfs, hdev, |
---|
| 1182 | + &force_no_mitm_fops); |
---|
997 | 1183 | |
---|
998 | 1184 | debugfs_create_file("quirk_strict_duplicate_filter", 0644, |
---|
999 | 1185 | hdev->debugfs, hdev, |
---|