2012-01-30 22:29:10

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 0/8] [Resend] New MGMT messages for SMP Long Term Keys

Hi,

This is the last version of the code that will allow the permanent
storage of SMP Long Term Keys.

The main changes from the last version are:
* In the structure that represents a LTK the field pin_length was
replaced by the information whether or not that key is
authenticated;

* Still on that structure, it was added information about the role in
which the key should be used, e.g. a key marked as master should
only be used when the host is in the master role;

* More specific types for each type and role of key, previously it was
used the address field of the key to indentify the role of the key.

* The address type of the remote is sent with the LTK, this information
will be useful for userspace when recreating the device from storage.

Marcel, as I changed the key format in the patch "Bluetooth: Add
structures for the new LTK exchange messages" I removed your Ack
from it.

Vinicius Costa Gomes (8):
Bluetooth: Add structures for the new LTK exchange messages
Bluetooth: Rename smp_key_size to enc_key_size
Bluetooth: Add new structures for handling SMP Long Term Keys
Bluetooth: Use the updated key structures for handling LTKs
Bluetooth: Add MGMT handlers for dealing with SMP LTK's
Bluetooth: Add support for removing LTK's when pairing is removed
Bluetooth: Clean up structures left unused
Bluetooth: Add support for notifying userspace of new LTK's

include/net/bluetooth/hci.h | 9 ++--
include/net/bluetooth/hci_core.h | 35 +++++++------
include/net/bluetooth/mgmt.h | 22 ++++++++
include/net/bluetooth/smp.h | 2 +-
net/bluetooth/hci_core.c | 111 ++++++++++++++++++++++++--------------
net/bluetooth/hci_event.c | 9 +++-
net/bluetooth/mgmt.c | 88 ++++++++++++++++++++++++++++++
net/bluetooth/smp.c | 50 ++++++++++-------
8 files changed, 241 insertions(+), 85 deletions(-)

--
1.7.8.1



2012-01-31 02:04:40

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 2/8] Bluetooth: Rename smp_key_size to enc_key_size

Hi Vinicius,

On Mon, Jan 30, 2012, Vinicius Costa Gomes wrote:
> 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(-)

Patches 1 and 2 have been applied to my bluetooth-next tree (with
Marcel's acks), so no need to resend them.

Johan

2012-01-31 00:50:27

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 6/8] Bluetooth: Add support for removing LTK's when pairing is removed

Hi Vinicius,

> > > Instead of having a separated command for removing SMP keys, we use the
> > > Remove Keys command to remove *all* keys.
> > >
> > > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > > ---
> > > include/net/bluetooth/hci_core.h | 1 +
> > > net/bluetooth/mgmt.c | 6 ++++++
> > > 2 files changed, 7 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > > index 9e415dc..b61de08 100644
> > > --- a/include/net/bluetooth/hci_core.h
> > > +++ b/include/net/bluetooth/hci_core.h
> > > @@ -665,6 +665,7 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> > > int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> > > struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> > > u8 addr_type);
> > > +int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
> >
> > why do we have this export now? So why was this previously public?
>
> A previous patch ("[PATCH 3/8] Bluetooth: Add new structures for handling SMP Long Term
> Keys") adds this function but doesn't export it then. Going to fix it.
>
> Just to be clear, it is public because it is going to use it on mgmt.c.

that is what I assumed, but it was kinda funky. Please clean this up and
feel free to keep the ack.

Regards

Marcel



2012-01-31 00:49:37

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 5/8] Bluetooth: Add MGMT handlers for dealing with SMP LTK's

Hi Vinicius,

> > > This adds a method to notify that a new LTK is available and
> > > a handler to store keys coming from userspace into the kernel LTK
> > > list.
> > >
> > > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > > ---
> > > include/net/bluetooth/hci_core.h | 2 +
> > > net/bluetooth/mgmt.c | 82 ++++++++++++++++++++++++++++++++++++++
> > > 2 files changed, 84 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > > index ae3f653..9e415dc 100644
> > > --- a/include/net/bluetooth/hci_core.h
> > > +++ b/include/net/bluetooth/hci_core.h
> > > @@ -994,6 +994,8 @@ 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/mgmt.c b/net/bluetooth/mgmt.c
> > > index 8970799..57aa716 100644
> > > --- a/net/bluetooth/mgmt.c
> > > +++ b/net/bluetooth/mgmt.c
> > > @@ -2181,6 +2181,62 @@ 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;
> >
> > can we get rid of this nasty casting by using proper void pointers in
> > the first place instead of unsigned char?
>
> I will send this change as a separated patch, as there are quite a few
> places that do the same thing.

sounds good. Just clean this up. We might have some cases where we have
been doing since for 10 years now and never got around fixing it.

Regards

Marcel



2012-01-31 00:48:44

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

Hi Vinicius,

> > > This updates all the users of the older way, that was using the
> > > link_keys list to store the SMP keys, to use the new way.
> > >
> > > This includes defining new types for the keys, we have a type for each
> > > combination of STK/LTK and Master/Slave.
> > >
> > > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > > ---
> > > include/net/bluetooth/hci_core.h | 11 +++--
> > > net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
> > > net/bluetooth/hci_event.c | 9 +++-
> > > net/bluetooth/smp.c | 38 +++++++++++-------
> > > 4 files changed, 73 insertions(+), 64 deletions(-)
> > >
> > > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > > index 06eab3f..ae3f653 100644
> > > --- a/include/net/bluetooth/hci_core.h
> > > +++ b/include/net/bluetooth/hci_core.h
> > > @@ -658,12 +658,13 @@ 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]);
> > > +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
> > > +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> > > + int new_key, u8 authenticated, u8 tk[16],
> > > + u8 enc_size, u16 ediv, u8 rand[8]);
> > > int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> > > +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> > > + u8 addr_type);
> > > int hci_smp_ltks_clear(struct hci_dev *hdev);
> > >
> > > int hci_remote_oob_data_clear(struct hci_dev *hdev);
> > > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > index a7b2d6b..d00704e 100644
> > > --- a/net/bluetooth/hci_core.c
> > > +++ b/net/bluetooth/hci_core.c
> > > @@ -1222,41 +1222,40 @@ 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])
> > > {
> >
> > this kind of API seems to be rather random. We need a bit better
> > semantics here.
>
> Ok. I can leave the work of removing the STK from the list to the
> caller. Would that make more sense to you?
>
> The point is that it doesn't make sense to keep the STK around after
> it was used.

that would be better. Then at least the semantics are clear.

Regards

Marcel



2012-01-30 23:33:16

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 6/8] Bluetooth: Add support for removing LTK's when pairing is removed

Hi Marcel,

On 14:49 Mon 30 Jan, Marcel Holtmann wrote:
> Hi Vinicius,
>
> > Instead of having a separated command for removing SMP keys, we use the
> > Remove Keys command to remove *all* keys.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > include/net/bluetooth/hci_core.h | 1 +
> > net/bluetooth/mgmt.c | 6 ++++++
> > 2 files changed, 7 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 9e415dc..b61de08 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -665,6 +665,7 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> > int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> > struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> > u8 addr_type);
> > +int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
>
> why do we have this export now? So why was this previously public?

A previous patch ("[PATCH 3/8] Bluetooth: Add new structures for handling SMP Long Term
Keys") adds this function but doesn't export it then. Going to fix it.

Just to be clear, it is public because it is going to use it on mgmt.c.

>
> > int hci_smp_ltks_clear(struct hci_dev *hdev);
> >
> > int hci_remote_oob_data_clear(struct hci_dev *hdev);
> > diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> > index 57aa716..57bee59 100644
> > --- a/net/bluetooth/mgmt.c
> > +++ b/net/bluetooth/mgmt.c
> > @@ -1113,6 +1113,12 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
> > bacpy(&rp.bdaddr, &cp->bdaddr);
> > rp.status = MGMT_STATUS_FAILED;
> >
> > + 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) {
> > rp.status = MGMT_STATUS_NOT_PAIRED;
>
> Acked-by: Marcel Holtmann <[email protected]>
>
> Regards
>
> Marcel
>
>

Cheers,
--
Vinicius

2012-01-30 23:27:08

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 5/8] Bluetooth: Add MGMT handlers for dealing with SMP LTK's

Hi Marcel,

On 14:46 Mon 30 Jan, Marcel Holtmann wrote:
> Hi Vinicius,
>
> > This adds a method to notify that a new LTK is available and
> > a handler to store keys coming from userspace into the kernel LTK
> > list.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > include/net/bluetooth/hci_core.h | 2 +
> > net/bluetooth/mgmt.c | 82 ++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 84 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index ae3f653..9e415dc 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -994,6 +994,8 @@ 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/mgmt.c b/net/bluetooth/mgmt.c
> > index 8970799..57aa716 100644
> > --- a/net/bluetooth/mgmt.c
> > +++ b/net/bluetooth/mgmt.c
> > @@ -2181,6 +2181,62 @@ 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;
>
> can we get rid of this nasty casting by using proper void pointers in
> the first place instead of unsigned char?

I will send this change as a separated patch, as there are quite a few
places that do the same thing.

>
> Regards
>
> Marcel
>
>

Cheers,
--
Vinicius

2012-01-30 23:24:13

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

Hi Marcel,

On 14:44 Mon 30 Jan, Marcel Holtmann wrote:
> Hi Vinicius,
>
> > This updates all the users of the older way, that was using the
> > link_keys list to store the SMP keys, to use the new way.
> >
> > This includes defining new types for the keys, we have a type for each
> > combination of STK/LTK and Master/Slave.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > include/net/bluetooth/hci_core.h | 11 +++--
> > net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
> > net/bluetooth/hci_event.c | 9 +++-
> > net/bluetooth/smp.c | 38 +++++++++++-------
> > 4 files changed, 73 insertions(+), 64 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 06eab3f..ae3f653 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -658,12 +658,13 @@ 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]);
> > +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
> > +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> > + int new_key, u8 authenticated, u8 tk[16],
> > + u8 enc_size, u16 ediv, u8 rand[8]);
> > int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> > +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> > + u8 addr_type);
> > int hci_smp_ltks_clear(struct hci_dev *hdev);
> >
> > int hci_remote_oob_data_clear(struct hci_dev *hdev);
> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > index a7b2d6b..d00704e 100644
> > --- a/net/bluetooth/hci_core.c
> > +++ b/net/bluetooth/hci_core.c
> > @@ -1222,41 +1222,40 @@ 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])
> > {
>
> this kind of API seems to be rather random. We need a bit better
> semantics here.

Ok. I can leave the work of removing the STK from the list to the
caller. Would that make more sense to you?

The point is that it doesn't make sense to keep the STK around after
it was used.

>
> Regards
>
> Marcel
>
>

Cheers,
--
Vinicius

2012-01-30 23:13:22

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 3/8] Bluetooth: Add new structures for handling SMP Long Term Keys

Hi Marcel,

On 14:42 Mon 30 Jan, Marcel Holtmann wrote:
> Hi Vinicius,
>
> > This includes a new list for storing the keys and a new structure used
> > to represent each key.
> >
> > Some notes: authenticated is used to identify that the key may be used
> > to setup a HIGH security link. As the same list is used to store both
> > the STK's and the LTK's the type field is used so we can separate
> > between those two types of keys and if the key should be used when
> > in the master or slave role.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > include/net/bluetooth/hci.h | 5 +++++
> > include/net/bluetooth/hci_core.h | 15 +++++++++++++++
> > net/bluetooth/hci_core.c | 31 +++++++++++++++++++++++++++++++
> > 3 files changed, 51 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> > index cb9097a..83f045a 100644
> > --- a/include/net/bluetooth/hci.h
> > +++ b/include/net/bluetooth/hci.h
> > @@ -274,6 +274,11 @@ enum {
> > #define HCI_LK_SMP_LTK 0x81
> > #define HCI_LK_SMP_IRK 0x82
> > #define HCI_LK_SMP_CSRK 0x83
> > +/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
> > +#define HCI_SMP_STK 0x80
> > +#define HCI_SMP_STK_SLAVE 0x81
> > +#define HCI_SMP_LTK 0x82
> > +#define HCI_SMP_LTK_SLAVE 0x83
> >
> > /* ---- HCI Error Codes ---- */
> > #define HCI_ERROR_AUTH_FAILURE 0x05
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 896d9e4..06eab3f 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -88,6 +88,18 @@ struct bt_uuid {
> > u8 svc_hint;
> > };
> >
> > +struct smp_ltk {
> > + struct list_head list;
> > + bdaddr_t bdaddr;
> > + u8 bdaddr_type;
> > + u8 authenticated;
> > + u8 type;
> > + u8 enc_size;
> > + __le16 ediv;
> > + u8 rand[8];
> > + u8 val[16];
> > +} __packed;
> > +
> > struct key_master_id {
> > __le16 ediv;
> > u8 rand[8];
> > @@ -239,6 +251,8 @@ struct hci_dev {
> >
> > struct list_head link_keys;
> >
> > + struct list_head ltks;
> > +
>
> I am fine with this as well, but just to discuss this, don't you think
> calling this long_term_keys would be better? It makes it easier to read
> and makes it similar to link_keys.

Yeah, it looks more consistent with the longer name. Will change it.

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

Cheers,
--
Vinicius

2012-01-30 22:50:30

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 8/8] Bluetooth: Add support for notifying userspace of new LTK's

Hi Vinicius,

> If we want to have proper pairing support over LE we need to
> inform userspace that a new LTK is available, so userspace
> can store that key permanently.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> net/bluetooth/hci_core.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)

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

Regards

Marcel



2012-01-30 22:49:48

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 7/8] Bluetooth: Clean up structures left unused

Hi Vinicius,

> With the use of the new structures and lists for the SMP LTK's
> we may remove some code that is now unused. No need to have extra
> fields of information inside link_key now that it is only used
> for Link Keys.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 4 ----
> include/net/bluetooth/hci_core.h | 16 ----------------
> 2 files changed, 0 insertions(+), 20 deletions(-)

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

Regards

Marcel



2012-01-30 22:49:06

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 6/8] Bluetooth: Add support for removing LTK's when pairing is removed

Hi Vinicius,

> Instead of having a separated command for removing SMP keys, we use the
> Remove Keys command to remove *all* keys.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 1 +
> net/bluetooth/mgmt.c | 6 ++++++
> 2 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 9e415dc..b61de08 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -665,6 +665,7 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> u8 addr_type);
> +int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);

why do we have this export now? So why was this previously public?

> int hci_smp_ltks_clear(struct hci_dev *hdev);
>
> int hci_remote_oob_data_clear(struct hci_dev *hdev);
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 57aa716..57bee59 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -1113,6 +1113,12 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
> bacpy(&rp.bdaddr, &cp->bdaddr);
> rp.status = MGMT_STATUS_FAILED;
>
> + 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) {
> rp.status = MGMT_STATUS_NOT_PAIRED;

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

Regards

Marcel



2012-01-30 22:46:01

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 5/8] Bluetooth: Add MGMT handlers for dealing with SMP LTK's

Hi Vinicius,

> This adds a method to notify that a new LTK is available and
> a handler to store keys coming from userspace into the kernel LTK
> list.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 2 +
> net/bluetooth/mgmt.c | 82 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 84 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index ae3f653..9e415dc 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -994,6 +994,8 @@ 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/mgmt.c b/net/bluetooth/mgmt.c
> index 8970799..57aa716 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -2181,6 +2181,62 @@ 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;

can we get rid of this nasty casting by using proper void pointers in
the first place instead of unsigned char?

Regards

Marcel



2012-01-30 22:44:26

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

Hi Vinicius,

> This updates all the users of the older way, that was using the
> link_keys list to store the SMP keys, to use the new way.
>
> This includes defining new types for the keys, we have a type for each
> combination of STK/LTK and Master/Slave.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 11 +++--
> net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
> net/bluetooth/hci_event.c | 9 +++-
> net/bluetooth/smp.c | 38 +++++++++++-------
> 4 files changed, 73 insertions(+), 64 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 06eab3f..ae3f653 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -658,12 +658,13 @@ 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]);
> +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
> +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> + int new_key, u8 authenticated, u8 tk[16],
> + u8 enc_size, u16 ediv, u8 rand[8]);
> int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> + u8 addr_type);
> int hci_smp_ltks_clear(struct hci_dev *hdev);
>
> int hci_remote_oob_data_clear(struct hci_dev *hdev);
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index a7b2d6b..d00704e 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1222,41 +1222,40 @@ 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])
> {

this kind of API seems to be rather random. We need a bit better
semantics here.

Regards

Marcel



2012-01-30 22:42:40

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 3/8] Bluetooth: Add new structures for handling SMP Long Term Keys

Hi Vinicius,

> This includes a new list for storing the keys and a new structure used
> to represent each key.
>
> Some notes: authenticated is used to identify that the key may be used
> to setup a HIGH security link. As the same list is used to store both
> the STK's and the LTK's the type field is used so we can separate
> between those two types of keys and if the key should be used when
> in the master or slave role.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 5 +++++
> include/net/bluetooth/hci_core.h | 15 +++++++++++++++
> net/bluetooth/hci_core.c | 31 +++++++++++++++++++++++++++++++
> 3 files changed, 51 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index cb9097a..83f045a 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -274,6 +274,11 @@ enum {
> #define HCI_LK_SMP_LTK 0x81
> #define HCI_LK_SMP_IRK 0x82
> #define HCI_LK_SMP_CSRK 0x83
> +/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
> +#define HCI_SMP_STK 0x80
> +#define HCI_SMP_STK_SLAVE 0x81
> +#define HCI_SMP_LTK 0x82
> +#define HCI_SMP_LTK_SLAVE 0x83
>
> /* ---- HCI Error Codes ---- */
> #define HCI_ERROR_AUTH_FAILURE 0x05
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 896d9e4..06eab3f 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -88,6 +88,18 @@ struct bt_uuid {
> u8 svc_hint;
> };
>
> +struct smp_ltk {
> + struct list_head list;
> + bdaddr_t bdaddr;
> + u8 bdaddr_type;
> + u8 authenticated;
> + u8 type;
> + u8 enc_size;
> + __le16 ediv;
> + u8 rand[8];
> + u8 val[16];
> +} __packed;
> +
> struct key_master_id {
> __le16 ediv;
> u8 rand[8];
> @@ -239,6 +251,8 @@ struct hci_dev {
>
> struct list_head link_keys;
>
> + struct list_head ltks;
> +

I am fine with this as well, but just to discuss this, don't you think
calling this long_term_keys would be better? It makes it easier to read
and makes it similar to link_keys.

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

Regards

Marcel



2012-01-30 22:39:43

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 2/8] Bluetooth: Rename smp_key_size to enc_key_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(-)

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

Regards

Marcel



2012-01-30 22:29:18

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 8/8] Bluetooth: Add support for notifying userspace of new LTK's

If we want to have proper pairing support over LE we need to
inform userspace that a new LTK is available, so userspace
can store that key permanently.

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

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d00704e..b24cb87 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1343,6 +1343,9 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
if (!new_key)
return 0;

+ if (type & HCI_SMP_LTK)
+ mgmt_new_ltk(hdev, key, 1);
+
return 0;
}

--
1.7.8.1


2012-01-30 22:29:17

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 7/8] Bluetooth: Clean up structures left unused

With the use of the new structures and lists for the SMP LTK's
we may remove some code that is now unused. No need to have extra
fields of information inside link_key now that it is only used
for Link Keys.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 83f045a..1b634e1 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -270,10 +270,6 @@ enum {
#define HCI_LK_UNAUTH_COMBINATION 0x04
#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_LTK 0x81
-#define HCI_LK_SMP_IRK 0x82
-#define HCI_LK_SMP_CSRK 0x83
/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
#define HCI_SMP_STK 0x80
#define HCI_SMP_STK_SLAVE 0x81
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b61de08..c3ef998 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -100,28 +100,12 @@ struct smp_ltk {
u8 val[16];
} __packed;

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

struct oob_data {
--
1.7.8.1


2012-01-30 22:29:16

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 6/8] Bluetooth: Add support for removing LTK's when pairing is removed

Instead of having a separated command for removing SMP keys, we use the
Remove Keys command to remove *all* keys.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 9e415dc..b61de08 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -665,6 +665,7 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type);
+int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_smp_ltks_clear(struct hci_dev *hdev);

int hci_remote_oob_data_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 57aa716..57bee59 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1113,6 +1113,12 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
bacpy(&rp.bdaddr, &cp->bdaddr);
rp.status = MGMT_STATUS_FAILED;

+ 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) {
rp.status = MGMT_STATUS_NOT_PAIRED;
--
1.7.8.1


2012-01-30 22:29:15

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 5/8] Bluetooth: Add MGMT handlers for dealing with SMP LTK's

This adds a method to notify that a new LTK is available and
a handler to store keys coming from userspace into the kernel LTK
list.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ae3f653..9e415dc 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -994,6 +994,8 @@ 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/mgmt.c b/net/bluetooth/mgmt.c
index 8970799..57aa716 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2181,6 +2181,62 @@ 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(hdev);
+
+ hci_smp_ltks_clear(hdev);
+
+ for (i = 0; i < key_count; i++) {
+ struct mgmt_ltk_info *key = &cp->keys[i];
+ u8 type;
+
+ if (key->master)
+ type = HCI_SMP_LTK;
+ else
+ type = HCI_SMP_LTK_SLAVE;
+
+ hci_add_ltk(hdev, &key->addr.bdaddr, key->addr.type,
+ type, 0, key->authenticated, key->val,
+ key->enc_size, key->ediv, key->rand);
+ }
+
+ hci_dev_unlock(hdev);
+ hci_dev_put(hdev);
+
+ return 0;
+}
+
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
unsigned char *buf;
@@ -2313,6 +2369,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_UNBLOCK_DEVICE:
err = unblock_device(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,
@@ -2466,6 +2525,29 @@ 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.addr.bdaddr, &key->bdaddr);
+ ev.key.addr.type = key->bdaddr_type;
+ ev.key.authenticated = key->authenticated;
+ ev.key.enc_size = key->enc_size;
+ ev.key.ediv = key->ediv;
+
+ if (key->type == HCI_SMP_LTK)
+ ev.key.master = 1;
+
+ 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_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *name, u8 name_len,
u8 *dev_class)
--
1.7.8.1


2012-01-30 22:29:14

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

This updates all the users of the older way, that was using the
link_keys list to store the SMP keys, to use the new way.

This includes defining new types for the keys, we have a type for each
combination of STK/LTK and Master/Slave.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci_core.h | 11 +++--
net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
net/bluetooth/hci_event.c | 9 +++-
net/bluetooth/smp.c | 38 +++++++++++-------
4 files changed, 73 insertions(+), 64 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 06eab3f..ae3f653 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -658,12 +658,13 @@ 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]);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
+ int new_key, u8 authenticated, u8 tk[16],
+ u8 enc_size, u16 ediv, u8 rand[8]);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type);
int hci_smp_ltks_clear(struct hci_dev *hdev);

int hci_remote_oob_data_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a7b2d6b..d00704e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1222,41 +1222,40 @@ 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_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,
+ u8 addr_type)
{
- 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 (addr_type == k->bdaddr_type &&
+ 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)
@@ -1313,40 +1312,36 @@ 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 addr_type, u8 type,
+ int new_key, u8 authenticated, 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_SMP_STK) && !(type & HCI_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, addr_type);
+ 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));
+ key->bdaddr_type = addr_type;
+ memcpy(key->val, tk, sizeof(key->val));
+ key->authenticated = authenticated;
+ key->ediv = ediv;
+ key->enc_size = enc_size;
+ key->type = type;
+ memcpy(key->rand, rand, sizeof(key->rand));

- if (new_key)
- mgmt_new_link_key(hdev, key, old_key_type);
+ if (!new_key)
+ return 0;

return 0;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6fb9016..ea0b464 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3252,7 +3252,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));

@@ -3268,10 +3268,15 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,

memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
cp.handle = cpu_to_le16(conn->handle);
- conn->pin_length = ltk->pin_len;
+
+ if (ltk->authenticated)
+ conn->sec_level = BT_SECURITY_HIGH;

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

+ if (ltk->type & HCI_SMP_STK)
+ kfree(ltk);
+
hci_dev_unlock(hdev);

return;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 5818334..ad61905 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -472,8 +472,9 @@ static void random_work(struct work_struct *work)
memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);

- hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_key_size,
- ediv, rand, stk);
+ hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
+ HCI_SMP_STK_SLAVE, 0, 0, stk,
+ smp->enc_key_size, ediv, rand);
}

return;
@@ -698,22 +699,18 @@ 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, hcon->dst_type);
if (!key)
return 0;

if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
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;

@@ -816,13 +813,19 @@ 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;
+ struct hci_conn *hcon = conn->hcon;
+ u8 authenticated;

skb_pull(skb, sizeof(*rp));

- hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
- rp->ediv, rp->rand, smp->tk);
-
+ hci_dev_lock(hdev);
+ authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
+ hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
+ HCI_SMP_LTK, 1, authenticated, smp->tk,
+ smp->enc_key_size, rp->ediv, rp->rand);
smp_distribute_keys(conn, 1);
+ hci_dev_unlock(hdev);

return 0;
}
@@ -932,6 +935,8 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
if (*keydist & SMP_DIST_ENC_KEY) {
struct smp_cmd_encrypt_info enc;
struct smp_cmd_master_ident ident;
+ struct hci_conn *hcon = conn->hcon;
+ u8 authenticated;
__le16 ediv;

get_random_bytes(enc.ltk, sizeof(enc.ltk));
@@ -940,8 +945,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_key_size,
- ediv, ident.rand, enc.ltk);
+ authenticated = hcon->sec_level == BT_SECURITY_HIGH;
+ hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
+ HCI_SMP_LTK_SLAVE, 1, authenticated,
+ enc.ltk, smp->enc_key_size,
+ ediv, ident.rand);

ident.ediv = cpu_to_le16(ediv);

--
1.7.8.1


2012-01-30 22:29:13

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 3/8] Bluetooth: Add new structures for handling SMP Long Term Keys

This includes a new list for storing the keys and a new structure used
to represent each key.

Some notes: authenticated is used to identify that the key may be used
to setup a HIGH security link. As the same list is used to store both
the STK's and the LTK's the type field is used so we can separate
between those two types of keys and if the key should be used when
in the master or slave role.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci.h | 5 +++++
include/net/bluetooth/hci_core.h | 15 +++++++++++++++
net/bluetooth/hci_core.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index cb9097a..83f045a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -274,6 +274,11 @@ enum {
#define HCI_LK_SMP_LTK 0x81
#define HCI_LK_SMP_IRK 0x82
#define HCI_LK_SMP_CSRK 0x83
+/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
+#define HCI_SMP_STK 0x80
+#define HCI_SMP_STK_SLAVE 0x81
+#define HCI_SMP_LTK 0x82
+#define HCI_SMP_LTK_SLAVE 0x83

/* ---- HCI Error Codes ---- */
#define HCI_ERROR_AUTH_FAILURE 0x05
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 896d9e4..06eab3f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -88,6 +88,18 @@ struct bt_uuid {
u8 svc_hint;
};

+struct smp_ltk {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 bdaddr_type;
+ u8 authenticated;
+ u8 type;
+ u8 enc_size;
+ __le16 ediv;
+ u8 rand[8];
+ u8 val[16];
+} __packed;
+
struct key_master_id {
__le16 ediv;
u8 rand[8];
@@ -239,6 +251,8 @@ struct hci_dev {

struct list_head link_keys;

+ struct list_head ltks;
+
struct list_head remote_oob_data;

struct list_head adv_entries;
@@ -650,6 +664,7 @@ struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
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_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_smp_ltks_clear(struct hci_dev *hdev);

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 91166db..a7b2d6b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1163,6 +1163,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;
@@ -1355,6 +1367,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)
{
@@ -1638,6 +1667,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);

@@ -1739,6 +1769,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(hdev);
--
1.7.8.1


2012-01-30 22:29:12

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 2/8] Bluetooth: Rename smp_key_size to enc_key_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 aeaf5fa..7b3acdd 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -127,7 +127,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_key_size;
unsigned long smp_flags;
struct crypto_blkcipher *tfm;
struct work_struct confirm;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e08fe6c..5818334 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -250,7 +250,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_key_size = max_key_size;

return 0;
}
@@ -446,8 +446,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_key_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);

if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
reason = SMP_UNSPECIFIED;
@@ -455,7 +455,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_key_size;
} else {
u8 stk[16], r[16], rand[8];
__le16 ediv;
@@ -469,10 +469,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_key_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);

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

@@ -819,7 +819,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->dst, smp->smp_key_size,
+ hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
rp->ediv, rp->rand, smp->tk);

smp_distribute_keys(conn, 1);
@@ -940,7 +940,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_key_size,
ediv, ident.rand, enc.ltk);

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


2012-01-30 22:29:11

by Vinicius Costa Gomes

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

This defines 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.

Besides the information necessary for the restablishement of
the secure link, we added some extra information: "authenticated"
that informs if the key can be used to establish an authenticated
link, and "master" that informs the role in that the key should
be used.

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

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 6f37983..0a69448 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -288,6 +288,22 @@ struct mgmt_cp_unblock_device {
bdaddr_t bdaddr;
} __packed;

+struct mgmt_ltk_info {
+ struct mgmt_addr_info addr;
+ __u8 authenticated;
+ __u8 master;
+ __u8 enc_size;
+ __le16 ediv;
+ __u8 rand[8];
+ __u8 val[16];
+} __packed;
+
+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0026
+struct mgmt_cp_load_long_term_keys {
+ __le16 key_count;
+ struct mgmt_ltk_info keys[0];
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -387,3 +403,9 @@ struct mgmt_ev_device_blocked {
struct mgmt_ev_device_unblocked {
bdaddr_t bdaddr;
} __packed;
+
+#define MGMT_EV_NEW_LONG_TERM_KEY 0x0015
+struct mgmt_ev_new_long_term_key {
+ __u8 store_hint;
+ struct mgmt_ltk_info key;
+} __packed;
--
1.7.8.1


2012-01-17 00:17:28

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

This updates all the users of the older way, that was using the
link_keys list to store the SMP keys, to use the new way.

This includes defining new types for the keys, we have a type for each
combination of STK/LTK and Master/Slave.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci_core.h | 11 +++--
net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
net/bluetooth/hci_event.c | 9 +++-
net/bluetooth/smp.c | 38 +++++++++++-------
4 files changed, 73 insertions(+), 64 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2884509..3f93fd2 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -651,12 +651,13 @@ 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]);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
+ int new_key, u8 authenticated, u8 tk[16],
+ u8 enc_size, u16 ediv, u8 rand[8]);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type);
int hci_smp_ltks_clear(struct hci_dev *hdev);

int hci_remote_oob_data_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 3b5902d..69d07e1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1222,41 +1222,40 @@ 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_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,
+ u8 addr_type)
{
- 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 (addr_type == k->bdaddr_type &&
+ 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)
@@ -1313,40 +1312,36 @@ 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 addr_type, u8 type,
+ int new_key, u8 authenticated, 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_SMP_STK) && !(type & HCI_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, addr_type);
+ 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));
+ key->bdaddr_type = addr_type;
+ memcpy(key->val, tk, sizeof(key->val));
+ key->authenticated = authenticated;
+ key->ediv = ediv;
+ key->enc_size = enc_size;
+ key->type = type;
+ memcpy(key->rand, rand, sizeof(key->rand));

- if (new_key)
- mgmt_new_link_key(hdev, key, old_key_type);
+ if (!new_key)
+ return 0;

return 0;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c2fe964..7251e00 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3234,7 +3234,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));

@@ -3250,10 +3250,15 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,

memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
cp.handle = cpu_to_le16(conn->handle);
- conn->pin_length = ltk->pin_len;
+
+ if (ltk->authenticated)
+ conn->sec_level = BT_SECURITY_HIGH;

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

+ if (ltk->type & HCI_SMP_STK)
+ kfree(ltk);
+
hci_dev_unlock(hdev);

return;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b7f2fd1..7bc82e4 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -472,8 +472,9 @@ static void random_work(struct work_struct *work)
memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);

- hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_key_size,
- ediv, rand, stk);
+ hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
+ HCI_SMP_STK_SLAVE, 0, 0, stk,
+ smp->enc_key_size, ediv, rand);
}

return;
@@ -698,12 +699,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, hcon->dst_type);
if (!key)
return 0;

@@ -711,10 +710,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;

@@ -817,13 +814,19 @@ 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;
+ struct hci_conn *hcon = conn->hcon;
+ u8 authenticated;

skb_pull(skb, sizeof(*rp));

- hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
- rp->ediv, rp->rand, smp->tk);
-
+ hci_dev_lock(hdev);
+ authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
+ hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
+ HCI_SMP_LTK, 1, authenticated, smp->tk,
+ smp->enc_key_size, rp->ediv, rp->rand);
smp_distribute_keys(conn, 1);
+ hci_dev_unlock(hdev);

return 0;
}
@@ -933,6 +936,8 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
if (*keydist & SMP_DIST_ENC_KEY) {
struct smp_cmd_encrypt_info enc;
struct smp_cmd_master_ident ident;
+ struct hci_conn *hcon = conn->hcon;
+ u8 authenticated;
__le16 ediv;

get_random_bytes(enc.ltk, sizeof(enc.ltk));
@@ -941,8 +946,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_key_size,
- ediv, ident.rand, enc.ltk);
+ authenticated = hcon->sec_level == BT_SECURITY_HIGH;
+ hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
+ HCI_SMP_LTK_SLAVE, 1, authenticated,
+ enc.ltk, smp->enc_key_size,
+ ediv, ident.rand);

ident.ediv = cpu_to_le16(ediv);

--
1.7.8.1


2012-01-17 00:14:54

by Vinicius Costa Gomes

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

This defines 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.

Besides the information necessary for the restablishement of
the secure link, we added some extra information: "authenticated"
that informs if the key can be used to establish an authenticated
link, and "master" that informs the role in that the key should
be used.

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

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index be65d34..c0bff97 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -288,6 +288,22 @@ struct mgmt_cp_unblock_device {
bdaddr_t bdaddr;
} __packed;

+struct mgmt_ltk_info {
+ struct mgmt_addr_info addr;
+ __u8 authenticated;
+ __u8 master;
+ __u8 enc_size;
+ __le16 ediv;
+ __u8 rand[8];
+ __u8 val[16];
+} __packed;
+
+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0026
+struct mgmt_cp_load_long_term_keys {
+ __le16 key_count;
+ struct mgmt_ltk_info keys[0];
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -388,3 +404,9 @@ struct mgmt_ev_device_blocked {
struct mgmt_ev_device_unblocked {
bdaddr_t bdaddr;
} __packed;
+
+#define MGMT_EV_NEW_LONG_TERM_KEY 0x0016
+struct mgmt_ev_new_long_term_key {
+ __u8 store_hint;
+ struct mgmt_ltk_info key;
+} __packed;
--
1.7.8.1


2012-01-13 21:43:39

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

On 12:52 Fri 13 Jan, Brian Gix wrote:
> Hi Vinicius,
>
> On 1/13/2012 11:39 AM, Vinicius Costa Gomes wrote:
> >This updates all the users of the older way, that was using the
> >link_keys list to store the SMP keys, to use the new way.
> >
> >This includes defining new types for the keys, we have a type for each
> >combination of STK/LTK and Master/Slave.
> >
> >Signed-off-by: Vinicius Costa Gomes<[email protected]>
> >---
> > include/net/bluetooth/hci_core.h | 11 +++--
> > net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
> > net/bluetooth/hci_event.c | 9 +++-
> > net/bluetooth/smp.c | 38 +++++++++++-------
> > 4 files changed, 73 insertions(+), 64 deletions(-)
> >
> >diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> >index 9d77a66..7ce25ad 100644
> >--- a/include/net/bluetooth/hci_core.h
> >+++ b/include/net/bluetooth/hci_core.h
> >@@ -651,12 +651,13 @@ 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]);
> >+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
> >+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> >+ int new_key, u8 authenticated, u8 tk[16],
> >+ u8 enc_size, u16 ediv, u8 rand[8]);
> > int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> >+struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> >+ u8 addr_type);
> > int hci_smp_ltks_clear(struct hci_dev *hdev);
> >
> > int hci_remote_oob_data_clear(struct hci_dev *hdev);
> >diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> >index 3b5902d..5f41e74 100644
> >--- a/net/bluetooth/hci_core.c
> >+++ b/net/bluetooth/hci_core.c
> >@@ -1222,41 +1222,40 @@ 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_SMP_STK)
> >+ list_del(&k->list);
>
> Is HCI_SMP_STK a mask? Shouldn't this be an equality test?

I agree that this might be too "smart", but as the only difference
between the master and slave key is the last bit, using an "and" makes
the code a little shorter. If you think something more explicit is
preferable, I will fix it.

>
> >
> >- 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,
> >+ u8 addr_type)
> > {
> >- 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 (addr_type == k->bdaddr_type&&
> >+ 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)
> >@@ -1313,40 +1312,36 @@ 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 addr_type, u8 type,
> >+ int new_key, u8 authenticated, 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_SMP_STK)&& !(type& HCI_SMP_LTK))
> >+ return 0;
>
> And here.

Same reason as above.

>
> >
> >- old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK);
> >- if (old_key) {
> >+ old_key = hci_find_ltk_addr(hdev, bdaddr, addr_type);
> >+ 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;
>
> Looks like some whitespace issues.

I couldn't find any problem here. But there was a problem in the
function declaration.

>
> >- 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));
> >+ key->bdaddr_type = addr_type;
> >+ memcpy(key->val, tk, sizeof(key->val));
> >+ key->authenticated = authenticated;
> >+ key->ediv = ediv;
> >+ key->enc_size = enc_size;
> >+ key->type = type;
> >+ memcpy(key->rand, rand, sizeof(key->rand));
> >
> >- if (new_key)
> >- mgmt_new_link_key(hdev, key, old_key_type);
> >+ if (!new_key)
> >+ return 0;
> >
> > return 0;
> > }
> >diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> >index 94a9ca2..750fc0c 100644
> >--- a/net/bluetooth/hci_event.c
> >+++ b/net/bluetooth/hci_event.c
> >@@ -3227,7 +3227,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));
> >
> >@@ -3243,10 +3243,15 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
> >
> > memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
> > cp.handle = cpu_to_le16(conn->handle);
> >- conn->pin_length = ltk->pin_len;
> >+
> >+ if (ltk->authenticated)
> >+ conn->sec_level = BT_SECURITY_HIGH;
> >
> > hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp),&cp);
> >
> >+ if (ltk->type& HCI_SMP_STK)
> >+ kfree(ltk);
> >+
> > hci_dev_unlock(hdev);
> >
> > return;
> >diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> >index b7f2fd1..7bc82e4 100644
> >--- a/net/bluetooth/smp.c
> >+++ b/net/bluetooth/smp.c
> >@@ -472,8 +472,9 @@ static void random_work(struct work_struct *work)
> > memset(stk + smp->enc_key_size, 0,
> > SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
> >
> >- hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_key_size,
> >- ediv, rand, stk);
> >+ hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
> >+ HCI_SMP_STK_SLAVE, 0, 0, stk,
> >+ smp->enc_key_size, ediv, rand);
> > }
> >
> > return;
> >@@ -698,12 +699,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, hcon->dst_type);
> > if (!key)
> > return 0;
> >
> >@@ -711,10 +710,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;
> >
> >@@ -817,13 +814,19 @@ 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;
> >+ struct hci_conn *hcon = conn->hcon;
> >+ u8 authenticated;
> >
> > skb_pull(skb, sizeof(*rp));
> >
> >- hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
> >- rp->ediv, rp->rand, smp->tk);
> >-
> >+ hci_dev_lock(hdev);
> >+ authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
> >+ hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
> >+ HCI_SMP_LTK, 1, authenticated, smp->tk,
> >+ smp->enc_key_size, rp->ediv, rp->rand);
> > smp_distribute_keys(conn, 1);
> >+ hci_dev_unlock(hdev);
> >
> > return 0;
> > }
> >@@ -933,6 +936,8 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
> > if (*keydist& SMP_DIST_ENC_KEY) {
> > struct smp_cmd_encrypt_info enc;
> > struct smp_cmd_master_ident ident;
> >+ struct hci_conn *hcon = conn->hcon;
> >+ u8 authenticated;
> > __le16 ediv;
> >
> > get_random_bytes(enc.ltk, sizeof(enc.ltk));
> >@@ -941,8 +946,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_key_size,
> >- ediv, ident.rand, enc.ltk);
> >+ authenticated = hcon->sec_level == BT_SECURITY_HIGH;
> >+ hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
> >+ HCI_SMP_LTK_SLAVE, 1, authenticated,
> >+ enc.ltk, smp->enc_key_size,
> >+ ediv, ident.rand);
> >
> > ident.ediv = cpu_to_le16(ediv);
> >
>
>
> --
> Brian Gix
> [email protected]
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

--
Vinicius

2012-01-13 20:52:27

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 4/8] Bluetooth: Use the updated key structures for handling LTKs

Hi Vinicius,

On 1/13/2012 11:39 AM, Vinicius Costa Gomes wrote:
> This updates all the users of the older way, that was using the
> link_keys list to store the SMP keys, to use the new way.
>
> This includes defining new types for the keys, we have a type for each
> combination of STK/LTK and Master/Slave.
>
> Signed-off-by: Vinicius Costa Gomes<[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 11 +++--
> net/bluetooth/hci_core.c | 79 ++++++++++++++++++--------------------
> net/bluetooth/hci_event.c | 9 +++-
> net/bluetooth/smp.c | 38 +++++++++++-------
> 4 files changed, 73 insertions(+), 64 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 9d77a66..7ce25ad 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -651,12 +651,13 @@ 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]);
> +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
> +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
> + int new_key, u8 authenticated, u8 tk[16],
> + u8 enc_size, u16 ediv, u8 rand[8]);
> int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
> + u8 addr_type);
> int hci_smp_ltks_clear(struct hci_dev *hdev);
>
> int hci_remote_oob_data_clear(struct hci_dev *hdev);
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 3b5902d..5f41e74 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1222,41 +1222,40 @@ 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_SMP_STK)
> + list_del(&k->list);

Is HCI_SMP_STK a mask? Shouldn't this be an equality test?

>
> - 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,
> + u8 addr_type)
> {
> - 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 (addr_type == k->bdaddr_type&&
> + 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)
> @@ -1313,40 +1312,36 @@ 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 addr_type, u8 type,
> + int new_key, u8 authenticated, 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_SMP_STK)&& !(type& HCI_SMP_LTK))
> + return 0;

And here.

>
> - old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK);
> - if (old_key) {
> + old_key = hci_find_ltk_addr(hdev, bdaddr, addr_type);
> + 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;

Looks like some whitespace issues.

> - 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));
> + key->bdaddr_type = addr_type;
> + memcpy(key->val, tk, sizeof(key->val));
> + key->authenticated = authenticated;
> + key->ediv = ediv;
> + key->enc_size = enc_size;
> + key->type = type;
> + memcpy(key->rand, rand, sizeof(key->rand));
>
> - if (new_key)
> - mgmt_new_link_key(hdev, key, old_key_type);
> + if (!new_key)
> + return 0;
>
> return 0;
> }
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 94a9ca2..750fc0c 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -3227,7 +3227,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));
>
> @@ -3243,10 +3243,15 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
>
> memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
> cp.handle = cpu_to_le16(conn->handle);
> - conn->pin_length = ltk->pin_len;
> +
> + if (ltk->authenticated)
> + conn->sec_level = BT_SECURITY_HIGH;
>
> hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp),&cp);
>
> + if (ltk->type& HCI_SMP_STK)
> + kfree(ltk);
> +
> hci_dev_unlock(hdev);
>
> return;
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index b7f2fd1..7bc82e4 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -472,8 +472,9 @@ static void random_work(struct work_struct *work)
> memset(stk + smp->enc_key_size, 0,
> SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
>
> - hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_key_size,
> - ediv, rand, stk);
> + hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
> + HCI_SMP_STK_SLAVE, 0, 0, stk,
> + smp->enc_key_size, ediv, rand);
> }
>
> return;
> @@ -698,12 +699,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, hcon->dst_type);
> if (!key)
> return 0;
>
> @@ -711,10 +710,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;
>
> @@ -817,13 +814,19 @@ 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;
> + struct hci_conn *hcon = conn->hcon;
> + u8 authenticated;
>
> skb_pull(skb, sizeof(*rp));
>
> - hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
> - rp->ediv, rp->rand, smp->tk);
> -
> + hci_dev_lock(hdev);
> + authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
> + hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
> + HCI_SMP_LTK, 1, authenticated, smp->tk,
> + smp->enc_key_size, rp->ediv, rp->rand);
> smp_distribute_keys(conn, 1);
> + hci_dev_unlock(hdev);
>
> return 0;
> }
> @@ -933,6 +936,8 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
> if (*keydist& SMP_DIST_ENC_KEY) {
> struct smp_cmd_encrypt_info enc;
> struct smp_cmd_master_ident ident;
> + struct hci_conn *hcon = conn->hcon;
> + u8 authenticated;
> __le16 ediv;
>
> get_random_bytes(enc.ltk, sizeof(enc.ltk));
> @@ -941,8 +946,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_key_size,
> - ediv, ident.rand, enc.ltk);
> + authenticated = hcon->sec_level == BT_SECURITY_HIGH;
> + hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
> + HCI_SMP_LTK_SLAVE, 1, authenticated,
> + enc.ltk, smp->enc_key_size,
> + ediv, ident.rand);
>
> ident.ediv = cpu_to_le16(ediv);
>


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

2012-01-13 20:43:18

by Brian Gix

[permalink] [raw]
Subject: Re: [PATCH 3/8] Bluetooth: Add new structures for handling SMP Long Term Keys

Hi Vinicius,

On 1/13/2012 11:39 AM, Vinicius Costa Gomes wrote:
> This includes a new list for storing the keys and a new structure used
> to represent each key.
>
> Some notes: authenticated is used to identify that the key may be used
> to setup a HIGH security link. As the same list is used to store both
> the STK's and the LTK's the type field is used so we can separate
> between those two types of keys and if the key should be used when
> in the master or slave role.
>
> Signed-off-by: Vinicius Costa Gomes<[email protected]>
> ---
> include/net/bluetooth/hci.h | 5 +++++
> include/net/bluetooth/hci_core.h | 15 +++++++++++++++
> net/bluetooth/hci_core.c | 31 +++++++++++++++++++++++++++++++
> 3 files changed, 51 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 8499307..3056115 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -273,6 +273,11 @@ enum {
> #define HCI_LK_SMP_LTK 0x81
> #define HCI_LK_SMP_IRK 0x82
> #define HCI_LK_SMP_CSRK 0x83
> +/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
> +#define HCI_SMP_STK 0x80
> +#define HCI_SMP_STK_SLAVE 0x81
> +#define HCI_SMP_LTK 0x82
> +#define HCI_SMP_LTK_SLAVE 0x83

This list should be contiguous, and you should probably remove the
others at the same time. I would also suggest adding MASTER and SLAVE
versions of CSRK and maybe IRK as well. (IRK is used differently, and
may not need a Master/Slave version, but it wouldn't hurt anything).
CSRK, when implimented will definitely need both Master and Slave versions.

>
> /* ---- HCI Error Codes ---- */
> #define HCI_ERROR_AUTH_FAILURE 0x05
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 59e3541..9d77a66 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -88,6 +88,18 @@ struct bt_uuid {
> u8 svc_hint;
> };
>
> +struct smp_ltk {
> + struct list_head list;
> + bdaddr_t bdaddr;
> + u8 bdaddr_type;
> + u8 authenticated;
> + u8 type;
> + u8 enc_size;
> + __le16 ediv;
> + u8 rand[8];
> + u8 val[16];
> +} __packed;
> +
> struct key_master_id {
> __le16 ediv;
> u8 rand[8];
> @@ -240,6 +252,8 @@ struct hci_dev {
>
> struct list_head link_keys;
>
> + struct list_head ltks;
> +
> struct list_head remote_oob_data;
>
> struct list_head adv_entries;
> @@ -643,6 +657,7 @@ struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
> 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_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
> +int hci_smp_ltks_clear(struct hci_dev *hdev);
>
> 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 a7b7200..3b5902d 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1163,6 +1163,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;
> @@ -1355,6 +1367,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)
> {
> @@ -1638,6 +1667,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);
>
> @@ -1739,6 +1769,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(hdev);


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

2012-01-13 20:40:27

by Vinicius Costa Gomes

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

Hi Brian,

On 12:37 Fri 13 Jan, Brian Gix wrote:
> Hi Vinicius,
>
> On 1/13/2012 11:39 AM, Vinicius Costa Gomes wrote:
> >This defines 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 | 22 ++++++++++++++++++++++
> > 1 files changed, 22 insertions(+), 0 deletions(-)
> >
> >diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> >index be65d34..994b551 100644
> >--- a/include/net/bluetooth/mgmt.h
> >+++ b/include/net/bluetooth/mgmt.h
> >@@ -288,6 +288,22 @@ struct mgmt_cp_unblock_device {
> > bdaddr_t bdaddr;
> > } __packed;
> >
> >+struct mgmt_ltk_info {
> >+ struct mgmt_addr_info addr;
> >+ __u8 authenticated;
> >+ __u8 master;
> >+ __u8 enc_size;
> >+ __le16 ediv;
> >+ __u8 rand[8];
> >+ __u8 val[16];
> >+} __packed;
> >+
> >+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0026
> >+struct mgmt_cp_load_long_term_keys {
> >+ __u16 key_count;
> >+ struct mgmt_ltk_info keys[0];
> >+} __packed;
> >+
>
> I think all multi-octet values should be going over the MGMT
> interface in "network order", so shouldn't key_count here be __le16
> ?
>

You are right. Going to fix it, thanks. It was a leftover from the last
version of these patches.

>
>
>
> > #define MGMT_EV_CMD_COMPLETE 0x0001
> > struct mgmt_ev_cmd_complete {
> > __le16 opcode;
> >@@ -388,3 +404,9 @@ struct mgmt_ev_device_blocked {
> > struct mgmt_ev_device_unblocked {
> > bdaddr_t bdaddr;
> > } __packed;
> >+
> >+#define MGMT_EV_NEW_LONG_TERM_KEY 0x0016
> >+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

2012-01-13 20:37:05

by Brian Gix

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

Hi Vinicius,

On 1/13/2012 11:39 AM, Vinicius Costa Gomes wrote:
> This defines 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 | 22 ++++++++++++++++++++++
> 1 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index be65d34..994b551 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -288,6 +288,22 @@ struct mgmt_cp_unblock_device {
> bdaddr_t bdaddr;
> } __packed;
>
> +struct mgmt_ltk_info {
> + struct mgmt_addr_info addr;
> + __u8 authenticated;
> + __u8 master;
> + __u8 enc_size;
> + __le16 ediv;
> + __u8 rand[8];
> + __u8 val[16];
> +} __packed;
> +
> +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0026
> +struct mgmt_cp_load_long_term_keys {
> + __u16 key_count;
> + struct mgmt_ltk_info keys[0];
> +} __packed;
> +

I think all multi-octet values should be going over the MGMT interface
in "network order", so shouldn't key_count here be __le16 ?




> #define MGMT_EV_CMD_COMPLETE 0x0001
> struct mgmt_ev_cmd_complete {
> __le16 opcode;
> @@ -388,3 +404,9 @@ struct mgmt_ev_device_blocked {
> struct mgmt_ev_device_unblocked {
> bdaddr_t bdaddr;
> } __packed;
> +
> +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0016
> +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