2011-11-11 01:03:48

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 0/8] New LTK messages

Hi,

These are the new version of the messages needed for permanent key
storage (and allows a more permanent pairing).

Changes from the last version:
- new messages strutures;
- support for only the LTK;
- the LTKs are kept on their own list;

The last three patches are improvements needed for proper pairing.

As the mgmt interface in the kernel and in userspace are different,
I wasn't able to test these patches with the latest userspace. To not
pollute the list even more I will send the userspace side of things
(already implemented) as soon as it seems that this the way to go.

Cheers,
--

Vinicius Costa Gomes (8):
Bluetooth: Add structures for the new LTK exchange messages
Bluetooth: Add a custom type for Short Term Keys
Bluetooth: Rename smp_key_size to enc_size
Bluetooth: Change SMP procedures to use the new key structures
Bluetooth: Add new mgmt handlers for Long Term Keys
Bluetooth: Add support for reusing the same hci_conn for LE links
Bluetooth: Disconnect the link if encryption fails
Bluetooth: Only increase the connection sec-level if encryption is
successful

include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 34 ++++++------
include/net/bluetooth/mgmt.h | 21 +++++++
include/net/bluetooth/smp.h | 2 +-
net/bluetooth/hci_conn.c | 27 +++++-----
net/bluetooth/hci_core.c | 107 +++++++++++++++++++++++--------------
net/bluetooth/hci_event.c | 5 ++-
net/bluetooth/l2cap_core.c | 58 ++++++++++++++-------
net/bluetooth/mgmt.c | 77 +++++++++++++++++++++++++++
net/bluetooth/smp.c | 44 +++++++++-------
10 files changed, 264 insertions(+), 112 deletions(-)

--
1.7.7



2011-11-12 23:35:44

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 3/8] Bluetooth: Rename smp_key_size to enc_size

Hi Vinicius,

> This makes clear that this is the size of the key used to
> encrypt the link.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/smp.h | 2 +-
> net/bluetooth/smp.c | 18 +++++++++---------
> 2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
> index 15b97d5..cf3aab0 100644
> --- a/include/net/bluetooth/smp.h
> +++ b/include/net/bluetooth/smp.h
> @@ -123,7 +123,7 @@ struct smp_chan {
> u8 rrnd[16]; /* SMP Pairing Random (remote) */
> u8 pcnf[16]; /* SMP Pairing Confirm */
> u8 tk[16]; /* SMP Temporary Key */
> - u8 smp_key_size;
> + u8 enc_size;

if we wanna be really clear, then enc_key_size would be the better name.

Regards

Marcel



2011-11-12 23:33:42

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Vinicius,

> Signed-off-by: Vinicius Costa Gomes <[email protected]>

we need to get into the habit to have at least 2 lines of commit
messages that explain this patch. Just the subject line is not good
enough for the kernel.

> ---
> include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++
> 1 files changed, 21 insertions(+), 0 deletions(-)

Otherwise I am fine with this, unless Johan objects.

Acked-by: Marcel Holtmann <[email protected]>

Regards

Marcel



2011-11-11 17:02:38

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys

Hi Johan, Vinicius,

On 11/11/2011 8:55 AM, Brian Gix wrote:
> On 11/10/2011 5:03 PM, Vinicius Costa Gomes wrote:
>> These keys are just used to encrypt the link, during SMP phase 2, they
>> should
>> not be stored nor reused. We use the same list as the LTKs to
>> temporarily store
>> them, but as soon as they are used they are removed from the list.
>>
>> Signed-off-by: Vinicius Costa Gomes<[email protected]>
>> ---
>> include/net/bluetooth/hci.h | 1 +
>> 1 files changed, 1 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index 139ce2a..069768c 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -260,6 +260,7 @@ enum {
>> #define HCI_LK_AUTH_COMBINATION 0x05
>> #define HCI_LK_CHANGED_COMBINATION 0x06
>> /* The spec doesn't define types for SMP keys */
>> +#define HCI_LK_SMP_STK 0x80
>> #define HCI_LK_SMP_LTK 0x81
>> #define HCI_LK_SMP_IRK 0x82
>> #define HCI_LK_SMP_CSRK 0x83
>
>
> At some point, we will also need to expand this list to include key
> types for both Initiator and Responder (or rather, keys Locally
> generated, and keys Remotely generated). Although there are 3 base types
> of LE keys (4 if you count the STK), there are in fact 6 different keys
> for different situations (7 if you count STK).
>
> LTKs might be considered an exception, since most devices will only ever
> be a Master or a Slave, and IRKs will often only need to be saved for
> remote privacy supporting peripherals, if the local side does not use
> privacy.
>
> However, for the CSRKs, I suspect that we will need to strongly
> differentiate between Locally and Remotely generated signing keys. If we
> have a server with a "Signed Write Cmd" Characteristic and the remote
> device has one too, we will need to sign the outbound Write Cmds with
> the key the remote side distributed to us, and they will use the key
> that we sent them, so we need to keep them separate.
>
> And once you start down that path, you should at least consider the
> possibility of needing to distinguish between remote and local LTKs and
> IRKs as well. STKs at least do not have that problem: them are jointly
> derived.
>
> Should we add _LCL_ and _REM_ to the naming conventions, and expand the
> enumeration out to 0x86?
>

I am including Johan in for this:
We also may want to expand or add an interface to MGMT to specify which
keys we can Generate and Accept during LE pairing. Obviously at this
point, I think this would be set to Generating No keys (if we are
Master, and Central) and accepting only the LTK (reverse that if we are
LE slaves).

Looking towards the future, the keys distributed will depend very much
on what the User space (bluez) entities are able to support.


--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-11-11 16:55:20

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys

On 11/10/2011 5:03 PM, Vinicius Costa Gomes wrote:
> These keys are just used to encrypt the link, during SMP phase 2, they should
> not be stored nor reused. We use the same list as the LTKs to temporarily store
> them, but as soon as they are used they are removed from the list.
>
> Signed-off-by: Vinicius Costa Gomes<[email protected]>
> ---
> include/net/bluetooth/hci.h | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 139ce2a..069768c 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -260,6 +260,7 @@ enum {
> #define HCI_LK_AUTH_COMBINATION 0x05
> #define HCI_LK_CHANGED_COMBINATION 0x06
> /* The spec doesn't define types for SMP keys */
> +#define HCI_LK_SMP_STK 0x80
> #define HCI_LK_SMP_LTK 0x81
> #define HCI_LK_SMP_IRK 0x82
> #define HCI_LK_SMP_CSRK 0x83


At some point, we will also need to expand this list to include key
types for both Initiator and Responder (or rather, keys Locally
generated, and keys Remotely generated). Although there are 3 base
types of LE keys (4 if you count the STK), there are in fact 6 different
keys for different situations (7 if you count STK).

LTKs might be considered an exception, since most devices will only ever
be a Master or a Slave, and IRKs will often only need to be saved for
remote privacy supporting peripherals, if the local side does not use
privacy.

However, for the CSRKs, I suspect that we will need to strongly
differentiate between Locally and Remotely generated signing keys. If
we have a server with a "Signed Write Cmd" Characteristic and the remote
device has one too, we will need to sign the outbound Write Cmds with
the key the remote side distributed to us, and they will use the key
that we sent them, so we need to keep them separate.

And once you start down that path, you should at least consider the
possibility of needing to distinguish between remote and local LTKs and
IRKs as well. STKs at least do not have that problem: them are jointly
derived.

Should we add _LCL_ and _REM_ to the naming conventions, and expand the
enumeration out to 0x86?

--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-11-11 01:03:56

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 8/8] Bluetooth: Only increase the connection sec-level if encryption is successful

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci_core.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b5cc198..25287de 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -845,7 +845,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;

- if (conn->pending_sec_level > conn->sec_level)
+ if (!status && conn->pending_sec_level > conn->sec_level)
conn->sec_level = conn->pending_sec_level;

hci_proto_encrypt_cfm(conn, status, encrypt);
--
1.7.7


2011-11-11 01:03:55

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 7/8] Bluetooth: Disconnect the link if encryption fails

The most common case of error is that the encryption keys don't agree, so
the best solution is to disconnect the link and inform the user that there
was a problem during encryption.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/l2cap_core.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 19dc625..361f75f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4499,10 +4499,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)

BT_DBG("conn %p", conn);

- if (hcon->type == LE_LINK) {
+ if (hcon->type == LE_LINK && !status) {
smp_distribute_keys(conn, 0);
del_timer(&conn->security_timer);
- }
+ } else if (hcon->type == LE_LINK)
+ l2cap_conn_del(hcon, bt_to_errno(status));

read_lock(&conn->chan_lock);

--
1.7.7


2011-11-11 01:03:54

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 6/8] Bluetooth: Add support for reusing the same hci_conn for LE links

As most LE devices leave advertising mode when they enter the connected
state, we may want to "pass" that connection to other users.

The first user will be the pairing procedure, the connection is
established without an associated socket, after the pairing is
complete, userspace may want to discover via GATT what services the
newly bonded device has.

If userspace establishes the connection while the timeout still
hasn't expired, the connection will be re-used.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/hci_conn.c | 27 +++++++++++----------
net/bluetooth/l2cap_core.c | 53 +++++++++++++++++++++++++++++--------------
2 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index de0b93e..0bc2771 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -502,23 +502,24 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
BT_DBG("%s dst %s", hdev->name, batostr(dst));

if (type == LE_LINK) {
- struct adv_entry *entry;
+ struct adv_entry *entry = NULL;

le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
- if (le)
- return ERR_PTR(-EBUSY);
+ if (!le) {
+ entry = hci_find_adv_entry(hdev, dst);
+ if (!entry)
+ return ERR_PTR(-EHOSTUNREACH);

- entry = hci_find_adv_entry(hdev, dst);
- if (!entry)
- return ERR_PTR(-EHOSTUNREACH);
+ le = hci_conn_add(hdev, LE_LINK, dst);
+ if (!le)
+ return ERR_PTR(-ENOMEM);

- le = hci_conn_add(hdev, LE_LINK, dst);
- if (!le)
- return ERR_PTR(-ENOMEM);
-
- le->dst_type = entry->bdaddr_type;
-
- hci_le_connect(le);
+ le->dst_type = entry->bdaddr_type;
+ le->pending_sec_level = sec_level;
+ le->sec_level = BT_SECURITY_LOW;
+ le->auth_type = auth_type;
+ hci_le_connect(le);
+ }

hci_conn_hold(le);

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 1790ce3..19dc625 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -656,10 +656,32 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
}

+static void l2cap_chan_ready(struct sock *sk)
+{
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct sock *parent = bt_sk(sk)->parent;
+
+ BT_DBG("sk %p, parent %p", sk, parent);
+
+ chan->conf_state = 0;
+ __clear_chan_timer(chan);
+
+ l2cap_state_change(chan, BT_CONNECTED);
+ sk->sk_state_change(sk);
+
+ if (parent)
+ parent->sk_data_ready(parent, 0);
+}
+
static void l2cap_do_start(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;

+ if (conn->hcon->type == LE_LINK) {
+ l2cap_chan_ready(chan->sk);
+ return;
+ }
+
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
return;
@@ -910,23 +932,6 @@ clean:
bh_unlock_sock(parent);
}

-static void l2cap_chan_ready(struct sock *sk)
-{
- struct l2cap_chan *chan = l2cap_pi(sk)->chan;
- struct sock *parent = bt_sk(sk)->parent;
-
- BT_DBG("sk %p, parent %p", sk, parent);
-
- chan->conf_state = 0;
- __clear_chan_timer(chan);
-
- l2cap_state_change(chan, BT_CONNECTED);
- sk->sk_state_change(sk);
-
- if (parent)
- parent->sk_data_ready(parent, 0);
-}
-
static void l2cap_conn_ready(struct l2cap_conn *conn)
{
struct l2cap_chan *chan;
@@ -1170,6 +1175,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
goto done;
}

+ if (hcon->type == LE_LINK) {
+ err = 0;
+
+ read_lock(&conn->chan_lock);
+ if (!list_empty(&conn->chan_l)) {
+ err = -EBUSY;
+ hci_conn_put(hcon);
+ }
+ read_unlock(&conn->chan_lock);
+
+ if (err)
+ goto done;
+ }
+
/* Update source addr of the socket */
bacpy(src, conn->src);

--
1.7.7


2011-11-11 01:03:53

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 5/8] Bluetooth: Add new mgmt handlers for Long Term Keys

This makes use of the new messages defined to exchange LTKs
between the kernel and userspace. Handlers for loading LTKs
into the kernel and for informing userspace of a new LTK are
defined.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 6 +++
net/bluetooth/mgmt.c | 71 ++++++++++++++++++++++++++++++++++++++
3 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ee660ce..b5cc198 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -943,6 +943,7 @@ int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0f3e534..8d56966 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1190,6 +1190,12 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key,
key->enc_size = enc_size;
memcpy(key->rand, rand, sizeof(key->rand));

+ if (!new_key)
+ return 0;
+
+ if (type == HCI_LK_SMP_LTK)
+ mgmt_new_ltk(hdev, key, 1);
+
return 0;
}

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7378d22..48143dd 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1840,6 +1840,56 @@ done:
return err;
}

+static int load_long_term_keys(struct sock *sk, u16 index,
+ unsigned char *data, u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_load_long_term_keys *cp;
+ u16 key_count, expected_len;
+ int i;
+
+ cp = (void *) data;
+
+ if (len < sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS,
+ EINVAL);
+
+ key_count = get_unaligned_le16(&cp->key_count);
+
+ expected_len = sizeof(*cp) + key_count *
+ sizeof(struct mgmt_ltk_info);
+ if (expected_len != len) {
+ BT_ERR("load_keys: expected %u bytes, got %u bytes",
+ len, expected_len);
+ return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS,
+ EINVAL);
+ }
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS,
+ ENODEV);
+
+ BT_DBG("hci%u key_count %u", index, key_count);
+
+ hci_dev_lock_bh(hdev);
+
+ hci_smp_ltks_clear(hdev);
+
+ for (i = 0; i < key_count; i++) {
+ struct mgmt_ltk_info *key = &cp->keys[i];
+
+ hci_add_ltk(hdev, &key->bdaddr, HCI_LK_SMP_LTK, 0,
+ key->pin_len, key->val, key->enc_size,
+ key->ediv, key->rand);
+ }
+
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return 0;
+}
+
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
unsigned char *buf;
@@ -1964,6 +2014,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
len);
break;
+ case MGMT_OP_LOAD_LONG_TERM_KEYS:
+ err = load_long_term_keys(sk, index, buf + sizeof(*hdr), len);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, index, opcode, 0x01);
@@ -2116,6 +2169,24 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
}

+int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
+{
+ struct mgmt_ev_new_long_term_key ev;
+
+ memset(&ev, 0, sizeof(ev));
+
+ ev.store_hint = persistent;
+ bacpy(&ev.key.bdaddr, &key->bdaddr);
+ ev.key.pin_len = key->pin_len;
+ ev.key.enc_size = key->enc_size;
+ ev.key.ediv = key->ediv;
+ memcpy(ev.key.rand, key->rand, sizeof(key->rand));
+ memcpy(ev.key.val, key->val, sizeof(key->val));
+
+ return mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev,
+ &ev, sizeof(ev), NULL);
+}
+
int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type)
{
--
1.7.7


2011-11-11 01:03:52

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures

Using separated messages and list for Long Term Keys allow simplification
of the code.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci_core.h | 31 +++++------
net/bluetooth/hci_core.c | 105 ++++++++++++++++++++++---------------
net/bluetooth/hci_event.c | 5 ++-
net/bluetooth/mgmt.c | 6 ++
net/bluetooth/smp.c | 32 +++++++-----
5 files changed, 105 insertions(+), 74 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a67ff88..ee660ce 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -84,18 +84,15 @@ struct bt_uuid {
u8 svc_hint;
};

-struct key_master_id {
- __le16 ediv;
- u8 rand[8];
-} __packed;
-
-struct link_key_data {
+struct smp_ltk {
+ struct list_head list;
bdaddr_t bdaddr;
+ u8 pin_len;
u8 type;
+ u8 enc_size;
+ __le16 ediv;
+ u8 rand[8];
u8 val[16];
- u8 pin_len;
- u8 dlen;
- u8 data[0];
} __packed;

struct link_key {
@@ -104,8 +101,6 @@ struct link_key {
u8 type;
u8 val[16];
u8 pin_len;
- u8 dlen;
- u8 data[0];
};

struct oob_data {
@@ -227,6 +222,8 @@ struct hci_dev {

struct list_head link_keys;

+ struct list_head ltks;
+
struct list_head remote_oob_data;

struct list_head adv_entries;
@@ -628,12 +625,14 @@ int hci_link_keys_clear(struct hci_dev *hdev);
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
-struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
-struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
- bdaddr_t *bdaddr, u8 type);
-int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
- u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
+int hci_smp_ltks_clear(struct hci_dev *hdev);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
+struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key,
+ u8 pin_len, u8 tk[16], u8 enc_size,
+ u16 ediv, u8 rand[8]);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);

int hci_remote_oob_data_clear(struct hci_dev *hdev);
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fb3feeb..0f3e534 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1017,6 +1017,18 @@ int hci_link_keys_clear(struct hci_dev *hdev)
return 0;
}

+int hci_smp_ltks_clear(struct hci_dev *hdev)
+{
+ struct smp_ltk *k, *tmp;
+
+ list_for_each_entry_safe(k, tmp, &hdev->ltks, list) {
+ list_del(&k->list);
+ kfree(k);
+ }
+
+ return 0;
+}
+
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct link_key *k;
@@ -1064,41 +1076,38 @@ static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
return 0;
}

-struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
+/* If the returned key is a STK it should be free'd by the caller */
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
{
- struct link_key *k;
-
- list_for_each_entry(k, &hdev->link_keys, list) {
- struct key_master_id *id;
+ struct smp_ltk *k, *tmp;

- if (k->type != HCI_LK_SMP_LTK)
+ list_for_each_entry_safe(k, tmp, &hdev->ltks, list) {
+ if (k->ediv != ediv ||
+ memcmp(rand, k->rand, sizeof(k->rand)))
continue;

- if (k->dlen != sizeof(*id))
- continue;
+ /* The STK should only be used once, no need to keep it */
+ if (k->type == HCI_LK_SMP_STK)
+ list_del(&k->list);

- id = (void *) &k->data;
- if (id->ediv == ediv &&
- (memcmp(rand, id->rand, sizeof(id->rand)) == 0))
- return k;
+ return k;
}

return NULL;
}
EXPORT_SYMBOL(hci_find_ltk);

-struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
- bdaddr_t *bdaddr, u8 type)
+struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
- struct link_key *k;
+ struct smp_ltk *k;

- list_for_each_entry(k, &hdev->link_keys, list)
- if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0)
+ list_for_each_entry(k, &hdev->ltks, list)
+ if (bacmp(bdaddr, &k->bdaddr) == 0)
return k;

return NULL;
}
-EXPORT_SYMBOL(hci_find_link_key_type);
+EXPORT_SYMBOL(hci_find_ltk_addr);

int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
@@ -1155,40 +1164,31 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
return 0;
}

-int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
- u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16])
+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key,
+ u8 pin_len, u8 tk[16], u8 enc_size,
+ u16 ediv, u8 rand[8])
{
- struct link_key *key, *old_key;
- struct key_master_id *id;
- u8 old_key_type;
+ struct smp_ltk *key, *old_key;

- BT_DBG("%s addr %s", hdev->name, batostr(bdaddr));
+ if (type != HCI_LK_SMP_STK && type != HCI_LK_SMP_LTK)
+ return 0;

- old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK);
- if (old_key) {
+ old_key = hci_find_ltk_addr(hdev, bdaddr);
+ if (old_key)
key = old_key;
- old_key_type = old_key->type;
- } else {
- key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC);
+ else {
+ key = kzalloc(sizeof(*key), GFP_ATOMIC);
if (!key)
return -ENOMEM;
- list_add(&key->list, &hdev->link_keys);
- old_key_type = 0xff;
+ list_add(&key->list, &hdev->ltks);
}

- key->dlen = sizeof(*id);
-
bacpy(&key->bdaddr, bdaddr);
- memcpy(key->val, ltk, sizeof(key->val));
- key->type = HCI_LK_SMP_LTK;
- key->pin_len = key_size;
-
- id = (void *) &key->data;
- id->ediv = ediv;
- memcpy(id->rand, rand, sizeof(id->rand));
-
- if (new_key)
- mgmt_new_link_key(hdev, key, old_key_type);
+ memcpy(key->val, tk, sizeof(key->val));
+ key->pin_len = pin_len;
+ key->ediv = ediv;
+ key->enc_size = enc_size;
+ memcpy(key->rand, rand, sizeof(key->rand));

return 0;
}
@@ -1209,6 +1209,23 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
return 0;
}

+int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct smp_ltk *k, *tmp;
+
+ list_for_each_entry_safe(k, tmp, &hdev->ltks, list) {
+ if (bacmp(bdaddr, &k->bdaddr))
+ continue;
+
+ BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+
+ list_del(&k->list);
+ kfree(k);
+ }
+
+ return 0;
+}
+
/* HCI command timer function */
static void hci_cmd_timer(unsigned long arg)
{
@@ -1493,6 +1510,7 @@ int hci_register_dev(struct hci_dev *hdev)
INIT_LIST_HEAD(&hdev->uuids);

INIT_LIST_HEAD(&hdev->link_keys);
+ INIT_LIST_HEAD(&hdev->ltks);

INIT_LIST_HEAD(&hdev->remote_oob_data);

@@ -1593,6 +1611,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_blacklist_clear(hdev);
hci_uuids_clear(hdev);
hci_link_keys_clear(hdev);
+ hci_smp_ltks_clear(hdev);
hci_remote_oob_data_clear(hdev);
hci_adv_entries_clear(hdev);
hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0d55d00..3df4ec7 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2919,7 +2919,7 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
struct hci_cp_le_ltk_reply cp;
struct hci_cp_le_ltk_neg_reply neg;
struct hci_conn *conn;
- struct link_key *ltk;
+ struct smp_ltk *ltk;

BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));

@@ -2939,6 +2939,9 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,

hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);

+ if (ltk->type == HCI_LK_SMP_STK)
+ kfree(ltk);
+
hci_dev_unlock(hdev);

return;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5562c21..7378d22 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -981,6 +981,12 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
memset(&rp, 0, sizeof(rp));
bacpy(&rp.bdaddr, &cp->bdaddr);

+ err = hci_remove_ltk(hdev, &cp->bdaddr);
+ if (err < 0) {
+ err = cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, -err);
+ goto unlock;
+ }
+
err = hci_remove_link_key(hdev, &cp->bdaddr);
if (err < 0)
goto unlock;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e30bf6a..028de8e 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -347,8 +347,8 @@ static void random_work(struct work_struct *work)
memset(stk + smp->enc_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_size);

- hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_size,
- ediv, rand, stk);
+ hci_add_ltk(hcon->hdev, conn->dst, HCI_LK_SMP_STK, 0,
+ 0, stk, smp->enc_size, ediv, rand);
}

return;
@@ -502,12 +502,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)

static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
{
- struct link_key *key;
- struct key_master_id *master;
+ struct smp_ltk *key;
struct hci_conn *hcon = conn->hcon;

- key = hci_find_link_key_type(hcon->hdev, conn->dst,
- HCI_LK_SMP_LTK);
+ key = hci_find_ltk_addr(hcon->hdev, conn->dst);
if (!key)
return 0;

@@ -515,10 +513,8 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
&hcon->pend))
return 1;

- master = (void *) key->data;
- hci_le_start_enc(hcon, master->ediv, master->rand,
- key->val);
- hcon->enc_key_size = key->pin_len;
+ hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
+ hcon->enc_key_size = key->enc_size;

return 1;

@@ -616,11 +612,15 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_master_ident *rp = (void *) skb->data;
struct smp_chan *smp = conn->smp_chan;
+ struct hci_dev *hdev = conn->hcon->hdev;

skb_pull(skb, sizeof(*rp));

- hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->enc_size,
- rp->ediv, rp->rand, smp->tk);
+ hci_dev_lock(hdev);
+ hci_add_ltk(conn->hcon->hdev, conn->dst, HCI_LK_SMP_LTK, 1,
+ conn->hcon->pin_length, smp->tk,
+ smp->enc_size, rp->ediv, rp->rand);
+ hci_dev_unlock(hdev);

smp_distribute_keys(conn, 1);

@@ -703,6 +703,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
{
struct smp_cmd_pairing *req, *rsp;
struct smp_chan *smp = conn->smp_chan;
+ struct hci_dev *hdev = conn->hcon->hdev;
__u8 *keydist;

BT_DBG("conn %p force %d", conn, force);
@@ -740,8 +741,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)

smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);

- hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_size,
- ediv, ident.rand, enc.ltk);
+ hci_dev_lock(hdev);
+ hci_add_ltk(conn->hcon->hdev, conn->src, HCI_LK_SMP_LTK, 1,
+ conn->hcon->pin_length, enc.ltk,
+ smp->enc_size, ediv, ident.rand);
+ hci_dev_unlock(hdev);

ident.ediv = cpu_to_le16(ediv);

--
1.7.7


2011-11-11 01:03:51

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 3/8] Bluetooth: Rename smp_key_size to enc_size

This makes clear that this is the size of the key used to
encrypt the link.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/smp.h | 2 +-
net/bluetooth/smp.c | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 15b97d5..cf3aab0 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -123,7 +123,7 @@ struct smp_chan {
u8 rrnd[16]; /* SMP Pairing Random (remote) */
u8 pcnf[16]; /* SMP Pairing Confirm */
u8 tk[16]; /* SMP Temporary Key */
- u8 smp_key_size;
+ u8 enc_size;
struct crypto_blkcipher *tfm;
struct work_struct confirm;
struct work_struct random;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 94e94ca..e30bf6a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -227,7 +227,7 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
(max_key_size < SMP_MIN_ENC_KEY_SIZE))
return SMP_ENC_KEY_SIZE;

- smp->smp_key_size = max_key_size;
+ smp->enc_size = max_key_size;

return 0;
}
@@ -321,8 +321,8 @@ static void random_work(struct work_struct *work)
smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
swap128(key, stk);

- memset(stk + smp->smp_key_size, 0,
- SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
+ memset(stk + smp->enc_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - smp->enc_size);

if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
reason = SMP_UNSPECIFIED;
@@ -330,7 +330,7 @@ static void random_work(struct work_struct *work)
}

hci_le_start_enc(hcon, ediv, rand, stk);
- hcon->enc_key_size = smp->smp_key_size;
+ hcon->enc_key_size = smp->enc_size;
} else {
u8 stk[16], r[16], rand[8];
__le16 ediv;
@@ -344,10 +344,10 @@ static void random_work(struct work_struct *work)
smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
swap128(key, stk);

- memset(stk + smp->smp_key_size, 0,
- SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
+ memset(stk + smp->enc_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - smp->enc_size);

- hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
+ hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_size,
ediv, rand, stk);
}

@@ -619,7 +619,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)

skb_pull(skb, sizeof(*rp));

- hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
+ hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->enc_size,
rp->ediv, rp->rand, smp->tk);

smp_distribute_keys(conn, 1);
@@ -740,7 +740,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)

smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);

- hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
+ hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_size,
ediv, ident.rand, enc.ltk);

ident.ediv = cpu_to_le16(ediv);
--
1.7.7


2011-11-11 01:03:50

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys

These keys are just used to encrypt the link, during SMP phase 2, they should
not be stored nor reused. We use the same list as the LTKs to temporarily store
them, but as soon as they are used they are removed from the list.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 139ce2a..069768c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -260,6 +260,7 @@ enum {
#define HCI_LK_AUTH_COMBINATION 0x05
#define HCI_LK_CHANGED_COMBINATION 0x06
/* The spec doesn't define types for SMP keys */
+#define HCI_LK_SMP_STK 0x80
#define HCI_LK_SMP_LTK 0x81
#define HCI_LK_SMP_IRK 0x82
#define HCI_LK_SMP_CSRK 0x83
--
1.7.7


2011-11-11 01:03:49

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 8b07a83..f4011e3 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -233,6 +233,21 @@ struct mgmt_cp_set_fast_connectable {
__u8 enable;
} __packed;

+struct mgmt_ltk_info {
+ bdaddr_t bdaddr;
+ __u8 pin_len;
+ __u8 enc_size;
+ __le16 ediv;
+ __u8 rand[8];
+ __u8 val[16];
+} __packed;
+
+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023
+struct mgmt_cp_load_long_term_keys {
+ __u16 key_count;
+ struct mgmt_ltk_info keys[0];
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -327,3 +342,9 @@ struct mgmt_ev_device_blocked {
struct mgmt_ev_device_unblocked {
bdaddr_t bdaddr;
} __packed;
+
+#define MGMT_EV_NEW_LONG_TERM_KEY 0x0017
+struct mgmt_ev_new_long_term_key {
+ __u8 store_hint;
+ struct mgmt_ltk_info key;
+} __packed;
--
1.7.7


2011-12-13 03:28:04

by Hemant Gupta

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Vinicius,

On Mon, Dec 12, 2011 at 6:47 PM, Vinicius Costa Gomes
<[email protected]> wrote:
> Hi,
>
> On 21:14 Wed 07 Dec, Hemant Gupta wrote:
>> Hi Vinicius,
>>
>> On Wed, Dec 7, 2011 at 6:18 AM, Vinicius Costa Gomes
>> <[email protected]> wrote:
>> > This defines two in the kernel side of BlueZ two new messages, one
The above line needs rewording.

>> > event that will inform userspace that a new Long Term Key was
>> > exchanged and one that will allow userspace to load LTKs into
>> > the kernel.
>>
>> The commit message has some issue, rewording is required.
>
> Could you please be more specific on what needs rewording, I will gladly
> fix it.
>
>>
>> > Acked-by: Marcel Holtmann <[email protected]>
>> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
>> > ---
>> > ?include/net/bluetooth/mgmt.h | ? 21 +++++++++++++++++++++
>> > ?1 files changed, 21 insertions(+), 0 deletions(-)
>> >
>> > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
>> > index 3b68806..0f100fa9 100644
>> > --- a/include/net/bluetooth/mgmt.h
>> > +++ b/include/net/bluetooth/mgmt.h
>> > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
>> > ? ? ? ?bdaddr_t bdaddr;
>> > ?} __packed;
>> >
>> > +struct mgmt_ltk_info {
>> > + ? ? ? bdaddr_t bdaddr;
>> > + ? ? ? __u8 pin_len;
>> > + ? ? ? __u8 enc_size;
>> > + ? ? ? __le16 ediv;
>> > + ? ? ? __u8 rand[8];
>> > + ? ? ? __u8 val[16];
>> > +} __packed;
>> > +
>> > +#define MGMT_OP_LOAD_LONG_TERM_KEYS ? ?0x0023
>> > +struct mgmt_cp_load_long_term_keys {
>> > + ? ? ? __u16 key_count;
>> > + ? ? ? struct mgmt_ltk_info keys[0];
>> > +} __packed;
>> > +
>> > ?#define MGMT_EV_CMD_COMPLETE ? ? ? ? ? 0x0001
>> > ?struct mgmt_ev_cmd_complete {
>> > ? ? ? ?__le16 opcode;
>> > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked {
>> > ?struct mgmt_ev_user_passkey_request {
>> > ? ? ? ?bdaddr_t bdaddr;
>> > ?} __packed;
>> > +
>> > +#define MGMT_EV_NEW_LONG_TERM_KEY ? ? ?0x0018
>> > +struct mgmt_ev_new_long_term_key {
>> > + ? ? ? __u8 store_hint;
>> > + ? ? ? struct mgmt_ltk_info key;
>> > +} __packed;
>> > --
>> > 1.7.8
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> > the body of a message to [email protected]
>> > More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Best Regards
>> Hemant Gupta
>> ST-Ericsson India
>
> Cheers,
> --
> Vinicius



--
Best Regards
Hemant Gupta
ST-Ericsson India

2011-12-12 17:37:12

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Vinicius, Johan,

On 12/12/2011 5:07 AM, Vinicius Costa Gomes wrote:
> Hi Brian,
>
> On 09:39 Wed 07 Dec, Brian Gix wrote:
>> > Hi Vinicius,
>> >
>> > On 12/6/2011 4:48 PM, Vinicius Costa Gomes wrote:
>>> > >This defines two in the kernel side of BlueZ two new messages, one
>>> > >event that will inform userspace that a new Long Term Key was
>>> > >exchanged and one that will allow userspace to load LTKs into
>>> > >the kernel.
>>> > >
>>> > >Acked-by: Marcel Holtmann<[email protected]>
>>> > >Signed-off-by: Vinicius Costa Gomes<[email protected]>
>>> > >---
>>> > > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++
>>> > > 1 files changed, 21 insertions(+), 0 deletions(-)
>>> > >
>>> > >diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
>>> > >index 3b68806..0f100fa9 100644
>>> > >--- a/include/net/bluetooth/mgmt.h
>>> > >+++ b/include/net/bluetooth/mgmt.h
>>> > >@@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
>>> > > bdaddr_t bdaddr;
>>> > > } __packed;
>>> > >
>>> > >+struct mgmt_ltk_info {
>>> > >+ bdaddr_t bdaddr;
>>> > >+ __u8 pin_len;
>>> > >+ __u8 enc_size;
>>> > >+ __le16 ediv;
>>> > >+ __u8 rand[8];
>>> > >+ __u8 val[16];
>>> > >+} __packed;
>> >
>> > I think we definitely want to store the auth level (octet) that was
>> > used to generate this key and/or the sec_level. Some profiles may
>> > require MITM (high sec_level) and from this key definition, there is
>> > no way to tell if it is Medium (no MITM) or High.
>> >
> Yeah, I was thinking about infering the security level using the pin_len
> field, but that assumption breaks once we have OOB. I will add this
> field.
>


Sorry I was not on the IRC when you were discussing the SMP-LTK
communication between Kernel and BluZ, but I was copied on the
conversation from a colleague.

I think everything you guys said was sound. An "authenticated" field
that is simply 0 or 1 should be sufficient for preserving the security
level that the key represents.

Also, I have looked at Hemants patch and it looks correct. It is
suitable for either SSP passkey request and entry, or SMP passkey
request and entry.

It should have no impact on how we handle LTK communication and storage.



--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-12-12 15:16:08

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Gustavo,

On 21:48 Tue 06 Dec, Vinicius Costa Gomes wrote:
> This defines two in the kernel side of BlueZ two new messages, one
> event that will inform userspace that a new Long Term Key was
> exchanged and one that will allow userspace to load LTKs into
> the kernel.
>
> Acked-by: Marcel Holtmann <[email protected]>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++
> 1 files changed, 21 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 3b68806..0f100fa9 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
> bdaddr_t bdaddr;
> } __packed;
>
> +struct mgmt_ltk_info {
> + bdaddr_t bdaddr;
> + __u8 pin_len;
> + __u8 enc_size;
> + __le16 ediv;
> + __u8 rand[8];
> + __u8 val[16];
> +} __packed;

As per a discussion on IRC right now, I will change this to include
authenticated/unauthenticated information and remove pin_len.

Please ignore this series.

> +
> +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023
> +struct mgmt_cp_load_long_term_keys {
> + __u16 key_count;
> + struct mgmt_ltk_info keys[0];
> +} __packed;
> +
> #define MGMT_EV_CMD_COMPLETE 0x0001
> struct mgmt_ev_cmd_complete {
> __le16 opcode;
> @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked {
> struct mgmt_ev_user_passkey_request {
> bdaddr_t bdaddr;
> } __packed;
> +
> +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018
> +struct mgmt_ev_new_long_term_key {
> + __u8 store_hint;
> + struct mgmt_ltk_info key;
> +} __packed;
> --
> 1.7.8
>

Cheers,
--
Vinicius

2011-12-12 13:17:54

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi,

On 21:14 Wed 07 Dec, Hemant Gupta wrote:
> Hi Vinicius,
>
> On Wed, Dec 7, 2011 at 6:18 AM, Vinicius Costa Gomes
> <[email protected]> wrote:
> > This defines two in the kernel side of BlueZ two new messages, one
> > event that will inform userspace that a new Long Term Key was
> > exchanged and one that will allow userspace to load LTKs into
> > the kernel.
>
> The commit message has some issue, rewording is required.

Could you please be more specific on what needs rewording, I will gladly
fix it.

>
> > Acked-by: Marcel Holtmann <[email protected]>
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > ?include/net/bluetooth/mgmt.h | ? 21 +++++++++++++++++++++
> > ?1 files changed, 21 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> > index 3b68806..0f100fa9 100644
> > --- a/include/net/bluetooth/mgmt.h
> > +++ b/include/net/bluetooth/mgmt.h
> > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
> > ? ? ? ?bdaddr_t bdaddr;
> > ?} __packed;
> >
> > +struct mgmt_ltk_info {
> > + ? ? ? bdaddr_t bdaddr;
> > + ? ? ? __u8 pin_len;
> > + ? ? ? __u8 enc_size;
> > + ? ? ? __le16 ediv;
> > + ? ? ? __u8 rand[8];
> > + ? ? ? __u8 val[16];
> > +} __packed;
> > +
> > +#define MGMT_OP_LOAD_LONG_TERM_KEYS ? ?0x0023
> > +struct mgmt_cp_load_long_term_keys {
> > + ? ? ? __u16 key_count;
> > + ? ? ? struct mgmt_ltk_info keys[0];
> > +} __packed;
> > +
> > ?#define MGMT_EV_CMD_COMPLETE ? ? ? ? ? 0x0001
> > ?struct mgmt_ev_cmd_complete {
> > ? ? ? ?__le16 opcode;
> > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked {
> > ?struct mgmt_ev_user_passkey_request {
> > ? ? ? ?bdaddr_t bdaddr;
> > ?} __packed;
> > +
> > +#define MGMT_EV_NEW_LONG_TERM_KEY ? ? ?0x0018
> > +struct mgmt_ev_new_long_term_key {
> > + ? ? ? __u8 store_hint;
> > + ? ? ? struct mgmt_ltk_info key;
> > +} __packed;
> > --
> > 1.7.8
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> > the body of a message to [email protected]
> > More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Best Regards
> Hemant Gupta
> ST-Ericsson India

Cheers,
--
Vinicius

2011-12-12 13:07:51

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Brian,

On 09:39 Wed 07 Dec, Brian Gix wrote:
> Hi Vinicius,
>
> On 12/6/2011 4:48 PM, Vinicius Costa Gomes wrote:
> >This defines two in the kernel side of BlueZ two new messages, one
> >event that will inform userspace that a new Long Term Key was
> >exchanged and one that will allow userspace to load LTKs into
> >the kernel.
> >
> >Acked-by: Marcel Holtmann<[email protected]>
> >Signed-off-by: Vinicius Costa Gomes<[email protected]>
> >---
> > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++
> > 1 files changed, 21 insertions(+), 0 deletions(-)
> >
> >diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> >index 3b68806..0f100fa9 100644
> >--- a/include/net/bluetooth/mgmt.h
> >+++ b/include/net/bluetooth/mgmt.h
> >@@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
> > bdaddr_t bdaddr;
> > } __packed;
> >
> >+struct mgmt_ltk_info {
> >+ bdaddr_t bdaddr;
> >+ __u8 pin_len;
> >+ __u8 enc_size;
> >+ __le16 ediv;
> >+ __u8 rand[8];
> >+ __u8 val[16];
> >+} __packed;
>
> I think we definitely want to store the auth level (octet) that was
> used to generate this key and/or the sec_level. Some profiles may
> require MITM (high sec_level) and from this key definition, there is
> no way to tell if it is Medium (no MITM) or High.
>

Yeah, I was thinking about infering the security level using the pin_len
field, but that assumption breaks once we have OOB. I will add this
field.

> This then needs to be used L2CAP to map the sock options, and
> potentially trigger a re-bonding. Not that it is likely to happen,
> since devices are suppose to pair with the Highest security level
> they have available, but there could be malicious devices which
> could gain access to "High" security services without performing
> MITM authentication.
>
> Also, I will harp once again that anything with an LE bdaddr should
> include the Public vs Random flag because the two address types are
> *not* interchangeable. I would like to see Johan's "mgmt_addr_info"
> structure used in place of the bdaddr_t here.

Sounds reasonable. Will change this.

>
>
> >+
> >+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023
> >+struct mgmt_cp_load_long_term_keys {
> >+ __u16 key_count;
> >+ struct mgmt_ltk_info keys[0];
> >+} __packed;
> >+
> > #define MGMT_EV_CMD_COMPLETE 0x0001
> > struct mgmt_ev_cmd_complete {
> > __le16 opcode;
> >@@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked {
> > struct mgmt_ev_user_passkey_request {
> > bdaddr_t bdaddr;
> > } __packed;
> >+
> >+#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018
> >+struct mgmt_ev_new_long_term_key {
> >+ __u8 store_hint;
> >+ struct mgmt_ltk_info key;
> >+} __packed;
>
>
> --
> Brian Gix
> [email protected]
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

Cheers,
--
Vinicius

2011-12-07 17:39:18

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Vinicius,

On 12/6/2011 4:48 PM, Vinicius Costa Gomes wrote:
> This defines two in the kernel side of BlueZ two new messages, one
> event that will inform userspace that a new Long Term Key was
> exchanged and one that will allow userspace to load LTKs into
> the kernel.
>
> Acked-by: Marcel Holtmann<[email protected]>
> Signed-off-by: Vinicius Costa Gomes<[email protected]>
> ---
> include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++
> 1 files changed, 21 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 3b68806..0f100fa9 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
> bdaddr_t bdaddr;
> } __packed;
>
> +struct mgmt_ltk_info {
> + bdaddr_t bdaddr;
> + __u8 pin_len;
> + __u8 enc_size;
> + __le16 ediv;
> + __u8 rand[8];
> + __u8 val[16];
> +} __packed;

I think we definitely want to store the auth level (octet) that was used
to generate this key and/or the sec_level. Some profiles may require
MITM (high sec_level) and from this key definition, there is no way to
tell if it is Medium (no MITM) or High.

This then needs to be used L2CAP to map the sock options, and
potentially trigger a re-bonding. Not that it is likely to happen,
since devices are suppose to pair with the Highest security level they
have available, but there could be malicious devices which could gain
access to "High" security services without performing MITM authentication.

Also, I will harp once again that anything with an LE bdaddr should
include the Public vs Random flag because the two address types are
*not* interchangeable. I would like to see Johan's "mgmt_addr_info"
structure used in place of the bdaddr_t here.


> +
> +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023
> +struct mgmt_cp_load_long_term_keys {
> + __u16 key_count;
> + struct mgmt_ltk_info keys[0];
> +} __packed;
> +
> #define MGMT_EV_CMD_COMPLETE 0x0001
> struct mgmt_ev_cmd_complete {
> __le16 opcode;
> @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked {
> struct mgmt_ev_user_passkey_request {
> bdaddr_t bdaddr;
> } __packed;
> +
> +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018
> +struct mgmt_ev_new_long_term_key {
> + __u8 store_hint;
> + struct mgmt_ltk_info key;
> +} __packed;


--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-12-07 15:44:27

by Hemant Gupta

[permalink] [raw]
Subject: Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages

Hi Vinicius,

On Wed, Dec 7, 2011 at 6:18 AM, Vinicius Costa Gomes
<[email protected]> wrote:
> This defines two in the kernel side of BlueZ two new messages, one
> event that will inform userspace that a new Long Term Key was
> exchanged and one that will allow userspace to load LTKs into
> the kernel.

The commit message has some issue, rewording is required.

> Acked-by: Marcel Holtmann <[email protected]>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> ?include/net/bluetooth/mgmt.h | ? 21 +++++++++++++++++++++
> ?1 files changed, 21 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 3b68806..0f100fa9 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply {
> ? ? ? ?bdaddr_t bdaddr;
> ?} __packed;
>
> +struct mgmt_ltk_info {
> + ? ? ? bdaddr_t bdaddr;
> + ? ? ? __u8 pin_len;
> + ? ? ? __u8 enc_size;
> + ? ? ? __le16 ediv;
> + ? ? ? __u8 rand[8];
> + ? ? ? __u8 val[16];
> +} __packed;
> +
> +#define MGMT_OP_LOAD_LONG_TERM_KEYS ? ?0x0023
> +struct mgmt_cp_load_long_term_keys {
> + ? ? ? __u16 key_count;
> + ? ? ? struct mgmt_ltk_info keys[0];
> +} __packed;
> +
> ?#define MGMT_EV_CMD_COMPLETE ? ? ? ? ? 0x0001
> ?struct mgmt_ev_cmd_complete {
> ? ? ? ?__le16 opcode;
> @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked {
> ?struct mgmt_ev_user_passkey_request {
> ? ? ? ?bdaddr_t bdaddr;
> ?} __packed;
> +
> +#define MGMT_EV_NEW_LONG_TERM_KEY ? ? ?0x0018
> +struct mgmt_ev_new_long_term_key {
> + ? ? ? __u8 store_hint;
> + ? ? ? struct mgmt_ltk_info key;
> +} __packed;
> --
> 1.7.8
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html



--
Best Regards
Hemant Gupta
ST-Ericsson India

2011-12-07 07:49:29

by Andrei Emeltchenko

[permalink] [raw]
Subject: Re: [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures

Hi Vinicius,

On Tue, Dec 06, 2011 at 09:48:08PM -0300, Vinicius Costa Gomes wrote:
> Using separated messages and list for Long Term Keys allow simplification
> of the code.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 31 +++++------
> net/bluetooth/hci_core.c | 105 ++++++++++++++++++++++---------------
> net/bluetooth/hci_event.c | 5 ++-
> net/bluetooth/mgmt.c | 6 ++
> net/bluetooth/smp.c | 29 +++++-----
> 5 files changed, 102 insertions(+), 74 deletions(-)

...
> -struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
> - bdaddr_t *bdaddr, u8 type)
> +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr)
> {
> - struct link_key *k;
> + struct smp_ltk *k;
>
> - list_for_each_entry(k, &hdev->link_keys, list)
> - if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0)
> + list_for_each_entry(k, &hdev->ltks, list)
> + if (bacmp(bdaddr, &k->bdaddr) == 0)

shall we use kernel-style here? (!bacmp())

...

Best regards
Andrei Emeltchenko