diff options
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
| -rw-r--r-- | net/bluetooth/Kconfig | 8 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 22 | ||||
| -rw-r--r-- | net/bluetooth/smp.c | 22 |
4 files changed, 50 insertions, 4 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 836d3e8c4bf1..7837f3260863 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
| @@ -177,6 +177,8 @@ struct hci_dev { | |||
| 177 | 177 | ||
| 178 | __u16 init_last_cmd; | 178 | __u16 init_last_cmd; |
| 179 | 179 | ||
| 180 | struct crypto_blkcipher *tfm; | ||
| 181 | |||
| 180 | struct inquiry_cache inq_cache; | 182 | struct inquiry_cache inq_cache; |
| 181 | struct hci_conn_hash conn_hash; | 183 | struct hci_conn_hash conn_hash; |
| 182 | struct list_head blacklist; | 184 | struct list_head blacklist; |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 6ae5ec508587..f495dea741e3 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
| @@ -22,6 +22,7 @@ menuconfig BT | |||
| 22 | BNEP Module (Bluetooth Network Encapsulation Protocol) | 22 | BNEP Module (Bluetooth Network Encapsulation Protocol) |
| 23 | CMTP Module (CAPI Message Transport Protocol) | 23 | CMTP Module (CAPI Message Transport Protocol) |
| 24 | HIDP Module (Human Interface Device Protocol) | 24 | HIDP Module (Human Interface Device Protocol) |
| 25 | SMP Module (Security Manager Protocol) | ||
| 25 | 26 | ||
| 26 | Say Y here to compile Bluetooth support into the kernel or say M to | 27 | Say Y here to compile Bluetooth support into the kernel or say M to |
| 27 | compile it as module (bluetooth). | 28 | compile it as module (bluetooth). |
| @@ -36,11 +37,18 @@ if BT != n | |||
| 36 | config BT_L2CAP | 37 | config BT_L2CAP |
| 37 | bool "L2CAP protocol support" | 38 | bool "L2CAP protocol support" |
| 38 | select CRC16 | 39 | select CRC16 |
| 40 | select CRYPTO | ||
| 41 | select CRYPTO_BLKCIPHER | ||
| 42 | select CRYPTO_AES | ||
| 43 | select CRYPTO_ECB | ||
| 39 | help | 44 | help |
| 40 | L2CAP (Logical Link Control and Adaptation Protocol) provides | 45 | L2CAP (Logical Link Control and Adaptation Protocol) provides |
| 41 | connection oriented and connection-less data transport. L2CAP | 46 | connection oriented and connection-less data transport. L2CAP |
| 42 | support is required for most Bluetooth applications. | 47 | support is required for most Bluetooth applications. |
| 43 | 48 | ||
| 49 | Also included is support for SMP (Security Manager Protocol) which | ||
| 50 | is the security layer on top of LE (Low Energy) links. | ||
| 51 | |||
| 44 | config BT_SCO | 52 | config BT_SCO |
| 45 | bool "SCO links support" | 53 | bool "SCO links support" |
| 46 | help | 54 | help |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e14e8a1cb04e..f62ca1935f5a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/notifier.h> | 42 | #include <linux/notifier.h> |
| 43 | #include <linux/rfkill.h> | 43 | #include <linux/rfkill.h> |
| 44 | #include <linux/timer.h> | 44 | #include <linux/timer.h> |
| 45 | #include <linux/crypto.h> | ||
| 45 | #include <net/sock.h> | 46 | #include <net/sock.h> |
| 46 | 47 | ||
| 47 | #include <asm/system.h> | 48 | #include <asm/system.h> |
| @@ -59,6 +60,8 @@ static void hci_tx_task(unsigned long arg); | |||
| 59 | 60 | ||
| 60 | static DEFINE_RWLOCK(hci_task_lock); | 61 | static DEFINE_RWLOCK(hci_task_lock); |
| 61 | 62 | ||
| 63 | static int enable_smp; | ||
| 64 | |||
| 62 | /* HCI device list */ | 65 | /* HCI device list */ |
| 63 | LIST_HEAD(hci_dev_list); | 66 | LIST_HEAD(hci_dev_list); |
| 64 | DEFINE_RWLOCK(hci_dev_list_lock); | 67 | DEFINE_RWLOCK(hci_dev_list_lock); |
| @@ -1274,6 +1277,14 @@ int hci_add_adv_entry(struct hci_dev *hdev, | |||
| 1274 | return 0; | 1277 | return 0; |
| 1275 | } | 1278 | } |
| 1276 | 1279 | ||
| 1280 | static struct crypto_blkcipher *alloc_cypher(void) | ||
| 1281 | { | ||
| 1282 | if (enable_smp) | ||
| 1283 | return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | ||
| 1284 | |||
| 1285 | return ERR_PTR(-ENOTSUPP); | ||
| 1286 | } | ||
| 1287 | |||
| 1277 | /* Register HCI device */ | 1288 | /* Register HCI device */ |
| 1278 | int hci_register_dev(struct hci_dev *hdev) | 1289 | int hci_register_dev(struct hci_dev *hdev) |
| 1279 | { | 1290 | { |
| @@ -1358,6 +1369,11 @@ int hci_register_dev(struct hci_dev *hdev) | |||
| 1358 | if (!hdev->workqueue) | 1369 | if (!hdev->workqueue) |
| 1359 | goto nomem; | 1370 | goto nomem; |
| 1360 | 1371 | ||
| 1372 | hdev->tfm = alloc_cypher(); | ||
| 1373 | if (IS_ERR(hdev->tfm)) | ||
| 1374 | BT_INFO("Failed to load transform for ecb(aes): %ld", | ||
| 1375 | PTR_ERR(hdev->tfm)); | ||
| 1376 | |||
| 1361 | hci_register_sysfs(hdev); | 1377 | hci_register_sysfs(hdev); |
| 1362 | 1378 | ||
| 1363 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | 1379 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, |
| @@ -1406,6 +1422,9 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
| 1406 | !test_bit(HCI_SETUP, &hdev->flags)) | 1422 | !test_bit(HCI_SETUP, &hdev->flags)) |
| 1407 | mgmt_index_removed(hdev->id); | 1423 | mgmt_index_removed(hdev->id); |
| 1408 | 1424 | ||
| 1425 | if (!IS_ERR(hdev->tfm)) | ||
| 1426 | crypto_free_blkcipher(hdev->tfm); | ||
| 1427 | |||
| 1409 | hci_notify(hdev, HCI_DEV_UNREG); | 1428 | hci_notify(hdev, HCI_DEV_UNREG); |
| 1410 | 1429 | ||
| 1411 | if (hdev->rfkill) { | 1430 | if (hdev->rfkill) { |
| @@ -2242,3 +2261,6 @@ static void hci_cmd_task(unsigned long arg) | |||
| 2242 | } | 2261 | } |
| 2243 | } | 2262 | } |
| 2244 | } | 2263 | } |
| 2264 | |||
| 2265 | module_param(enable_smp, bool, 0644); | ||
| 2266 | MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)"); | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 2240e96552f1..aa20bee97501 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
| @@ -154,9 +154,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 154 | 154 | ||
| 155 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | 155 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) |
| 156 | { | 156 | { |
| 157 | struct hci_conn *hcon = conn->hcon; | ||
| 157 | __u8 authreq; | 158 | __u8 authreq; |
| 158 | 159 | ||
| 159 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level); | 160 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); |
| 161 | |||
| 162 | if (IS_ERR(hcon->hdev->tfm)) | ||
| 163 | return 1; | ||
| 160 | 164 | ||
| 161 | switch (sec_level) { | 165 | switch (sec_level) { |
| 162 | case BT_SECURITY_MEDIUM: | 166 | case BT_SECURITY_MEDIUM: |
| @@ -174,7 +178,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
| 174 | return 1; | 178 | return 1; |
| 175 | } | 179 | } |
| 176 | 180 | ||
| 177 | if (conn->hcon->link_mode & HCI_LM_MASTER) { | 181 | if (hcon->link_mode & HCI_LM_MASTER) { |
| 178 | struct smp_cmd_pairing cp; | 182 | struct smp_cmd_pairing cp; |
| 179 | cp.io_capability = 0x00; | 183 | cp.io_capability = 0x00; |
| 180 | cp.oob_flag = 0x00; | 184 | cp.oob_flag = 0x00; |
| @@ -198,6 +202,12 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 198 | __u8 reason; | 202 | __u8 reason; |
| 199 | int err = 0; | 203 | int err = 0; |
| 200 | 204 | ||
| 205 | if (IS_ERR(conn->hcon->hdev->tfm)) { | ||
| 206 | err = PTR_ERR(conn->hcon->hdev->tfm); | ||
| 207 | reason = SMP_PAIRING_NOTSUPP; | ||
| 208 | goto done; | ||
| 209 | } | ||
| 210 | |||
| 201 | skb_pull(skb, sizeof(code)); | 211 | skb_pull(skb, sizeof(code)); |
| 202 | 212 | ||
| 203 | switch (code) { | 213 | switch (code) { |
| @@ -233,11 +243,15 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 233 | BT_DBG("Unknown command code 0x%2.2x", code); | 243 | BT_DBG("Unknown command code 0x%2.2x", code); |
| 234 | 244 | ||
| 235 | reason = SMP_CMD_NOTSUPP; | 245 | reason = SMP_CMD_NOTSUPP; |
| 236 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), | ||
| 237 | &reason); | ||
| 238 | err = -EOPNOTSUPP; | 246 | err = -EOPNOTSUPP; |
| 247 | goto done; | ||
| 239 | } | 248 | } |
| 240 | 249 | ||
| 250 | done: | ||
| 251 | if (reason) | ||
| 252 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), | ||
| 253 | &reason); | ||
| 254 | |||
| 241 | kfree_skb(skb); | 255 | kfree_skb(skb); |
| 242 | return err; | 256 | return err; |
| 243 | } | 257 | } |
