Skip to content

Commit

Permalink
Bluetooth: Introduce force_bredr_smp debugfs option for testing
Browse files Browse the repository at this point in the history
Testing cross-transport pairing that starts on BR/EDR is only valid when
using a controller with BR/EDR Secure Connections. Devices will indicate
this by providing BR/EDR SMP fixed channel over L2CAP. To allow testing
of this feature on Bluetooth 4.0 controller or controllers without the
BR/EDR Secure Connections features, introduce a force_bredr_smp debugfs
option that allows faking the required AES connection.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
  • Loading branch information
Marcel Holtmann committed Jan 2, 2015
1 parent e8768f9 commit 300acfd
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 5 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ enum {
HCI_DUT_MODE,
HCI_FORCE_SC,
HCI_FORCE_LESC,
HCI_FORCE_BREDR_SMP,
HCI_FORCE_STATIC_ADDR,
};

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/l2cap_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -6968,7 +6968,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)

if (test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags) &&
(bredr_sc_enabled(hcon->hdev) ||
test_bit(HCI_FORCE_LESC, &hcon->hdev->dbg_flags)))
test_bit(HCI_FORCE_BREDR_SMP, &hcon->hdev->dbg_flags)))
conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;

mutex_init(&conn->ident_lock);
Expand Down
78 changes: 74 additions & 4 deletions net/bluetooth/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
SOFTWARE IS DISCLAIMED.
*/

#include <linux/debugfs.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <crypto/b128ops.h>
Expand Down Expand Up @@ -1675,7 +1676,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (conn->hcon->type == ACL_LINK) {
/* We must have a BR/EDR SC link */
if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
!test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
!test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags))
return SMP_CROSS_TRANSP_NOT_ALLOWED;

set_bit(SMP_FLAG_SC, &smp->flags);
Expand Down Expand Up @@ -2738,7 +2739,7 @@ static void bredr_pairing(struct l2cap_chan *chan)

/* BR/EDR must use Secure Connections for SMP */
if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
!test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
!test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags))
return;

/* If our LE support is not enabled don't do anything */
Expand Down Expand Up @@ -2976,6 +2977,66 @@ static void smp_del_chan(struct l2cap_chan *chan)
l2cap_chan_put(chan);
}

static ssize_t force_bredr_smp_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] = test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}

static ssize_t force_bredr_smp_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 == test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags))
return -EALREADY;

if (enable) {
struct l2cap_chan *chan;

chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
if (IS_ERR(chan))
return PTR_ERR(chan);

hdev->smp_bredr_data = chan;
} else {
struct l2cap_chan *chan;

chan = hdev->smp_bredr_data;
hdev->smp_bredr_data = NULL;
smp_del_chan(chan);
}

change_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags);

return count;
}

static const struct file_operations force_bredr_smp_fops = {
.open = simple_open,
.read = force_bredr_smp_read,
.write = force_bredr_smp_write,
.llseek = default_llseek,
};

int smp_register(struct hci_dev *hdev)
{
struct l2cap_chan *chan;
Expand All @@ -2988,9 +3049,18 @@ int smp_register(struct hci_dev *hdev)

hdev->smp_data = chan;

if (!lmp_sc_capable(hdev) &&
!test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
/* If the controller does not support BR/EDR Secure Connections
* feature, then the BR/EDR SMP channel shall not be present.
*
* To test this with Bluetooth 4.0 controllers, create a debugfs
* switch that allows forcing BR/EDR SMP support and accepting
* cross-transport pairing on non-AES encrypted connections.
*/
if (!lmp_sc_capable(hdev)) {
debugfs_create_file("force_bredr_smp", 0644, hdev->debugfs,
hdev, &force_bredr_smp_fops);
return 0;
}

chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
if (IS_ERR(chan)) {
Expand Down

0 comments on commit 300acfd

Please sign in to comment.