Skip to content

Commit

Permalink
Bluetooth: Add support for using the crypto subsystem
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vinicius Costa Gomes authored and Gustavo F. Padovan committed Jun 13, 2011
1 parent 88ba43b commit 3a0259b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
2 changes: 2 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ struct hci_dev {

__u16 init_last_cmd;

struct crypto_blkcipher *tfm;

struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
struct list_head blacklist;
Expand Down
8 changes: 8 additions & 0 deletions net/bluetooth/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ menuconfig BT
BNEP Module (Bluetooth Network Encapsulation Protocol)
CMTP Module (CAPI Message Transport Protocol)
HIDP Module (Human Interface Device Protocol)
SMP Module (Security Manager Protocol)

Say Y here to compile Bluetooth support into the kernel or say M to
compile it as module (bluetooth).
Expand All @@ -36,11 +37,18 @@ if BT != n
config BT_L2CAP
bool "L2CAP protocol support"
select CRC16
select CRYPTO
select CRYPTO_BLKCIPHER
select CRYPTO_AES
select CRYPTO_ECB
help
L2CAP (Logical Link Control and Adaptation Protocol) provides
connection oriented and connection-less data transport. L2CAP
support is required for most Bluetooth applications.

Also included is support for SMP (Security Manager Protocol) which
is the security layer on top of LE (Low Energy) links.

config BT_SCO
bool "SCO links support"
help
Expand Down
22 changes: 22 additions & 0 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <linux/notifier.h>
#include <linux/rfkill.h>
#include <linux/timer.h>
#include <linux/crypto.h>
#include <net/sock.h>

#include <asm/system.h>
Expand All @@ -59,6 +60,8 @@ static void hci_tx_task(unsigned long arg);

static DEFINE_RWLOCK(hci_task_lock);

static int enable_smp;

/* HCI device list */
LIST_HEAD(hci_dev_list);
DEFINE_RWLOCK(hci_dev_list_lock);
Expand Down Expand Up @@ -1274,6 +1277,14 @@ int hci_add_adv_entry(struct hci_dev *hdev,
return 0;
}

static struct crypto_blkcipher *alloc_cypher(void)
{
if (enable_smp)
return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);

return ERR_PTR(-ENOTSUPP);
}

/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
Expand Down Expand Up @@ -1358,6 +1369,11 @@ int hci_register_dev(struct hci_dev *hdev)
if (!hdev->workqueue)
goto nomem;

hdev->tfm = alloc_cypher();
if (IS_ERR(hdev->tfm))
BT_INFO("Failed to load transform for ecb(aes): %ld",
PTR_ERR(hdev->tfm));

hci_register_sysfs(hdev);

hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
Expand Down Expand Up @@ -1406,6 +1422,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
!test_bit(HCI_SETUP, &hdev->flags))
mgmt_index_removed(hdev->id);

if (!IS_ERR(hdev->tfm))
crypto_free_blkcipher(hdev->tfm);

hci_notify(hdev, HCI_DEV_UNREG);

if (hdev->rfkill) {
Expand Down Expand Up @@ -2242,3 +2261,6 @@ static void hci_cmd_task(unsigned long arg)
}
}
}

module_param(enable_smp, bool, 0644);
MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
22 changes: 18 additions & 4 deletions net/bluetooth/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)

int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
{
struct hci_conn *hcon = conn->hcon;
__u8 authreq;

BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);

if (IS_ERR(hcon->hdev->tfm))
return 1;

switch (sec_level) {
case BT_SECURITY_MEDIUM:
Expand All @@ -174,7 +178,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
return 1;
}

if (conn->hcon->link_mode & HCI_LM_MASTER) {
if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;
cp.io_capability = 0x00;
cp.oob_flag = 0x00;
Expand All @@ -198,6 +202,12 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
__u8 reason;
int err = 0;

if (IS_ERR(conn->hcon->hdev->tfm)) {
err = PTR_ERR(conn->hcon->hdev->tfm);
reason = SMP_PAIRING_NOTSUPP;
goto done;
}

skb_pull(skb, sizeof(code));

switch (code) {
Expand Down Expand Up @@ -233,11 +243,15 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG("Unknown command code 0x%2.2x", code);

reason = SMP_CMD_NOTSUPP;
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
err = -EOPNOTSUPP;
goto done;
}

done:
if (reason)
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);

kfree_skb(skb);
return err;
}

0 comments on commit 3a0259b

Please sign in to comment.