diff options
author | Vinicius Costa Gomes <vinicius.gomes@openbossa.org> | 2011-06-09 17:50:43 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-06-13 14:48:22 -0400 |
commit | 3a0259bb80cec7595a2d085a150412d23ba28c81 (patch) | |
tree | eec4da988424125848d09261a015f8930a3b96c6 | |
parent | 88ba43b662b6b944c6278ad81a114fa559807776 (diff) |
Bluetooth: Add support for using the crypto subsystem
This will allow using the crypto subsystem for encrypting data. As SMP
(Security Manager Protocol) is implemented almost entirely on the host
side and the crypto module already implements the needed methods
(AES-128), it makes sense to use it.
There's now a new module option to enable/disable SMP support.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-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 836d3e8c4bf..7837f326086 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 6ae5ec50858..f495dea741e 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 e14e8a1cb04..f62ca1935f5 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 2240e96552f..aa20bee9750 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 | } |