2012-02-03 00:07:58

by Vinicius Costa Gomes

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

Changes from last version:
* Updated code acording to review comments;
* Added a patch that removes useless casts from MGMT code;


Cheers,

Vinicius Costa Gomes (7):
Bluetooth: Fix doing some useless casts when receiving MGMT commands
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 +++--
net/bluetooth/hci_core.c | 108 +++++++++------
net/bluetooth/hci_event.c | 11 ++-
net/bluetooth/mgmt.c | 296 ++++++++++++++++++++++----------------
net/bluetooth/smp.c | 38 +++--
6 files changed, 296 insertions(+), 201 deletions(-)

--
1.7.8.1



2012-02-03 01:25:03

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v2 0/7] New MGMT messages for SMP Long Term Keys

Hi Vinicius,

On Thu, Feb 02, 2012, Vinicius Costa Gomes wrote:
> Changes from last version:
> * Updated code acording to review comments;
> * Added a patch that removes useless casts from MGMT code;
>
>
> Cheers,
>
> Vinicius Costa Gomes (7):
> Bluetooth: Fix doing some useless casts when receiving MGMT commands
> 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 +++--
> net/bluetooth/hci_core.c | 108 +++++++++------
> net/bluetooth/hci_event.c | 11 ++-
> net/bluetooth/mgmt.c | 296 ++++++++++++++++++++++----------------
> net/bluetooth/smp.c | 38 +++--
> 6 files changed, 296 insertions(+), 201 deletions(-)

All seven patches have been pushed to my bluetooth-next tree. I went
ahead and did the minor changes proposed by Marcel myself.

Johan

2012-02-03 00:24:17

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v2 4/7] 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 | 80 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 82 insertions(+), 0 deletions(-)

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

Regards

Marcel



2012-02-03 00:23:22

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v2 3/7] 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 | 76 ++++++++++++++++---------------------
> net/bluetooth/hci_event.c | 11 ++++-
> net/bluetooth/smp.c | 38 +++++++++++-------
> 4 files changed, 71 insertions(+), 65 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index c998176..3f22f03 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);
> +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]);
> +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_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
> - u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
> int hci_smp_ltks_clear(struct hci_dev *hdev);
> int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
>
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index a28e637..ff519b5 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1222,41 +1222,35 @@ 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])
> +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;
>
> - if (k->type != HCI_LK_SMP_LTK)
> + list_for_each_entry(k, &hdev->long_term_keys, list) {
> + if (k->ediv != ediv ||
> + memcmp(rand, k->rand, sizeof(k->rand)))
> continue;
>
> - if (k->dlen != sizeof(*id))
> - continue;
> -
> - 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)

minor nitpick with naming here. It should be find_ltk_by_addr. That way
it is consistent with similar calls in the Bluetooth subsystem.

Also in theory we might be better using "lookup" than "find", but you
can fix that one later one. Otherwise this looks fine.

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

Regards

Marcel



2012-02-03 00:20:10

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] Bluetooth: Fix doing some useless casts when receiving MGMT commands

Hi Vinicius,

> Every command handler of mgmt does a cast to the command structure
> so it can properly interpreted. So we can avoid that cast if we
> make those functions receive a void * directly.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> net/bluetooth/mgmt.c | 210 +++++++++++++++++++++-----------------------------
> 1 files changed, 88 insertions(+), 122 deletions(-)
>
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 00ab083..f8720de 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -611,15 +611,13 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
> return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
> }
>
> -static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
> +static int set_powered(struct sock *sk, u16 index, void *cp_data, u16 len)
> {
> - struct mgmt_mode *cp;
> + struct mgmt_mode *cp = cp_data;

why are we doing the rename to cp_data here. I rather keep this as
*data. Otherwise this is fine.

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

Regards

Marcel



2012-02-03 00:08:05

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 7/7] 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]>
Acked-by: Marcel Holtmann <[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 ff519b5..aa5e571 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1338,6 +1338,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-02-03 00:08:04

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 6/7] 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]>
Acked-by: Marcel Holtmann <[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 6cf39d7..9ced7dc 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-02-03 00:08:03

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 5/7] 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]>
Acked-by: Marcel Holtmann <[email protected]>
---
net/bluetooth/mgmt.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d1433de..4d9c8ce 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1089,6 +1089,12 @@ static int remove_keys(struct sock *sk, u16 index, void *cp_data, u16 len)
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-02-03 00:08:02

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 4/7] 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 | 80 ++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3f22f03..6cf39d7 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -995,6 +995,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 f8720de..d1433de 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2196,6 +2196,60 @@ done:
return err;
}

+static int load_long_term_keys(struct sock *sk, u16 index,
+ void *cp_data, u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_load_long_term_keys *cp = cp_data;
+ u16 key_count, expected_len;
+ int i;
+
+ 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)
{
void *buf;
@@ -2330,6 +2384,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_UNBLOCK_DEVICE:
err = unblock_device(sk, index, cp, len);
break;
+ case MGMT_OP_LOAD_LONG_TERM_KEYS:
+ err = load_long_term_keys(sk, index, cp, len);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, index, opcode,
@@ -2483,6 +2540,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-02-03 00:08:01

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 3/7] 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 | 76 ++++++++++++++++---------------------
net/bluetooth/hci_event.c | 11 ++++-
net/bluetooth/smp.c | 38 +++++++++++-------
4 files changed, 71 insertions(+), 65 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c998176..3f22f03 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);
+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]);
+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_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
- u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
int hci_smp_ltks_clear(struct hci_dev *hdev);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a28e637..ff519b5 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1222,41 +1222,35 @@ 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])
+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;

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

- if (k->dlen != sizeof(*id))
- continue;
-
- 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->long_term_keys, 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 +1307,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->long_term_keys);
}

- 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 a86f82b..23dbb31 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3256,7 +3256,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));

@@ -3272,10 +3272,17 @@ 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) {
+ list_del(&ltk->list);
+ kfree(ltk);
+ }
+
hci_dev_unlock(hdev);

return;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 9ff56e1..19d1371 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -475,8 +475,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;
@@ -701,22 +702,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;

@@ -819,13 +816,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;
}
@@ -935,6 +938,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));
@@ -943,8 +948,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-02-03 00:08:00

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 2/7] 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]>
Acked-by: Marcel Holtmann <[email protected]>
---
include/net/bluetooth/hci.h | 5 +++++
include/net/bluetooth/hci_core.h | 16 ++++++++++++++++
net/bluetooth/hci_core.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 52 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..c998176 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 long_term_keys;
+
struct list_head remote_oob_data;

struct list_head adv_entries;
@@ -647,8 +661,10 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
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_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
+int hci_smp_ltks_clear(struct hci_dev *hdev);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);

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 45e2d2a..a28e637 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->long_term_keys, 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->long_term_keys, 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->long_term_keys);

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-02-03 00:07:59

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [PATCH v2 1/7] Bluetooth: Fix doing some useless casts when receiving MGMT commands

Every command handler of mgmt does a cast to the command structure
so it can properly interpreted. So we can avoid that cast if we
make those functions receive a void * directly.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 00ab083..f8720de 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -611,15 +611,13 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
}

-static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
+static int set_powered(struct sock *sk, u16 index, void *cp_data, u16 len)
{
- struct mgmt_mode *cp;
+ struct mgmt_mode *cp = cp_data;
struct hci_dev *hdev;
struct pending_cmd *cmd;
int err, up;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -645,7 +643,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
goto failed;
}

- cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, cp_data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -664,17 +662,14 @@ failed:
return err;
}

-static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int set_discoverable(struct sock *sk, u16 index, void *cp_data, u16 len)
{
- struct mgmt_cp_set_discoverable *cp;
+ struct mgmt_cp_set_discoverable *cp = cp_data;
struct hci_dev *hdev;
struct pending_cmd *cmd;
u8 scan;
int err;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -707,7 +702,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
goto failed;
}

- cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, cp_data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -734,17 +729,14 @@ failed:
return err;
}

-static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int set_connectable(struct sock *sk, u16 index, void *cp_data, u16 len)
{
- struct mgmt_mode *cp;
+ struct mgmt_mode *cp = cp_data;
struct hci_dev *hdev;
struct pending_cmd *cmd;
u8 scan;
int err;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -776,7 +768,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
goto failed;
}

- cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, cp_data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -827,16 +819,13 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
return 0;
}

-static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int set_pairable(struct sock *sk, u16 index, void *cp_data, u16 len)
{
- struct mgmt_mode *cp;
+ struct mgmt_mode *cp = cp_data;
struct hci_dev *hdev;
__le32 ev;
int err;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -870,15 +859,13 @@ failed:
return err;
}

-static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
+static int add_uuid(struct sock *sk, u16 index, void *cp_data, u16 len)
{
- struct mgmt_cp_add_uuid *cp;
+ struct mgmt_cp_add_uuid *cp = cp_data;
struct hci_dev *hdev;
struct bt_uuid *uuid;
int err;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -920,16 +907,14 @@ failed:
return err;
}

-static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
+static int remove_uuid(struct sock *sk, u16 index, void *cp_data, u16 len)
{
+ struct mgmt_cp_remove_uuid *cp = cp_data;
struct list_head *p, *n;
- struct mgmt_cp_remove_uuid *cp;
struct hci_dev *hdev;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int err, found;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -983,15 +968,12 @@ unlock:
return err;
}

-static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int set_dev_class(struct sock *sk, u16 index, void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_set_dev_class *cp;
+ struct mgmt_cp_set_dev_class *cp = cp_data;
int err;

- cp = (void *) data;
-
BT_DBG("request for hci%u", index);

if (len != sizeof(*cp))
@@ -1026,16 +1008,13 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
return err;
}

-static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int load_link_keys(struct sock *sk, u16 index, void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_load_link_keys *cp;
+ struct mgmt_cp_load_link_keys *cp = cp_data;
u16 key_count, expected_len;
int i;

- cp = (void *) data;
-
if (len < sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
@@ -1085,19 +1064,16 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
return 0;
}

-static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int remove_keys(struct sock *sk, u16 index, void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_remove_keys *cp;
+ struct mgmt_cp_remove_keys *cp = cp_data;
struct mgmt_rp_remove_keys rp;
struct hci_cp_disconnect dc;
struct pending_cmd *cmd;
struct hci_conn *conn;
int err;

- cp = (void *) data;
-
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
MGMT_STATUS_INVALID_PARAMS);
@@ -1154,10 +1130,10 @@ unlock:
return err;
}

-static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
+static int disconnect(struct sock *sk, u16 index, void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_disconnect *cp;
+ struct mgmt_cp_disconnect *cp = cp_data;
struct hci_cp_disconnect dc;
struct pending_cmd *cmd;
struct hci_conn *conn;
@@ -1165,8 +1141,6 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)

BT_DBG("");

- cp = (void *) data;
-
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_DISCONNECT,
MGMT_STATUS_INVALID_PARAMS);
@@ -1200,7 +1174,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
goto failed;
}

- cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, cp_data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -1314,12 +1288,12 @@ static int send_pin_code_neg_reply(struct sock *sk, u16 index,
return err;
}

-static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
+static int pin_code_reply(struct sock *sk, u16 index, void *cp_data,
u16 len)
{
struct hci_dev *hdev;
struct hci_conn *conn;
- struct mgmt_cp_pin_code_reply *cp;
+ struct mgmt_cp_pin_code_reply *cp = cp_data;
struct mgmt_cp_pin_code_neg_reply ncp;
struct hci_cp_pin_code_reply reply;
struct pending_cmd *cmd;
@@ -1327,8 +1301,6 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,

BT_DBG("");

- cp = (void *) data;
-
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_INVALID_PARAMS);
@@ -1366,7 +1338,8 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
goto failed;
}

- cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, cp_data,
+ len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -1387,17 +1360,15 @@ failed:
return err;
}

-static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
+static int pin_code_neg_reply(struct sock *sk, u16 index, void *cp_data,
u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_pin_code_neg_reply *cp;
+ struct mgmt_cp_pin_code_neg_reply *cp = cp_data;
int err;

BT_DBG("");

- cp = (void *) data;
-
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
MGMT_STATUS_INVALID_PARAMS);
@@ -1424,16 +1395,14 @@ failed:
return err;
}

-static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
+static int set_io_capability(struct sock *sk, u16 index, void *cp_data,
u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_set_io_capability *cp;
+ struct mgmt_cp_set_io_capability *cp = cp_data;

BT_DBG("");

- cp = (void *) data;
-
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
MGMT_STATUS_INVALID_PARAMS);
@@ -1508,10 +1477,10 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
pairing_complete(cmd, status);
}

-static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
+static int pair_device(struct sock *sk, u16 index, void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_pair_device *cp;
+ struct mgmt_cp_pair_device *cp = cp_data;
struct mgmt_rp_pair_device rp;
struct pending_cmd *cmd;
u8 sec_level, auth_type;
@@ -1520,8 +1489,6 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)

BT_DBG("");

- cp = (void *) data;
-
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS);
@@ -1565,7 +1532,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
goto unlock;
}

- cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, cp_data, len);
if (!cmd) {
err = -ENOMEM;
hci_conn_put(conn);
@@ -1721,7 +1688,7 @@ done:

static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
{
- struct mgmt_cp_user_confirm_reply *cp = (void *) data;
+ struct mgmt_cp_user_confirm_reply *cp = data;

BT_DBG("");

@@ -1752,7 +1719,7 @@ static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,

static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
{
- struct mgmt_cp_user_passkey_reply *cp = (void *) data;
+ struct mgmt_cp_user_passkey_reply *cp = data;

BT_DBG("");

@@ -1768,7 +1735,7 @@ static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
u16 len)
{
- struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data;
+ struct mgmt_cp_user_passkey_neg_reply *cp = data;

BT_DBG("");

@@ -1781,10 +1748,10 @@ static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
}

-static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
+static int set_local_name(struct sock *sk, u16 index, void *cp_data,
u16 len)
{
- struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
+ struct mgmt_cp_set_local_name *mgmt_cp = cp_data;
struct hci_cp_write_local_name hci_cp;
struct hci_dev *hdev;
struct pending_cmd *cmd;
@@ -1803,7 +1770,8 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,

hci_dev_lock(hdev);

- cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, cp_data,
+ len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -1872,11 +1840,11 @@ unlock:
return err;
}

-static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int add_remote_oob_data(struct sock *sk, u16 index, void *cp_data,
+ u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
+ struct mgmt_cp_add_remote_oob_data *cp = cp_data;
int err;

BT_DBG("hci%u ", index);
@@ -1908,10 +1876,10 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
}

static int remove_remote_oob_data(struct sock *sk, u16 index,
- unsigned char *data, u16 len)
+ void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
+ struct mgmt_cp_remove_remote_oob_data *cp = cp_data;
int err;

BT_DBG("hci%u ", index);
@@ -1942,9 +1910,9 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
}

static int start_discovery(struct sock *sk, u16 index,
- unsigned char *data, u16 len)
+ void *cp_data, u16 len)
{
- struct mgmt_cp_start_discovery *cp = (void *) data;
+ struct mgmt_cp_start_discovery *cp = cp_data;
struct pending_cmd *cmd;
struct hci_dev *hdev;
int err;
@@ -2054,10 +2022,10 @@ unlock:
return err;
}

-static int confirm_name(struct sock *sk, u16 index, unsigned char *data,
+static int confirm_name(struct sock *sk, u16 index, void *cp_data,
u16 len)
{
- struct mgmt_cp_confirm_name *cp = (void *) data;
+ struct mgmt_cp_confirm_name *cp = cp_data;
struct inquiry_entry *e;
struct hci_dev *hdev;
int err;
@@ -2104,11 +2072,11 @@ failed:
return err;
}

-static int block_device(struct sock *sk, u16 index, unsigned char *data,
+static int block_device(struct sock *sk, u16 index, void *cp_data,
u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_block_device *cp = (void *) data;
+ struct mgmt_cp_block_device *cp = cp_data;
int err;

BT_DBG("hci%u", index);
@@ -2138,11 +2106,10 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
return err;
}

-static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int unblock_device(struct sock *sk, u16 index, void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_cp_unblock_device *cp = (void *) data;
+ struct mgmt_cp_unblock_device *cp = cp_data;
int err;

BT_DBG("hci%u", index);
@@ -2174,10 +2141,10 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
}

static int set_fast_connectable(struct sock *sk, u16 index,
- unsigned char *data, u16 len)
+ void *cp_data, u16 len)
{
struct hci_dev *hdev;
- struct mgmt_mode *cp = (void *) data;
+ struct mgmt_mode *cp = cp_data;
struct hci_cp_write_page_scan_activity acp;
u8 type;
int err;
@@ -2231,7 +2198,8 @@ done:

int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
- unsigned char *buf;
+ void *buf;
+ u8 *cp;
struct mgmt_hdr *hdr;
u16 opcode, index, len;
int err;
@@ -2250,7 +2218,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
goto done;
}

- hdr = (struct mgmt_hdr *) buf;
+ hdr = buf;
opcode = get_unaligned_le16(&hdr->opcode);
index = get_unaligned_le16(&hdr->index);
len = get_unaligned_le16(&hdr->len);
@@ -2260,6 +2228,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
goto done;
}

+ cp = buf + sizeof(*hdr);
+
switch (opcode) {
case MGMT_OP_READ_VERSION:
err = read_version(sk);
@@ -2271,98 +2241,94 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
err = read_controller_info(sk, index);
break;
case MGMT_OP_SET_POWERED:
- err = set_powered(sk, index, buf + sizeof(*hdr), len);
+ err = set_powered(sk, index, cp, len);
break;
case MGMT_OP_SET_DISCOVERABLE:
- err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
+ err = set_discoverable(sk, index, cp, len);
break;
case MGMT_OP_SET_CONNECTABLE:
- err = set_connectable(sk, index, buf + sizeof(*hdr), len);
+ err = set_connectable(sk, index, cp, len);
break;
case MGMT_OP_SET_FAST_CONNECTABLE:
- err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
- len);
+ err = set_fast_connectable(sk, index, cp, len);
break;
case MGMT_OP_SET_PAIRABLE:
- err = set_pairable(sk, index, buf + sizeof(*hdr), len);
+ err = set_pairable(sk, index, cp, len);
break;
case MGMT_OP_ADD_UUID:
- err = add_uuid(sk, index, buf + sizeof(*hdr), len);
+ err = add_uuid(sk, index, cp, len);
break;
case MGMT_OP_REMOVE_UUID:
- err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
+ err = remove_uuid(sk, index, cp, len);
break;
case MGMT_OP_SET_DEV_CLASS:
- err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
+ err = set_dev_class(sk, index, cp, len);
break;
case MGMT_OP_LOAD_LINK_KEYS:
- err = load_link_keys(sk, index, buf + sizeof(*hdr), len);
+ err = load_link_keys(sk, index, cp, len);
break;
case MGMT_OP_REMOVE_KEYS:
- err = remove_keys(sk, index, buf + sizeof(*hdr), len);
+ err = remove_keys(sk, index, cp, len);
break;
case MGMT_OP_DISCONNECT:
- err = disconnect(sk, index, buf + sizeof(*hdr), len);
+ err = disconnect(sk, index, cp, len);
break;
case MGMT_OP_GET_CONNECTIONS:
err = get_connections(sk, index);
break;
case MGMT_OP_PIN_CODE_REPLY:
- err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
+ err = pin_code_reply(sk, index, cp, len);
break;
case MGMT_OP_PIN_CODE_NEG_REPLY:
- err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
+ err = pin_code_neg_reply(sk, index, cp, len);
break;
case MGMT_OP_SET_IO_CAPABILITY:
- err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
+ err = set_io_capability(sk, index, cp, len);
break;
case MGMT_OP_PAIR_DEVICE:
- err = pair_device(sk, index, buf + sizeof(*hdr), len);
+ err = pair_device(sk, index, cp, len);
break;
case MGMT_OP_CANCEL_PAIR_DEVICE:
err = cancel_pair_device(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_USER_CONFIRM_REPLY:
- err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len);
+ err = user_confirm_reply(sk, index, cp, len);
break;
case MGMT_OP_USER_CONFIRM_NEG_REPLY:
- err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr),
- len);
+ err = user_confirm_neg_reply(sk, index, cp, len);
break;
case MGMT_OP_USER_PASSKEY_REPLY:
- err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len);
+ err = user_passkey_reply(sk, index, cp, len);
break;
case MGMT_OP_USER_PASSKEY_NEG_REPLY:
- err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr),
- len);
+ err = user_passkey_neg_reply(sk, index, cp, len);
break;
case MGMT_OP_SET_LOCAL_NAME:
- err = set_local_name(sk, index, buf + sizeof(*hdr), len);
+ err = set_local_name(sk, index, cp, len);
break;
case MGMT_OP_READ_LOCAL_OOB_DATA:
err = read_local_oob_data(sk, index);
break;
case MGMT_OP_ADD_REMOTE_OOB_DATA:
- err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
+ err = add_remote_oob_data(sk, index, cp, len);
break;
case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
- err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
- len);
+ err = remove_remote_oob_data(sk, index, cp, len);
break;
case MGMT_OP_START_DISCOVERY:
- err = start_discovery(sk, index, buf + sizeof(*hdr), len);
+ err = start_discovery(sk, index, cp, len);
break;
case MGMT_OP_STOP_DISCOVERY:
err = stop_discovery(sk, index);
break;
case MGMT_OP_CONFIRM_NAME:
- err = confirm_name(sk, index, buf + sizeof(*hdr), len);
+ err = confirm_name(sk, index, cp, len);
break;
case MGMT_OP_BLOCK_DEVICE:
- err = block_device(sk, index, buf + sizeof(*hdr), len);
+ err = block_device(sk, index, cp, len);
break;
case MGMT_OP_UNBLOCK_DEVICE:
- err = unblock_device(sk, index, buf + sizeof(*hdr), len);
+ err = unblock_device(sk, index, cp, len);
break;
default:
BT_DBG("Unknown op %u", opcode);
--
1.7.8.1