2011-06-07 22:50:01

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 00/13] SMP Key Exchange Support

Hi,

This will introduce support for Exchanging Keys with remote devices.

The keys will be generated by the kernel and will be notified to
userspace so they can be stored. The management interface will
be used for this communication.

The "new key" event and the "load keys" command had to be changed, so
more information could be added to each key, for example, the long term
key has a 16bit number and a 64bit random value associated with it. But,
userpace isn't aware of the format of those keys, it just knows that they
are present or not.

Another thing that should be noted is that the link_keys list (already
present) is used to store these keys, including the Short Term Key, as
it makes the handling of this type of key more transparent.

The related userspace changes should appear a little after this series.


Cheers,
--

Anderson Lizardo (1):
Bluetooth: Add support for random destination address

Vinicius Costa Gomes (12):
Bluetooth: Add support for SMP phase 3 (key distribution)
Bluetooth: Fix sending wrong IO Capabilities value
Bluetooth: Add new structures for supporting SM key distribution
Bluetooth: Add functions to manipulate the link key list for SMP
Bluetooth: Reject an encryption request when the key isn't found
Bluetooth: Add support for providing parameters to LE Start
Encryption
Bluetooth: Fix SM pairing parameters negotiation
Bluetooth: Add support for storing the LTK
Bluetooth: Use the link key list to temporarily store the STK
Bluetooth: Use the stored LTK for restabilishing security
Bluetooth: Remove unused field in hci_conn
Bluetooth: Add support for communicating keys with userspace

include/net/bluetooth/hci.h | 4 +
include/net/bluetooth/hci_core.h | 25 ++++-
include/net/bluetooth/mgmt.h | 2 +
include/net/bluetooth/smp.h | 1 +
net/bluetooth/hci_conn.c | 5 +-
net/bluetooth/hci_core.c | 81 ++++++++++++++
net/bluetooth/hci_event.c | 18 +++-
net/bluetooth/l2cap_core.c | 1 +
net/bluetooth/mgmt.c | 60 ++++++++---
net/bluetooth/smp.c | 214 ++++++++++++++++++++++++++++++++++----
10 files changed, 368 insertions(+), 43 deletions(-)

--
1.7.5.4



2011-06-09 13:09:49

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [bluetooth-next 00/13] SMP Key Exchange Support

Hi Luiz,

On Thu, Jun 9, 2011 at 9:02 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> This patches seems to be working fine, tried with pts and some other
> stacks without problem, the only inconvenients for testing are the
> hardcoded io capabilitity, hardcoded distribution keys (it seems we
> distribute only LTK) and not being able to remove keys other than
> remove the adapter (didn't try reset).

About the "not being able to remove keys" part, there is some proposal
(original code is from Johan) to a "mgmt tool" that could be used to
remove keys. Also note that if the remote reports pairing error due to
"missing key or PIN", the bluez side will forget the keys and issue a
fresh pairing.

Not sure what you meant about "hardcoded distribution keys". IIRC I've
seen at least master and identity information distributed as well (but
Vinicius can definitely confirm or deny that).

HTH,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

2011-06-09 13:02:36

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [bluetooth-next 00/13] SMP Key Exchange Support

Hi Vinicius,

On Wed, Jun 8, 2011 at 7:50 AM, Vinicius Costa Gomes
<[email protected]> wrote:
> Hi,
>
> This will introduce support for Exchanging Keys with remote devices.
>
> The keys will be generated by the kernel and will be notified to
> userspace so they can be stored. The management interface will
> be used for this communication.
>
> The "new key" event and the "load keys" command had to be changed, so
> more information could be added to each key, for example, the long term
> key has a 16bit number and a 64bit random value associated with it. But,
> userpace isn't aware of the format of those keys, it just knows that they
> are present or not.
>
> Another thing that should be noted is that the link_keys list (already
> present) is used to store these keys, including the Short Term Key, as
> it makes the handling of this type of key more transparent.
>
> The related userspace changes should appear a little after this series.
>
>
> Cheers,
> --
>
> Anderson Lizardo (1):
> ?Bluetooth: Add support for random destination address
>
> Vinicius Costa Gomes (12):
> ?Bluetooth: Add support for SMP phase 3 (key distribution)
> ?Bluetooth: Fix sending wrong IO Capabilities value
> ?Bluetooth: Add new structures for supporting SM key distribution
> ?Bluetooth: Add functions to manipulate the link key list for SMP
> ?Bluetooth: Reject an encryption request when the key isn't found
> ?Bluetooth: Add support for providing parameters to LE Start
> ? ?Encryption
> ?Bluetooth: Fix SM pairing parameters negotiation
> ?Bluetooth: Add support for storing the LTK
> ?Bluetooth: Use the link key list to temporarily store the STK
> ?Bluetooth: Use the stored LTK for restabilishing security
> ?Bluetooth: Remove unused field in hci_conn
> ?Bluetooth: Add support for communicating keys with userspace
>
> ?include/net/bluetooth/hci.h ? ? ?| ? ?4 +
> ?include/net/bluetooth/hci_core.h | ? 25 ++++-
> ?include/net/bluetooth/mgmt.h ? ? | ? ?2 +
> ?include/net/bluetooth/smp.h ? ? ?| ? ?1 +
> ?net/bluetooth/hci_conn.c ? ? ? ? | ? ?5 +-
> ?net/bluetooth/hci_core.c ? ? ? ? | ? 81 ++++++++++++++
> ?net/bluetooth/hci_event.c ? ? ? ?| ? 18 +++-
> ?net/bluetooth/l2cap_core.c ? ? ? | ? ?1 +
> ?net/bluetooth/mgmt.c ? ? ? ? ? ? | ? 60 ++++++++---
> ?net/bluetooth/smp.c ? ? ? ? ? ? ?| ?214 ++++++++++++++++++++++++++++++++++----
> ?10 files changed, 368 insertions(+), 43 deletions(-)

This patches seems to be working fine, tried with pts and some other
stacks without problem, the only inconvenients for testing are the
hardcoded io capabilitity, hardcoded distribution keys (it seems we
distribute only LTK) and not being able to remove keys other than
remove the adapter (didn't try reset).

--
Luiz Augusto von Dentz
Computer Engineer

2011-06-08 16:30:35

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [bluetooth-next 02/13] Bluetooth: Fix sending wrong IO Capabilities value

Hi Luiz,

On 17:20 Wed 08 Jun, Luiz Augusto von Dentz wrote:
> Hi Vinicius,
>
> On Wed, Jun 8, 2011 at 7:50 AM, Vinicius Costa Gomes
> <[email protected]> wrote:
> > We should send the IO Capabilities set by userspace, using the
> > management interface, instead of a fixed value.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > ?net/bluetooth/smp.c | ? ?2 +-
> > ?1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> > index c9ae5d4..171a65c 100644
> > --- a/net/bluetooth/smp.c
> > +++ b/net/bluetooth/smp.c
> > @@ -198,7 +198,7 @@ static __u8 seclevel_to_authreq(__u8 level)
> > ?static void build_pairing_cmd(struct l2cap_conn *conn,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct smp_cmd_pairing *cmd, __u8 authreq)
> > ?{
> > - ? ? ? cmd->io_capability = SMP_IO_NO_INPUT_OUTPUT;
> > + ? ? ? cmd->io_capability = conn->hcon->io_capability;
> > ? ? ? ?cmd->oob_flag = SMP_OOB_NOT_PRESENT;
> > ? ? ? ?cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
> > ? ? ? ?cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
> > --
>
> Does this fix something that is not upstream yet? If not then we
> should be fixing it in place whenever possible.

Done. Thanks.

>
> --
> Luiz Augusto von Dentz
> Computer Engineer


Cheers,
--
Vinicius

2011-06-08 08:20:41

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [bluetooth-next 02/13] Bluetooth: Fix sending wrong IO Capabilities value

Hi Vinicius,

On Wed, Jun 8, 2011 at 7:50 AM, Vinicius Costa Gomes
<[email protected]> wrote:
> We should send the IO Capabilities set by userspace, using the
> management interface, instead of a fixed value.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> ?net/bluetooth/smp.c | ? ?2 +-
> ?1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index c9ae5d4..171a65c 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -198,7 +198,7 @@ static __u8 seclevel_to_authreq(__u8 level)
> ?static void build_pairing_cmd(struct l2cap_conn *conn,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct smp_cmd_pairing *cmd, __u8 authreq)
> ?{
> - ? ? ? cmd->io_capability = SMP_IO_NO_INPUT_OUTPUT;
> + ? ? ? cmd->io_capability = conn->hcon->io_capability;
> ? ? ? ?cmd->oob_flag = SMP_OOB_NOT_PRESENT;
> ? ? ? ?cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
> ? ? ? ?cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
> --

Does this fix something that is not upstream yet? If not then we
should be fixing it in place whenever possible.

--
Luiz Augusto von Dentz
Computer Engineer

2011-06-07 22:50:03

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 02/13] Bluetooth: Fix sending wrong IO Capabilities value

We should send the IO Capabilities set by userspace, using the
management interface, instead of a fixed value.

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

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index c9ae5d4..171a65c 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -198,7 +198,7 @@ static __u8 seclevel_to_authreq(__u8 level)
static void build_pairing_cmd(struct l2cap_conn *conn,
struct smp_cmd_pairing *cmd, __u8 authreq)
{
- cmd->io_capability = SMP_IO_NO_INPUT_OUTPUT;
+ cmd->io_capability = conn->hcon->io_capability;
cmd->oob_flag = SMP_OOB_NOT_PRESENT;
cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
--
1.7.5.4


2011-06-07 22:50:14

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 13/13] Bluetooth: Add support for random destination address

From: Anderson Lizardo <[email protected]>

For source address, only public address type is supported for now.

Signed-off-by: Anderson Lizardo <[email protected]>
---
net/bluetooth/smp.c | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b8774a7..9abcc6a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -306,7 +306,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
return SMP_UNSPECIFIED;

ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
- conn->src, 0, conn->dst, res);
+ conn->src, conn->hcon->dst_type, conn->dst, res);
if (ret)
return SMP_UNSPECIFIED;

@@ -342,7 +342,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
return SMP_UNSPECIFIED;

ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
- 0, conn->dst, 0, conn->src, res);
+ conn->hcon->dst_type, conn->dst,
+ 0, conn->src, res);
if (ret)
return SMP_CONFIRM_FAILED;

@@ -369,10 +370,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)

if (conn->hcon->out)
ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
- conn->src, 0, conn->dst, res);
+ conn->src, conn->hcon->dst_type, conn->dst,
+ res);
else
- ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
- conn->dst, 0, conn->src, res);
+ ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
+ conn->hcon->dst_type, conn->dst, 0, conn->src,
+ res);
if (ret)
return SMP_UNSPECIFIED;

--
1.7.5.4


2011-06-07 22:50:13

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 12/13] Bluetooth: Add support for communicating keys with userspace

As the key format has changed to something that has a dynamic size,
the way that keys are received and sent must be changed.

The structure fields order is changed to make the parsing of the
information received from the Management Interface easier.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index fcccf10..f229342 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -908,7 +908,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
struct hci_dev *hdev;
struct mgmt_cp_load_keys *cp;
u16 key_count, expected_len;
- int i;
+ int i, err;

cp = (void *) data;

@@ -918,9 +918,9 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
key_count = get_unaligned_le16(&cp->key_count);

expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
- if (expected_len != len) {
- BT_ERR("load_keys: expected %u bytes, got %u bytes",
- len, expected_len);
+ if (expected_len > len) {
+ BT_ERR("load_keys: expected at least %u bytes, got %u bytes",
+ expected_len, len);
return -EINVAL;
}

@@ -942,17 +942,36 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
else
clear_bit(HCI_DEBUG_KEYS, &hdev->flags);

- for (i = 0; i < key_count; i++) {
- struct mgmt_key_info *key = &cp->keys[i];
+ len -= sizeof(*cp);
+ i = 0;
+
+ while (i < len) {
+ struct mgmt_key_info *key = (void *) cp->keys + i;
+
+ i += sizeof(*key) + key->dlen;
+
+ if (key->type == HCI_LK_SMP_LTK) {
+ struct key_master_id *id = (void *) key->data;
+
+ if (key->dlen != sizeof(struct key_master_id))
+ continue;
+
+ hci_add_ltk(hdev, 0, &key->bdaddr, id->ediv,
+ id->rand, key->val);
+
+ continue;
+ }

hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
key->pin_len);
}

+ err = cmd_complete(sk, index, MGMT_OP_LOAD_KEYS, NULL, 0);
+
hci_dev_unlock(hdev);
hci_dev_put(hdev);

- return 0;
+ return err;
}

static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
@@ -1888,17 +1907,28 @@ int mgmt_connectable(u16 index, u8 connectable)

int mgmt_new_key(u16 index, struct link_key *key, u8 persistent)
{
- struct mgmt_ev_new_key ev;
+ struct mgmt_ev_new_key *ev;
+ int err, total;

- memset(&ev, 0, sizeof(ev));
+ total = sizeof(struct mgmt_ev_new_key) + key->dlen;
+ ev = kzalloc(total, GFP_ATOMIC);
+ if (!ev)
+ return -ENOMEM;
+
+ bacpy(&ev->key.bdaddr, &key->bdaddr);
+ ev->key.type = key->type;
+ memcpy(ev->key.val, key->val, 16);
+ ev->key.pin_len = key->pin_len;
+ ev->key.dlen = key->dlen;
+ ev->store_hint = persistent;
+
+ memcpy(ev->key.data, key->data, key->dlen);

- ev.store_hint = persistent;
- bacpy(&ev.key.bdaddr, &key->bdaddr);
- ev.key.type = key->type;
- memcpy(ev.key.val, key->val, 16);
- ev.key.pin_len = key->pin_len;
+ err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);

- return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
+ kfree(ev);
+
+ return err;
}

int mgmt_connected(u16 index, bdaddr_t *bdaddr)
--
1.7.5.4


2011-06-07 22:50:12

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 11/13] Bluetooth: Remove unused field in hci_conn

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f80ea71..c04e798 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -265,7 +265,6 @@ struct hci_conn {
__u8 power_save;
__u16 disc_timeout;
unsigned long pend;
- __u8 ltk[16];

__u8 remote_cap;
__u8 remote_oob;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index adf625a..b8774a7 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -367,8 +367,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
swap128(skb->data, random);
skb_pull(skb, sizeof(random));

- memset(hcon->ltk, 0, sizeof(hcon->ltk));
-
if (conn->hcon->out)
ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
conn->src, 0, conn->dst, res);
--
1.7.5.4


2011-06-07 22:50:11

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 10/13] Bluetooth: Use the stored LTK for restabilishing security

Now that it's possible that the exchanged key is present in
the link key list, we may be able to estabilish security with
an already existing key, without need to perform any SMP
procedure.

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

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 11f5f4f..adf625a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -474,6 +474,20 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
authreq = seclevel_to_authreq(sec_level);

if (hcon->link_mode & HCI_LM_MASTER) {
+ struct link_key *key;
+
+ key = hci_find_link_key_type(hcon->hdev, conn->dst,
+ HCI_LK_SMP_LTK);
+ if (key) {
+ struct key_master_id *master = (void *) key->data;
+
+ hci_le_start_enc(hcon, master->ediv, master->rand,
+ key->val);
+ goto done;
+ }
+ }
+
+ if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;

build_pairing_cmd(conn, &cp, NULL, authreq);
@@ -490,6 +504,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
}

+done:
hcon->pending_sec_level = sec_level;
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);

--
1.7.5.4


2011-06-07 22:50:10

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 09/13] Bluetooth: Use the link key list to temporarily store the STK

With this we can use only one place to store all keys, without
need to use a field in the connection structure for this
purpose.

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

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index bbc327b..11f5f4f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -388,29 +388,36 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
}

if (conn->hcon->out) {
+ u8 stk[16], rand[8];
__le16 ediv;
- u8 rand[8];
+
+ memset(rand, 0, sizeof(rand));
+ ediv = 0;

smp_s1(tfm, conn->tk, random, conn->prnd, key);
- swap128(key, hcon->ltk);
+ swap128(key, stk);

- memset(hcon->ltk + conn->smp_key_size, 0,
+ memset(stk + conn->smp_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);

+ hci_le_start_enc(hcon, ediv, rand, stk);
+ } else {
+ u8 stk[16], r[16], rand[8];
+ __le16 ediv;
+
memset(rand, 0, sizeof(rand));
ediv = 0;
- hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
- } else {
- u8 r[16];

swap128(conn->prnd, r);
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);

smp_s1(tfm, conn->tk, conn->prnd, random, key);
- swap128(key, hcon->ltk);
+ swap128(key, stk);

- memset(hcon->ltk + conn->smp_key_size, 0,
+ memset(stk + conn->smp_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+
+ hci_add_ltk(conn->hcon->hdev, 0, conn->dst, ediv, rand, stk);
}

return 0;
--
1.7.5.4


2011-06-07 22:50:09

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 08/13] Bluetooth: Add support for storing the LTK

Now when the LTK is received from the remote or generated it is stored,
so it can later be used.

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

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b8f9910..bbc327b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -491,18 +491,23 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)

static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
{
- BT_DBG("conn %p", conn);
- /* FIXME: store the ltk */
+ struct smp_cmd_encrypt_info *rp = (void *) skb->data;
+
+ skb_pull(skb, sizeof(*rp));
+
+ memcpy(conn->tk, rp->ltk, sizeof(conn->tk));
+
return 0;
}

static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1];
- u8 keydist = paircmd->init_key_dist;
+ struct smp_cmd_master_ident *rp = (void *) skb->data;
+
+ skb_pull(skb, sizeof(*rp));

- BT_DBG("keydist 0x%x", keydist);
- /* FIXME: store ediv and rand */
+ hci_add_ltk(conn->hcon->hdev, 1, conn->src, rp->ediv,
+ rp->rand, conn->tk);

smp_distribute_keys(conn, 1);

@@ -621,6 +626,9 @@ 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, ediv,
+ ident.rand, enc.ltk);
+
ident.ediv = cpu_to_le16(ediv);

smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
--
1.7.5.4


2011-06-07 22:50:08

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 07/13] Bluetooth: Fix SM pairing parameters negotiation

Before implementing SM key distribution, the pairing features
exchange must be better negotiated, taking into account some
features of the host and connection requirements.

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

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 01a6038..b8f9910 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -196,14 +196,36 @@ static __u8 seclevel_to_authreq(__u8 level)
}

static void build_pairing_cmd(struct l2cap_conn *conn,
- struct smp_cmd_pairing *cmd, __u8 authreq)
+ struct smp_cmd_pairing *req,
+ struct smp_cmd_pairing *rsp,
+ __u8 authreq)
{
- cmd->io_capability = conn->hcon->io_capability;
- cmd->oob_flag = SMP_OOB_NOT_PRESENT;
- cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
- cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
- cmd->resp_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
- cmd->auth_req = authreq;
+ u8 all_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY |
+ SMP_DIST_SIGN;
+ u8 dist_keys;
+
+ dist_keys = 0;
+ if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
+ dist_keys = SMP_DIST_ENC_KEY;
+ authreq |= SMP_AUTH_BONDING;
+ }
+
+ if (rsp == NULL) {
+ req->io_capability = conn->hcon->io_capability;
+ req->oob_flag = SMP_OOB_NOT_PRESENT;
+ req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+ req->init_key_dist = dist_keys;
+ req->resp_key_dist = all_keys;
+ req->auth_req = authreq;
+ return;
+ }
+
+ rsp->io_capability = conn->hcon->io_capability;
+ rsp->oob_flag = SMP_OOB_NOT_PRESENT;
+ rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+ rsp->init_key_dist = req->init_key_dist & all_keys;
+ rsp->resp_key_dist = req->resp_key_dist & dist_keys;
+ rsp->auth_req = authreq;
}

static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
@@ -232,7 +254,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
return SMP_OOB_NOT_AVAIL;

/* We didn't start the pairing, so no requirements */
- build_pairing_cmd(conn, &rsp, SMP_AUTH_NONE);
+ build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);

key_size = min(req->max_key_size, rsp.max_key_size);
if (check_enc_key_size(conn, key_size))
@@ -408,7 +430,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
skb_pull(skb, sizeof(*rp));

memset(&cp, 0, sizeof(cp));
- build_pairing_cmd(conn, &cp, rp->auth_req);
+ build_pairing_cmd(conn, &cp, NULL, rp->auth_req);

conn->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&conn->preq[1], &cp, sizeof(cp));
@@ -447,7 +469,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;

- build_pairing_cmd(conn, &cp, authreq);
+ build_pairing_cmd(conn, &cp, NULL, authreq);
conn->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&conn->preq[1], &cp, sizeof(cp));

--
1.7.5.4


2011-06-07 22:50:07

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 06/13] Bluetooth: Add support for providing parameters to LE Start Encryption

With LTK support we need to be able to provide LE Start Encryption
with EDIV (Encrypted Diversifier) and Rand (just an 64 bit random
number).

Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci_core.h | 3 ++-
net/bluetooth/hci_conn.c | 5 ++++-
net/bluetooth/smp.c | 7 ++++++-
3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index dbe6321..f80ea71 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -874,7 +874,8 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);

void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier);
-void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+ __u8 ltk[16]);
void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
void hci_le_ltk_neg_reply(struct hci_conn *conn);

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b4754a8..2f5ae53 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -205,7 +205,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
}
EXPORT_SYMBOL(hci_le_conn_update);

-void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16])
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+ __u8 ltk[16])
{
struct hci_dev *hdev = conn->hdev;
struct hci_cp_le_start_enc cp;
@@ -216,6 +217,8 @@ void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16])

cp.handle = cpu_to_le16(conn->handle);
memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+ cp.ediv = ediv;
+ memcpy(cp.rand, rand, sizeof(rand));

hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 171a65c..01a6038 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -366,13 +366,18 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
}

if (conn->hcon->out) {
+ __le16 ediv;
+ u8 rand[8];
+
smp_s1(tfm, conn->tk, random, conn->prnd, key);
swap128(key, hcon->ltk);

memset(hcon->ltk + conn->smp_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);

- hci_le_start_enc(hcon, hcon->ltk);
+ memset(rand, 0, sizeof(rand));
+ ediv = 0;
+ hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
} else {
u8 r[16];

--
1.7.5.4


2011-06-07 22:50:06

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 05/13] Bluetooth: Reject an encryption request when the key isn't found

Now that we have methods to finding keys by its parameters we can
reject an encryption request if the key isn't found.

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

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ac2c5e8..9c7c370 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2793,21 +2793,35 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
{
struct hci_ev_le_ltk_req *ev = (void *) skb->data;
struct hci_cp_le_ltk_reply cp;
+ struct hci_cp_le_ltk_neg_reply neg;
struct hci_conn *conn;
+ struct link_key *ltk;

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

hci_dev_lock(hdev);

conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+ if (conn == NULL)
+ goto not_found;
+
+ ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
+ if (ltk == NULL)
+ goto not_found;

- memset(&cp, 0, sizeof(cp));
+ memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
cp.handle = cpu_to_le16(conn->handle);
- memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));

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

hci_dev_unlock(hdev);
+
+ return;
+
+not_found:
+ neg.handle = ev->handle;
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
+ hci_dev_unlock(hdev);
}

static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
--
1.7.5.4


2011-06-07 22:50:05

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 04/13] Bluetooth: Add functions to manipulate the link key list for SMP

As the LTK (the new type of key being handled now) has more data
associated with it, we need to store this extra data and retrieve
the keys based on that data.

Methods for searching for a key and for adding a new LTK are
introduced here.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 0ba309e..dbe6321 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -548,6 +548,11 @@ 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,
+ __le16 ediv, u8 rand[8], u8 ltk[16]);
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 f62ca19..02cad1f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1059,6 +1059,50 @@ 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 list_head *p;
+
+ list_for_each(p, &hdev->link_keys) {
+ struct link_key *k;
+ struct key_master_id *id;
+
+ k = list_entry(p, struct link_key, list);
+
+ if (k->type != HCI_LK_SMP_LTK)
+ 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 NULL;
+}
+EXPORT_SYMBOL(hci_find_ltk);
+
+struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 type)
+{
+ struct list_head *p;
+
+ list_for_each(p, &hdev->link_keys) {
+ struct link_key *k;
+
+ k = list_entry(p, struct link_key, list);
+
+ if ((k->type == type) && (bacmp(bdaddr, &k->bdaddr) == 0))
+ return k;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(hci_find_link_key_type);
+
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)
{
@@ -1114,6 +1158,43 @@ 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,
+ __le16 ediv, u8 rand[8], u8 ltk[16])
+{
+ struct link_key *key, *old_key;
+ struct key_master_id *id;
+ u8 old_key_type;
+
+ BT_DBG("%s addr %s", hdev->name, batostr(bdaddr));
+
+ old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK);
+ if (old_key) {
+ key = old_key;
+ old_key_type = old_key->type;
+ } else {
+ key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC);
+ if (!key)
+ return -ENOMEM;
+ list_add(&key->list, &hdev->link_keys);
+ old_key_type = 0xff;
+ }
+
+ key->dlen = sizeof(*id);
+
+ bacpy(&key->bdaddr, bdaddr);
+ memcpy(key->val, ltk, sizeof(key->val));
+ key->type = HCI_LK_SMP_LTK;
+
+ id = (void *) &key->data;
+ id->ediv = ediv;
+ memcpy(id->rand, rand, sizeof(id->rand));
+
+ if (new_key)
+ mgmt_new_key(hdev->id, key, old_key_type);
+
+ return 0;
+}
+
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct link_key *key;
--
1.7.5.4


2011-06-07 22:50:04

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 03/13] Bluetooth: Add new structures for supporting SM key distribution

We need these changes because SMP keys may have more information
associated with them, for example, in the LTK case, it has an
encrypted diversifier (ediv) and a random number (rand).

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 65345cd..3b6d057 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -254,6 +254,10 @@ 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

/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 13e5b48..0ba309e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -74,12 +74,28 @@ struct bt_uuid {
u8 svc_hint;
};

+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 {
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4899286..129d4b3 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -101,6 +101,8 @@ struct mgmt_key_info {
u8 type;
u8 val[16];
u8 pin_len;
+ u8 dlen;
+ u8 data[0];
} __packed;

#define MGMT_OP_LOAD_KEYS 0x000D
--
1.7.5.4


2011-06-07 22:50:02

by Vinicius Costa Gomes

[permalink] [raw]
Subject: [bluetooth-next 01/13] Bluetooth: Add support for SMP phase 3 (key distribution)

This adds support for generating and distributing all the keys
specified in the third phase of SMP.

This will make possible to re-establish secure connections, resolve
private addresses and sign commands.

For now, the values generated are random.

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

diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 4fb7d19..46c4576 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -118,5 +118,6 @@ struct smp_cmd_security_req {
/* SMP Commands */
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);

#endif /* __SMP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9db461d..f202fa3 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4193,6 +4193,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
chan->sec_level = hcon->sec_level;
del_timer(&conn->security_timer);
l2cap_chan_ready(sk);
+ smp_distribute_keys(conn, 0);
}

bh_unlock_sock(sk);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 3822159..c9ae5d4 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -201,8 +201,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
cmd->io_capability = SMP_IO_NO_INPUT_OUTPUT;
cmd->oob_flag = SMP_OOB_NOT_PRESENT;
cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
- cmd->init_key_dist = 0x00;
- cmd->resp_key_dist = 0x00;
+ cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
+ cmd->resp_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
cmd->auth_req = authreq;
}

@@ -462,6 +462,26 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
return 0;
}

+static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ BT_DBG("conn %p", conn);
+ /* FIXME: store the ltk */
+ return 0;
+}
+
+static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1];
+ u8 keydist = paircmd->init_key_dist;
+
+ BT_DBG("keydist 0x%x", keydist);
+ /* FIXME: store ediv and rand */
+
+ smp_distribute_keys(conn, 1);
+
+ return 0;
+}
+
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
{
__u8 code = skb->data[0];
@@ -503,10 +523,20 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
break;

case SMP_CMD_ENCRYPT_INFO:
+ reason = smp_cmd_encrypt_info(conn, skb);
+ break;
+
case SMP_CMD_MASTER_IDENT:
+ reason = smp_cmd_master_ident(conn, skb);
+ break;
+
case SMP_CMD_IDENT_INFO:
case SMP_CMD_IDENT_ADDR_INFO:
case SMP_CMD_SIGN_INFO:
+ /* Just ignored */
+ reason = 0;
+ break;
+
default:
BT_DBG("Unknown command code 0x%2.2x", code);

@@ -523,3 +553,83 @@ done:
kfree_skb(skb);
return err;
}
+
+int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
+{
+ struct smp_cmd_pairing *req, *rsp;
+ __u8 *keydist;
+
+ BT_DBG("conn %p force %d", conn, force);
+
+ if (IS_ERR(conn->hcon->hdev->tfm))
+ return PTR_ERR(conn->hcon->hdev->tfm);
+
+ rsp = (void *) &conn->prsp[1];
+
+ /* The responder sends its keys first */
+ if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
+ return 0;
+
+ req = (void *) &conn->preq[1];
+
+ if (conn->hcon->out) {
+ keydist = &rsp->init_key_dist;
+ *keydist &= req->init_key_dist;
+ } else {
+ keydist = &rsp->resp_key_dist;
+ *keydist &= req->resp_key_dist;
+ }
+
+
+ BT_DBG("keydist 0x%x", *keydist);
+
+ if (*keydist & SMP_DIST_ENC_KEY) {
+ struct smp_cmd_encrypt_info enc;
+ struct smp_cmd_master_ident ident;
+ __le16 ediv;
+
+ get_random_bytes(enc.ltk, sizeof(enc.ltk));
+ get_random_bytes(&ediv, sizeof(ediv));
+ get_random_bytes(ident.rand, sizeof(ident.rand));
+
+ smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
+
+ ident.ediv = cpu_to_le16(ediv);
+
+ smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
+
+ *keydist &= ~SMP_DIST_ENC_KEY;
+ }
+
+ if (*keydist & SMP_DIST_ID_KEY) {
+ struct smp_cmd_ident_addr_info addrinfo;
+ struct smp_cmd_ident_info idinfo;
+
+ /* Send a dummy key */
+ get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
+
+ smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
+
+ /* Just public address */
+ memset(&addrinfo, 0, sizeof(addrinfo));
+ bacpy(&addrinfo.bdaddr, conn->src);
+
+ smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
+ &addrinfo);
+
+ *keydist &= ~SMP_DIST_ID_KEY;
+ }
+
+ if (*keydist & SMP_DIST_SIGN) {
+ struct smp_cmd_sign_info sign;
+
+ /* Send a dummy key */
+ get_random_bytes(sign.csrk, sizeof(sign.csrk));
+
+ smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
+
+ *keydist &= ~SMP_DIST_SIGN;
+ }
+
+ return 0;
+}
--
1.7.5.4