* [PATCH 0/8] Bluetooth: SMP Key Exchange
@ 2011-12-07 0:48 Vinicius Costa Gomes
2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes
` (7 more replies)
0 siblings, 8 replies; 18+ messages in thread
From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
This is the newest version of SMP key exchange.
For this to work, this depends on userspace having the address type of an
LE device, so there is a functional dependency on Andre's LE Discovery
series (patches 7/9 and 8/9 from his last series more specifically).
What's new:
- hci_add_ltk() now expects hdev to be locked;
--
Cheers,
Vinicius Costa Gomes (8):
Bluetooth: Add structures for the new LTK exchange messages
Bluetooth: Add a custom type for Short Term Keys
Bluetooth: Rename smp_key_size to enc_key_size
Bluetooth: Change SMP procedures to use the new key structures
Bluetooth: Add new mgmt handlers for Long Term Keys
Bluetooth: Add support for reusing the same hci_conn for LE links
Bluetooth: Disconnect the link if encryption fails
Bluetooth: Only increase the connection sec-level if encryption is
successful
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 34 ++++++------
include/net/bluetooth/mgmt.h | 21 +++++++
include/net/bluetooth/smp.h | 2 +-
net/bluetooth/hci_conn.c | 33 ++++++-----
net/bluetooth/hci_core.c | 107 +++++++++++++++++++++++--------------
net/bluetooth/hci_event.c | 5 ++-
net/bluetooth/l2cap_core.c | 58 ++++++++++++++-------
net/bluetooth/mgmt.c | 77 +++++++++++++++++++++++++++
net/bluetooth/smp.c | 41 +++++++-------
10 files changed, 265 insertions(+), 114 deletions(-)
--
1.7.8
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 15:44 ` Hemant Gupta ` (2 more replies) 2011-12-07 0:48 ` [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys Vinicius Costa Gomes ` (6 subsequent siblings) 7 siblings, 3 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes This defines two in the kernel side of BlueZ two new messages, one event that will inform userspace that a new Long Term Key was exchanged and one that will allow userspace to load LTKs into the kernel. Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 3b68806..0f100fa9 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { bdaddr_t bdaddr; } __packed; +struct mgmt_ltk_info { + bdaddr_t bdaddr; + __u8 pin_len; + __u8 enc_size; + __le16 ediv; + __u8 rand[8]; + __u8 val[16]; +} __packed; + +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 +struct mgmt_cp_load_long_term_keys { + __u16 key_count; + struct mgmt_ltk_info keys[0]; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { struct mgmt_ev_user_passkey_request { bdaddr_t bdaddr; } __packed; + +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 +struct mgmt_ev_new_long_term_key { + __u8 store_hint; + struct mgmt_ltk_info key; +} __packed; -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes @ 2011-12-07 15:44 ` Hemant Gupta 2011-12-12 13:17 ` Vinicius Costa Gomes 2011-12-07 17:39 ` Brian Gix 2011-12-12 15:16 ` Vinicius Costa Gomes 2 siblings, 1 reply; 18+ messages in thread From: Hemant Gupta @ 2011-12-07 15:44 UTC (permalink / raw) To: Vinicius Costa Gomes; +Cc: linux-bluetooth Hi Vinicius, On Wed, Dec 7, 2011 at 6:18 AM, Vinicius Costa Gomes <vinicius.gomes@openbossa.org> wrote: > This defines two in the kernel side of BlueZ two new messages, one > event that will inform userspace that a new Long Term Key was > exchanged and one that will allow userspace to load LTKs into > the kernel. The commit message has some issue, rewording is required. > Acked-by: Marcel Holtmann <marcel@holtmann.org> > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> > --- > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ > 1 files changed, 21 insertions(+), 0 deletions(-) > > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h > index 3b68806..0f100fa9 100644 > --- a/include/net/bluetooth/mgmt.h > +++ b/include/net/bluetooth/mgmt.h > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { > bdaddr_t bdaddr; > } __packed; > > +struct mgmt_ltk_info { > + bdaddr_t bdaddr; > + __u8 pin_len; > + __u8 enc_size; > + __le16 ediv; > + __u8 rand[8]; > + __u8 val[16]; > +} __packed; > + > +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 > +struct mgmt_cp_load_long_term_keys { > + __u16 key_count; > + struct mgmt_ltk_info keys[0]; > +} __packed; > + > #define MGMT_EV_CMD_COMPLETE 0x0001 > struct mgmt_ev_cmd_complete { > __le16 opcode; > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { > struct mgmt_ev_user_passkey_request { > bdaddr_t bdaddr; > } __packed; > + > +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 > +struct mgmt_ev_new_long_term_key { > + __u8 store_hint; > + struct mgmt_ltk_info key; > +} __packed; > -- > 1.7.8 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Best Regards Hemant Gupta ST-Ericsson India ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-07 15:44 ` Hemant Gupta @ 2011-12-12 13:17 ` Vinicius Costa Gomes 2011-12-13 3:28 ` Hemant Gupta 0 siblings, 1 reply; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-12 13:17 UTC (permalink / raw) To: Hemant Gupta; +Cc: linux-bluetooth Hi, On 21:14 Wed 07 Dec, Hemant Gupta wrote: > Hi Vinicius, > > On Wed, Dec 7, 2011 at 6:18 AM, Vinicius Costa Gomes > <vinicius.gomes@openbossa.org> wrote: > > This defines two in the kernel side of BlueZ two new messages, one > > event that will inform userspace that a new Long Term Key was > > exchanged and one that will allow userspace to load LTKs into > > the kernel. > > The commit message has some issue, rewording is required. Could you please be more specific on what needs rewording, I will gladly fix it. > > > Acked-by: Marcel Holtmann <marcel@holtmann.org> > > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> > > --- > > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ > > 1 files changed, 21 insertions(+), 0 deletions(-) > > > > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h > > index 3b68806..0f100fa9 100644 > > --- a/include/net/bluetooth/mgmt.h > > +++ b/include/net/bluetooth/mgmt.h > > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { > > bdaddr_t bdaddr; > > } __packed; > > > > +struct mgmt_ltk_info { > > + bdaddr_t bdaddr; > > + __u8 pin_len; > > + __u8 enc_size; > > + __le16 ediv; > > + __u8 rand[8]; > > + __u8 val[16]; > > +} __packed; > > + > > +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 > > +struct mgmt_cp_load_long_term_keys { > > + __u16 key_count; > > + struct mgmt_ltk_info keys[0]; > > +} __packed; > > + > > #define MGMT_EV_CMD_COMPLETE 0x0001 > > struct mgmt_ev_cmd_complete { > > __le16 opcode; > > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { > > struct mgmt_ev_user_passkey_request { > > bdaddr_t bdaddr; > > } __packed; > > + > > +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 > > +struct mgmt_ev_new_long_term_key { > > + __u8 store_hint; > > + struct mgmt_ltk_info key; > > +} __packed; > > -- > > 1.7.8 > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > -- > Best Regards > Hemant Gupta > ST-Ericsson India Cheers, -- Vinicius ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-12 13:17 ` Vinicius Costa Gomes @ 2011-12-13 3:28 ` Hemant Gupta 0 siblings, 0 replies; 18+ messages in thread From: Hemant Gupta @ 2011-12-13 3:28 UTC (permalink / raw) To: Vinicius Costa Gomes; +Cc: linux-bluetooth Hi Vinicius, On Mon, Dec 12, 2011 at 6:47 PM, Vinicius Costa Gomes <vinicius.gomes@openbossa.org> wrote: > Hi, > > On 21:14 Wed 07 Dec, Hemant Gupta wrote: >> Hi Vinicius, >> >> On Wed, Dec 7, 2011 at 6:18 AM, Vinicius Costa Gomes >> <vinicius.gomes@openbossa.org> wrote: >> > This defines two in the kernel side of BlueZ two new messages, one The above line needs rewording. >> > event that will inform userspace that a new Long Term Key was >> > exchanged and one that will allow userspace to load LTKs into >> > the kernel. >> >> The commit message has some issue, rewording is required. > > Could you please be more specific on what needs rewording, I will gladly > fix it. > >> >> > Acked-by: Marcel Holtmann <marcel@holtmann.org> >> > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> >> > --- >> > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ >> > 1 files changed, 21 insertions(+), 0 deletions(-) >> > >> > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h >> > index 3b68806..0f100fa9 100644 >> > --- a/include/net/bluetooth/mgmt.h >> > +++ b/include/net/bluetooth/mgmt.h >> > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { >> > bdaddr_t bdaddr; >> > } __packed; >> > >> > +struct mgmt_ltk_info { >> > + bdaddr_t bdaddr; >> > + __u8 pin_len; >> > + __u8 enc_size; >> > + __le16 ediv; >> > + __u8 rand[8]; >> > + __u8 val[16]; >> > +} __packed; >> > + >> > +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 >> > +struct mgmt_cp_load_long_term_keys { >> > + __u16 key_count; >> > + struct mgmt_ltk_info keys[0]; >> > +} __packed; >> > + >> > #define MGMT_EV_CMD_COMPLETE 0x0001 >> > struct mgmt_ev_cmd_complete { >> > __le16 opcode; >> > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { >> > struct mgmt_ev_user_passkey_request { >> > bdaddr_t bdaddr; >> > } __packed; >> > + >> > +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 >> > +struct mgmt_ev_new_long_term_key { >> > + __u8 store_hint; >> > + struct mgmt_ltk_info key; >> > +} __packed; >> > -- >> > 1.7.8 >> > >> > -- >> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in >> > the body of a message to majordomo@vger.kernel.org >> > More majordomo info at http://vger.kernel.org/majordomo-info.html >> >> >> >> -- >> Best Regards >> Hemant Gupta >> ST-Ericsson India > > Cheers, > -- > Vinicius -- Best Regards Hemant Gupta ST-Ericsson India ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes 2011-12-07 15:44 ` Hemant Gupta @ 2011-12-07 17:39 ` Brian Gix 2011-12-12 13:07 ` Vinicius Costa Gomes 2011-12-12 15:16 ` Vinicius Costa Gomes 2 siblings, 1 reply; 18+ messages in thread From: Brian Gix @ 2011-12-07 17:39 UTC (permalink / raw) To: Vinicius Costa Gomes; +Cc: linux-bluetooth Hi Vinicius, On 12/6/2011 4:48 PM, Vinicius Costa Gomes wrote: > This defines two in the kernel side of BlueZ two new messages, one > event that will inform userspace that a new Long Term Key was > exchanged and one that will allow userspace to load LTKs into > the kernel. > > Acked-by: Marcel Holtmann<marcel@holtmann.org> > Signed-off-by: Vinicius Costa Gomes<vinicius.gomes@openbossa.org> > --- > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ > 1 files changed, 21 insertions(+), 0 deletions(-) > > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h > index 3b68806..0f100fa9 100644 > --- a/include/net/bluetooth/mgmt.h > +++ b/include/net/bluetooth/mgmt.h > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { > bdaddr_t bdaddr; > } __packed; > > +struct mgmt_ltk_info { > + bdaddr_t bdaddr; > + __u8 pin_len; > + __u8 enc_size; > + __le16 ediv; > + __u8 rand[8]; > + __u8 val[16]; > +} __packed; I think we definitely want to store the auth level (octet) that was used to generate this key and/or the sec_level. Some profiles may require MITM (high sec_level) and from this key definition, there is no way to tell if it is Medium (no MITM) or High. This then needs to be used L2CAP to map the sock options, and potentially trigger a re-bonding. Not that it is likely to happen, since devices are suppose to pair with the Highest security level they have available, but there could be malicious devices which could gain access to "High" security services without performing MITM authentication. Also, I will harp once again that anything with an LE bdaddr should include the Public vs Random flag because the two address types are *not* interchangeable. I would like to see Johan's "mgmt_addr_info" structure used in place of the bdaddr_t here. > + > +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 > +struct mgmt_cp_load_long_term_keys { > + __u16 key_count; > + struct mgmt_ltk_info keys[0]; > +} __packed; > + > #define MGMT_EV_CMD_COMPLETE 0x0001 > struct mgmt_ev_cmd_complete { > __le16 opcode; > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { > struct mgmt_ev_user_passkey_request { > bdaddr_t bdaddr; > } __packed; > + > +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 > +struct mgmt_ev_new_long_term_key { > + __u8 store_hint; > + struct mgmt_ltk_info key; > +} __packed; -- Brian Gix bgix@codeaurora.org Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-07 17:39 ` Brian Gix @ 2011-12-12 13:07 ` Vinicius Costa Gomes 2011-12-12 17:37 ` Brian Gix 0 siblings, 1 reply; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-12 13:07 UTC (permalink / raw) To: Brian Gix; +Cc: linux-bluetooth Hi Brian, On 09:39 Wed 07 Dec, Brian Gix wrote: > Hi Vinicius, > > On 12/6/2011 4:48 PM, Vinicius Costa Gomes wrote: > >This defines two in the kernel side of BlueZ two new messages, one > >event that will inform userspace that a new Long Term Key was > >exchanged and one that will allow userspace to load LTKs into > >the kernel. > > > >Acked-by: Marcel Holtmann<marcel@holtmann.org> > >Signed-off-by: Vinicius Costa Gomes<vinicius.gomes@openbossa.org> > >--- > > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ > > 1 files changed, 21 insertions(+), 0 deletions(-) > > > >diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h > >index 3b68806..0f100fa9 100644 > >--- a/include/net/bluetooth/mgmt.h > >+++ b/include/net/bluetooth/mgmt.h > >@@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { > > bdaddr_t bdaddr; > > } __packed; > > > >+struct mgmt_ltk_info { > >+ bdaddr_t bdaddr; > >+ __u8 pin_len; > >+ __u8 enc_size; > >+ __le16 ediv; > >+ __u8 rand[8]; > >+ __u8 val[16]; > >+} __packed; > > I think we definitely want to store the auth level (octet) that was > used to generate this key and/or the sec_level. Some profiles may > require MITM (high sec_level) and from this key definition, there is > no way to tell if it is Medium (no MITM) or High. > Yeah, I was thinking about infering the security level using the pin_len field, but that assumption breaks once we have OOB. I will add this field. > This then needs to be used L2CAP to map the sock options, and > potentially trigger a re-bonding. Not that it is likely to happen, > since devices are suppose to pair with the Highest security level > they have available, but there could be malicious devices which > could gain access to "High" security services without performing > MITM authentication. > > Also, I will harp once again that anything with an LE bdaddr should > include the Public vs Random flag because the two address types are > *not* interchangeable. I would like to see Johan's "mgmt_addr_info" > structure used in place of the bdaddr_t here. Sounds reasonable. Will change this. > > > >+ > >+#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 > >+struct mgmt_cp_load_long_term_keys { > >+ __u16 key_count; > >+ struct mgmt_ltk_info keys[0]; > >+} __packed; > >+ > > #define MGMT_EV_CMD_COMPLETE 0x0001 > > struct mgmt_ev_cmd_complete { > > __le16 opcode; > >@@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { > > struct mgmt_ev_user_passkey_request { > > bdaddr_t bdaddr; > > } __packed; > >+ > >+#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 > >+struct mgmt_ev_new_long_term_key { > >+ __u8 store_hint; > >+ struct mgmt_ltk_info key; > >+} __packed; > > > -- > Brian Gix > bgix@codeaurora.org > Employee of Qualcomm Innovation Center, Inc. > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum Cheers, -- Vinicius ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-12 13:07 ` Vinicius Costa Gomes @ 2011-12-12 17:37 ` Brian Gix 0 siblings, 0 replies; 18+ messages in thread From: Brian Gix @ 2011-12-12 17:37 UTC (permalink / raw) To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Johan Hedberg Hi Vinicius, Johan, On 12/12/2011 5:07 AM, Vinicius Costa Gomes wrote: > Hi Brian, > > On 09:39 Wed 07 Dec, Brian Gix wrote: >> > Hi Vinicius, >> > >> > On 12/6/2011 4:48 PM, Vinicius Costa Gomes wrote: >>> > >This defines two in the kernel side of BlueZ two new messages, one >>> > >event that will inform userspace that a new Long Term Key was >>> > >exchanged and one that will allow userspace to load LTKs into >>> > >the kernel. >>> > > >>> > >Acked-by: Marcel Holtmann<marcel@holtmann.org> >>> > >Signed-off-by: Vinicius Costa Gomes<vinicius.gomes@openbossa.org> >>> > >--- >>> > > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ >>> > > 1 files changed, 21 insertions(+), 0 deletions(-) >>> > > >>> > >diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h >>> > >index 3b68806..0f100fa9 100644 >>> > >--- a/include/net/bluetooth/mgmt.h >>> > >+++ b/include/net/bluetooth/mgmt.h >>> > >@@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { >>> > > bdaddr_t bdaddr; >>> > > } __packed; >>> > > >>> > >+struct mgmt_ltk_info { >>> > >+ bdaddr_t bdaddr; >>> > >+ __u8 pin_len; >>> > >+ __u8 enc_size; >>> > >+ __le16 ediv; >>> > >+ __u8 rand[8]; >>> > >+ __u8 val[16]; >>> > >+} __packed; >> > >> > I think we definitely want to store the auth level (octet) that was >> > used to generate this key and/or the sec_level. Some profiles may >> > require MITM (high sec_level) and from this key definition, there is >> > no way to tell if it is Medium (no MITM) or High. >> > > Yeah, I was thinking about infering the security level using the pin_len > field, but that assumption breaks once we have OOB. I will add this > field. > Sorry I was not on the IRC when you were discussing the SMP-LTK communication between Kernel and BluZ, but I was copied on the conversation from a colleague. I think everything you guys said was sound. An "authenticated" field that is simply 0 or 1 should be sufficient for preserving the security level that the key represents. Also, I have looked at Hemants patch and it looks correct. It is suitable for either SSP passkey request and entry, or SMP passkey request and entry. It should have no impact on how we handle LTK communication and storage. -- Brian Gix bgix@codeaurora.org Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages 2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes 2011-12-07 15:44 ` Hemant Gupta 2011-12-07 17:39 ` Brian Gix @ 2011-12-12 15:16 ` Vinicius Costa Gomes 2 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-12 15:16 UTC (permalink / raw) To: linux-bluetooth Hi Gustavo, On 21:48 Tue 06 Dec, Vinicius Costa Gomes wrote: > This defines two in the kernel side of BlueZ two new messages, one > event that will inform userspace that a new Long Term Key was > exchanged and one that will allow userspace to load LTKs into > the kernel. > > Acked-by: Marcel Holtmann <marcel@holtmann.org> > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> > --- > include/net/bluetooth/mgmt.h | 21 +++++++++++++++++++++ > 1 files changed, 21 insertions(+), 0 deletions(-) > > diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h > index 3b68806..0f100fa9 100644 > --- a/include/net/bluetooth/mgmt.h > +++ b/include/net/bluetooth/mgmt.h > @@ -264,6 +264,21 @@ struct mgmt_cp_user_passkey_neg_reply { > bdaddr_t bdaddr; > } __packed; > > +struct mgmt_ltk_info { > + bdaddr_t bdaddr; > + __u8 pin_len; > + __u8 enc_size; > + __le16 ediv; > + __u8 rand[8]; > + __u8 val[16]; > +} __packed; As per a discussion on IRC right now, I will change this to include authenticated/unauthenticated information and remove pin_len. Please ignore this series. > + > +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0023 > +struct mgmt_cp_load_long_term_keys { > + __u16 key_count; > + struct mgmt_ltk_info keys[0]; > +} __packed; > + > #define MGMT_EV_CMD_COMPLETE 0x0001 > struct mgmt_ev_cmd_complete { > __le16 opcode; > @@ -363,3 +378,9 @@ struct mgmt_ev_device_unblocked { > struct mgmt_ev_user_passkey_request { > bdaddr_t bdaddr; > } __packed; > + > +#define MGMT_EV_NEW_LONG_TERM_KEY 0x0018 > +struct mgmt_ev_new_long_term_key { > + __u8 store_hint; > + struct mgmt_ltk_info key; > +} __packed; > -- > 1.7.8 > Cheers, -- Vinicius ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 3/8] Bluetooth: Rename smp_key_size to enc_key_size Vinicius Costa Gomes ` (5 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes These keys are just used to encrypt the link, during SMP phase 2, they should not be stored nor reused. We use the same list as the LTKs to temporarily store them, but as soon as they are used they are removed from the list. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/hci.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 67ad984..5eb236e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -268,6 +268,7 @@ enum { #define HCI_LK_AUTH_COMBINATION 0x05 #define HCI_LK_CHANGED_COMBINATION 0x06 /* The spec doesn't define types for SMP keys */ +#define HCI_LK_SMP_STK 0x80 #define HCI_LK_SMP_LTK 0x81 #define HCI_LK_SMP_IRK 0x82 #define HCI_LK_SMP_CSRK 0x83 -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 3/8] Bluetooth: Rename smp_key_size to enc_key_size 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures Vinicius Costa Gomes ` (4 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes This makes clear that this is the size of the key used to encrypt the link. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/smp.h | 2 +- net/bluetooth/smp.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index 15b97d5..2eff4de 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -123,7 +123,7 @@ struct smp_chan { u8 rrnd[16]; /* SMP Pairing Random (remote) */ u8 pcnf[16]; /* SMP Pairing Confirm */ u8 tk[16]; /* SMP Temporary Key */ - u8 smp_key_size; + u8 enc_key_size; struct crypto_blkcipher *tfm; struct work_struct confirm; struct work_struct random; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 0b96737..d943f9f 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -227,7 +227,7 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) (max_key_size < SMP_MIN_ENC_KEY_SIZE)) return SMP_ENC_KEY_SIZE; - smp->smp_key_size = max_key_size; + smp->enc_key_size = max_key_size; return 0; } @@ -332,8 +332,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->pend)) { reason = SMP_UNSPECIFIED; @@ -341,7 +341,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; @@ -355,10 +355,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); } @@ -637,7 +637,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) skb_pull(skb, sizeof(*rp)); - hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size, + hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->enc_key_size, rp->ediv, rp->rand, smp->tk); smp_distribute_keys(conn, 1); @@ -758,7 +758,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 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes ` (2 preceding siblings ...) 2011-12-07 0:48 ` [PATCH 3/8] Bluetooth: Rename smp_key_size to enc_key_size Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 7:49 ` Andrei Emeltchenko 2011-12-07 0:48 ` [PATCH 5/8] Bluetooth: Add new mgmt handlers for Long Term Keys Vinicius Costa Gomes ` (3 subsequent siblings) 7 siblings, 1 reply; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes Using separated messages and list for Long Term Keys allow simplification of the code. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/hci_core.h | 31 +++++------ net/bluetooth/hci_core.c | 105 ++++++++++++++++++++++--------------- net/bluetooth/hci_event.c | 5 ++- net/bluetooth/mgmt.c | 6 ++ net/bluetooth/smp.c | 29 +++++----- 5 files changed, 102 insertions(+), 74 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e34cd71..6939012 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -84,18 +84,15 @@ struct bt_uuid { u8 svc_hint; }; -struct key_master_id { - __le16 ediv; - u8 rand[8]; -} __packed; - -struct link_key_data { +struct smp_ltk { + struct list_head list; bdaddr_t bdaddr; + u8 pin_len; u8 type; + u8 enc_size; + __le16 ediv; + u8 rand[8]; u8 val[16]; - u8 pin_len; - u8 dlen; - u8 data[0]; } __packed; struct link_key { @@ -104,8 +101,6 @@ struct link_key { u8 type; u8 val[16]; u8 pin_len; - u8 dlen; - u8 data[0]; }; struct oob_data { @@ -229,6 +224,8 @@ struct hci_dev { struct list_head link_keys; + struct list_head ltks; + struct list_head remote_oob_data; struct list_head adv_entries; @@ -632,12 +629,14 @@ int hci_link_keys_clear(struct hci_dev *hdev); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); -struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); -struct link_key *hci_find_link_key_type(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 type); -int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]); +int hci_smp_ltks_clear(struct hci_dev *hdev); +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key, + u8 pin_len, u8 tk[16], u8 enc_size, + u16 ediv, u8 rand[8]); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remote_oob_data_clear(struct hci_dev *hdev); struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ce3727e..5b819cd 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1008,6 +1008,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; @@ -1055,41 +1067,38 @@ static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, return 0; } -struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) +/* If the returned key is a STK it should be free'd by the caller */ +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) { - struct link_key *k; - - list_for_each_entry(k, &hdev->link_keys, list) { - struct key_master_id *id; + struct smp_ltk *k, *tmp; - if (k->type != HCI_LK_SMP_LTK) + list_for_each_entry_safe(k, tmp, &hdev->ltks, list) { + if (k->ediv != ediv || + memcmp(rand, k->rand, sizeof(k->rand))) continue; - if (k->dlen != sizeof(*id)) - continue; + /* The STK should only be used once, no need to keep it */ + if (k->type == HCI_LK_SMP_STK) + list_del(&k->list); - id = (void *) &k->data; - if (id->ediv == ediv && - (memcmp(rand, id->rand, sizeof(id->rand)) == 0)) - return k; + return k; } return NULL; } EXPORT_SYMBOL(hci_find_ltk); -struct link_key *hci_find_link_key_type(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 type) +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr) { - struct link_key *k; + struct smp_ltk *k; - list_for_each_entry(k, &hdev->link_keys, list) - if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0) + list_for_each_entry(k, &hdev->ltks, list) + if (bacmp(bdaddr, &k->bdaddr) == 0) return k; return NULL; } -EXPORT_SYMBOL(hci_find_link_key_type); +EXPORT_SYMBOL(hci_find_ltk_addr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) @@ -1146,40 +1155,31 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, return 0; } -int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]) +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key, + u8 pin_len, u8 tk[16], u8 enc_size, + u16 ediv, u8 rand[8]) { - struct link_key *key, *old_key; - struct key_master_id *id; - u8 old_key_type; + struct smp_ltk *key, *old_key; - BT_DBG("%s addr %s", hdev->name, batostr(bdaddr)); + if (type != HCI_LK_SMP_STK && type != HCI_LK_SMP_LTK) + return 0; - old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK); - if (old_key) { + old_key = hci_find_ltk_addr(hdev, bdaddr); + if (old_key) key = old_key; - old_key_type = old_key->type; - } else { - key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC); + else { + key = kzalloc(sizeof(*key), GFP_ATOMIC); if (!key) return -ENOMEM; - list_add(&key->list, &hdev->link_keys); - old_key_type = 0xff; + list_add(&key->list, &hdev->ltks); } - key->dlen = sizeof(*id); - bacpy(&key->bdaddr, bdaddr); - memcpy(key->val, ltk, sizeof(key->val)); - key->type = HCI_LK_SMP_LTK; - key->pin_len = key_size; - - id = (void *) &key->data; - id->ediv = ediv; - memcpy(id->rand, rand, sizeof(id->rand)); - - if (new_key) - mgmt_new_link_key(hdev, key, old_key_type); + memcpy(key->val, tk, sizeof(key->val)); + key->pin_len = pin_len; + key->ediv = ediv; + key->enc_size = enc_size; + memcpy(key->rand, rand, sizeof(key->rand)); return 0; } @@ -1200,6 +1200,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) { @@ -1483,6 +1500,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); @@ -1583,6 +1601,7 @@ void hci_unregister_dev(struct hci_dev *hdev) hci_blacklist_clear(hdev); hci_uuids_clear(hdev); hci_link_keys_clear(hdev); + hci_smp_ltks_clear(hdev); hci_remote_oob_data_clear(hdev); hci_adv_entries_clear(hdev); hci_dev_unlock_bh(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 35cb56e..f2006e9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3012,7 +3012,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)); @@ -3032,6 +3032,9 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); + if (ltk->type == HCI_LK_SMP_STK) + kfree(ltk); + hci_dev_unlock(hdev); return; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7a23f21..49729fa 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1088,6 +1088,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; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index d943f9f..4763719 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -358,8 +358,8 @@ 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, HCI_LK_SMP_STK, 0, + 0, stk, smp->enc_key_size, ediv, rand); } return; @@ -520,12 +520,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) static u8 smp_ltk_encrypt(struct l2cap_conn *conn) { - struct link_key *key; - struct key_master_id *master; + struct smp_ltk *key; struct hci_conn *hcon = conn->hcon; - key = hci_find_link_key_type(hcon->hdev, conn->dst, - HCI_LK_SMP_LTK); + key = hci_find_ltk_addr(hcon->hdev, conn->dst); if (!key) return 0; @@ -533,10 +531,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; @@ -634,13 +630,17 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; + struct hci_dev *hdev = conn->hcon->hdev; skb_pull(skb, sizeof(*rp)); - hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->enc_key_size, - rp->ediv, rp->rand, smp->tk); + hci_dev_lock(hdev); + hci_add_ltk(conn->hcon->hdev, conn->dst, HCI_LK_SMP_LTK, 1, + conn->hcon->pin_length, smp->tk, + smp->enc_key_size, rp->ediv, rp->rand); smp_distribute_keys(conn, 1); + hci_dev_unlock(hdev); return 0; } @@ -758,8 +758,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, smp->enc_key_size, - ediv, ident.rand, enc.ltk); + hci_add_ltk(conn->hcon->hdev, conn->src, HCI_LK_SMP_LTK, 1, + conn->hcon->pin_length, enc.ltk, + smp->enc_key_size, ediv, ident.rand); ident.ediv = cpu_to_le16(ediv); -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures 2011-12-07 0:48 ` [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures Vinicius Costa Gomes @ 2011-12-07 7:49 ` Andrei Emeltchenko 0 siblings, 0 replies; 18+ messages in thread From: Andrei Emeltchenko @ 2011-12-07 7:49 UTC (permalink / raw) To: Vinicius Costa Gomes; +Cc: linux-bluetooth Hi Vinicius, On Tue, Dec 06, 2011 at 09:48:08PM -0300, Vinicius Costa Gomes wrote: > Using separated messages and list for Long Term Keys allow simplification > of the code. > > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> > --- > include/net/bluetooth/hci_core.h | 31 +++++------ > net/bluetooth/hci_core.c | 105 ++++++++++++++++++++++--------------- > net/bluetooth/hci_event.c | 5 ++- > net/bluetooth/mgmt.c | 6 ++ > net/bluetooth/smp.c | 29 +++++----- > 5 files changed, 102 insertions(+), 74 deletions(-) ... > -struct link_key *hci_find_link_key_type(struct hci_dev *hdev, > - bdaddr_t *bdaddr, u8 type) > +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr) > { > - struct link_key *k; > + struct smp_ltk *k; > > - list_for_each_entry(k, &hdev->link_keys, list) > - if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0) > + list_for_each_entry(k, &hdev->ltks, list) > + if (bacmp(bdaddr, &k->bdaddr) == 0) shall we use kernel-style here? (!bacmp()) ... Best regards Andrei Emeltchenko ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 5/8] Bluetooth: Add new mgmt handlers for Long Term Keys 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes ` (3 preceding siblings ...) 2011-12-07 0:48 ` [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 6/8] Bluetooth: Add support for reusing the same hci_conn for LE links Vinicius Costa Gomes ` (2 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes This makes use of the new messages defined to exchange LTKs between the kernel and userspace. Handlers for loading LTKs into the kernel and for informing userspace of a new LTK are defined. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 6 +++ net/bluetooth/mgmt.c | 71 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 0 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 6939012..96407cf 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -953,6 +953,7 @@ int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); +int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5b819cd..8d96125 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1181,6 +1181,12 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key, key->enc_size = enc_size; memcpy(key->rand, rand, sizeof(key->rand)); + if (!new_key) + return 0; + + if (type == HCI_LK_SMP_LTK) + mgmt_new_ltk(hdev, key, 1); + return 0; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 49729fa..f7314d1 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2066,6 +2066,56 @@ done: return err; } +static int load_long_term_keys(struct sock *sk, u16 index, + unsigned char *data, u16 len) +{ + struct hci_dev *hdev; + struct mgmt_cp_load_long_term_keys *cp; + u16 key_count, expected_len; + int i; + + cp = (void *) data; + + if (len < sizeof(*cp)) + return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS, + EINVAL); + + key_count = get_unaligned_le16(&cp->key_count); + + expected_len = sizeof(*cp) + key_count * + sizeof(struct mgmt_ltk_info); + if (expected_len != len) { + BT_ERR("load_keys: expected %u bytes, got %u bytes", + len, expected_len); + return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS, + EINVAL); + } + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS, + ENODEV); + + BT_DBG("hci%u key_count %u", index, key_count); + + hci_dev_lock_bh(hdev); + + hci_smp_ltks_clear(hdev); + + for (i = 0; i < key_count; i++) { + struct mgmt_ltk_info *key = &cp->keys[i]; + + hci_add_ltk(hdev, &key->bdaddr, HCI_LK_SMP_LTK, 0, + key->pin_len, key->val, key->enc_size, + key->ediv, key->rand); + } + + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return 0; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -2198,6 +2248,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) err = set_fast_connectable(sk, index, buf + sizeof(*hdr), len); break; + case MGMT_OP_LOAD_LONG_TERM_KEYS: + err = load_long_term_keys(sk, index, buf + sizeof(*hdr), len); + break; default: BT_DBG("Unknown op %u", opcode); err = cmd_status(sk, index, opcode, @@ -2353,6 +2406,24 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); } +int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) +{ + struct mgmt_ev_new_long_term_key ev; + + memset(&ev, 0, sizeof(ev)); + + ev.store_hint = persistent; + bacpy(&ev.key.bdaddr, &key->bdaddr); + ev.key.pin_len = key->pin_len; + ev.key.enc_size = key->enc_size; + ev.key.ediv = key->ediv; + memcpy(ev.key.rand, key->rand, sizeof(key->rand)); + memcpy(ev.key.val, key->val, sizeof(key->val)); + + return mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, + &ev, sizeof(ev), NULL); +} + int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type) { -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 6/8] Bluetooth: Add support for reusing the same hci_conn for LE links 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes ` (4 preceding siblings ...) 2011-12-07 0:48 ` [PATCH 5/8] Bluetooth: Add new mgmt handlers for Long Term Keys Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 7/8] Bluetooth: Disconnect the link if encryption fails Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 8/8] Bluetooth: Only increase the connection sec-level if encryption is successful Vinicius Costa Gomes 7 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes As most LE devices leave advertising mode when they enter the connected state, we may want to "pass" that connection to other users. The first user will be the pairing procedure, the connection is established without an associated socket, after the pairing is complete, userspace may want to discover via GATT what services the newly bonded device has. If userspace establishes the connection while the timeout still hasn't expired, the connection will be re-used. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- net/bluetooth/hci_conn.c | 33 +++++++++++++++------------ net/bluetooth/l2cap_core.c | 53 +++++++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b328ac6..00b86ac 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -502,26 +502,29 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 BT_DBG("%s dst %s", hdev->name, batostr(dst)); if (type == LE_LINK) { - struct adv_entry *entry; + struct adv_entry *entry = NULL; le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (le) - return ERR_PTR(-EBUSY); - - entry = hci_find_adv_entry(hdev, dst); - if (!entry) - return ERR_PTR(-EHOSTUNREACH); - - le = hci_conn_add(hdev, LE_LINK, dst); - if (!le) - return ERR_PTR(-ENOMEM); - - le->dst_type = entry->bdaddr_type; + if (!le) { + entry = hci_find_adv_entry(hdev, dst); + if (!entry) + return ERR_PTR(-EHOSTUNREACH); + + le = hci_conn_add(hdev, LE_LINK, dst); + if (!le) + return ERR_PTR(-ENOMEM); + + le->dst_type = entry->bdaddr_type; + le->pending_sec_level = sec_level; + le->sec_level = BT_SECURITY_LOW; + le->auth_type = auth_type; + hci_le_connect(le); + } - hci_le_connect(le); + le->pending_sec_level = sec_level; + le->auth_type = auth_type; hci_conn_hold(le); - return le; } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 014fdec..9da7ebf 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -680,10 +680,32 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); } +static void l2cap_chan_ready(struct sock *sk) +{ + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct sock *parent = bt_sk(sk)->parent; + + BT_DBG("sk %p, parent %p", sk, parent); + + chan->conf_state = 0; + __clear_chan_timer(chan); + + l2cap_state_change(chan, BT_CONNECTED); + sk->sk_state_change(sk); + + if (parent) + parent->sk_data_ready(parent, 0); +} + static void l2cap_do_start(struct l2cap_chan *chan) { struct l2cap_conn *conn = chan->conn; + if (conn->hcon->type == LE_LINK) { + l2cap_chan_ready(chan->sk); + return; + } + if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; @@ -934,23 +956,6 @@ clean: bh_unlock_sock(parent); } -static void l2cap_chan_ready(struct sock *sk) -{ - struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct sock *parent = bt_sk(sk)->parent; - - BT_DBG("sk %p, parent %p", sk, parent); - - chan->conf_state = 0; - __clear_chan_timer(chan); - - l2cap_state_change(chan, BT_CONNECTED); - sk->sk_state_change(sk); - - if (parent) - parent->sk_data_ready(parent, 0); -} - static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan *chan; @@ -1194,6 +1199,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan) goto done; } + if (hcon->type == LE_LINK) { + err = 0; + + read_lock(&conn->chan_lock); + if (!list_empty(&conn->chan_l)) { + err = -EBUSY; + hci_conn_put(hcon); + } + read_unlock(&conn->chan_lock); + + if (err) + goto done; + } + /* Update source addr of the socket */ bacpy(src, conn->src); -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 7/8] Bluetooth: Disconnect the link if encryption fails 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes ` (5 preceding siblings ...) 2011-12-07 0:48 ` [PATCH 6/8] Bluetooth: Add support for reusing the same hci_conn for LE links Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 8/8] Bluetooth: Only increase the connection sec-level if encryption is successful Vinicius Costa Gomes 7 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes The most common case of error is that the encryption keys don't agree, so the best solution is to disconnect the link and inform the user that there was a problem during encryption. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- net/bluetooth/l2cap_core.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9da7ebf..15d1a3b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -4532,10 +4532,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) BT_DBG("conn %p", conn); - if (hcon->type == LE_LINK) { + if (hcon->type == LE_LINK && !status) { smp_distribute_keys(conn, 0); del_timer(&conn->security_timer); - } + } else if (hcon->type == LE_LINK) + l2cap_conn_del(hcon, bt_to_errno(status)); read_lock(&conn->chan_lock); -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 8/8] Bluetooth: Only increase the connection sec-level if encryption is successful 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes ` (6 preceding siblings ...) 2011-12-07 0:48 ` [PATCH 7/8] Bluetooth: Disconnect the link if encryption fails Vinicius Costa Gomes @ 2011-12-07 0:48 ` Vinicius Costa Gomes 7 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-12-07 0:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes In some case, mainly with LE connections, it is possible to get at that point with a failed encryption. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/hci_core.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 96407cf..7a7eec5 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -849,7 +849,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, if (conn->sec_level == BT_SECURITY_SDP) conn->sec_level = BT_SECURITY_LOW; - if (conn->pending_sec_level > conn->sec_level) + if (!status && conn->pending_sec_level > conn->sec_level) conn->sec_level = conn->pending_sec_level; hci_proto_encrypt_cfm(conn, status, encrypt); -- 1.7.8 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 0/8] New LTK messages
@ 2011-11-11 1:03 Vinicius Costa Gomes
2011-11-11 1:03 ` [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures Vinicius Costa Gomes
0 siblings, 1 reply; 18+ messages in thread
From: Vinicius Costa Gomes @ 2011-11-11 1:03 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
These are the new version of the messages needed for permanent key
storage (and allows a more permanent pairing).
Changes from the last version:
- new messages strutures;
- support for only the LTK;
- the LTKs are kept on their own list;
The last three patches are improvements needed for proper pairing.
As the mgmt interface in the kernel and in userspace are different,
I wasn't able to test these patches with the latest userspace. To not
pollute the list even more I will send the userspace side of things
(already implemented) as soon as it seems that this the way to go.
Cheers,
--
Vinicius Costa Gomes (8):
Bluetooth: Add structures for the new LTK exchange messages
Bluetooth: Add a custom type for Short Term Keys
Bluetooth: Rename smp_key_size to enc_size
Bluetooth: Change SMP procedures to use the new key structures
Bluetooth: Add new mgmt handlers for Long Term Keys
Bluetooth: Add support for reusing the same hci_conn for LE links
Bluetooth: Disconnect the link if encryption fails
Bluetooth: Only increase the connection sec-level if encryption is
successful
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 34 ++++++------
include/net/bluetooth/mgmt.h | 21 +++++++
include/net/bluetooth/smp.h | 2 +-
net/bluetooth/hci_conn.c | 27 +++++-----
net/bluetooth/hci_core.c | 107 +++++++++++++++++++++++--------------
net/bluetooth/hci_event.c | 5 ++-
net/bluetooth/l2cap_core.c | 58 ++++++++++++++-------
net/bluetooth/mgmt.c | 77 +++++++++++++++++++++++++++
net/bluetooth/smp.c | 44 +++++++++-------
10 files changed, 264 insertions(+), 112 deletions(-)
--
1.7.7
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures 2011-11-11 1:03 [PATCH 0/8] New LTK messages Vinicius Costa Gomes @ 2011-11-11 1:03 ` Vinicius Costa Gomes 0 siblings, 0 replies; 18+ messages in thread From: Vinicius Costa Gomes @ 2011-11-11 1:03 UTC (permalink / raw) To: linux-bluetooth; +Cc: Vinicius Costa Gomes Using separated messages and list for Long Term Keys allow simplification of the code. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> --- include/net/bluetooth/hci_core.h | 31 +++++------ net/bluetooth/hci_core.c | 105 ++++++++++++++++++++++--------------- net/bluetooth/hci_event.c | 5 ++- net/bluetooth/mgmt.c | 6 ++ net/bluetooth/smp.c | 32 +++++++----- 5 files changed, 105 insertions(+), 74 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index a67ff88..ee660ce 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -84,18 +84,15 @@ struct bt_uuid { u8 svc_hint; }; -struct key_master_id { - __le16 ediv; - u8 rand[8]; -} __packed; - -struct link_key_data { +struct smp_ltk { + struct list_head list; bdaddr_t bdaddr; + u8 pin_len; u8 type; + u8 enc_size; + __le16 ediv; + u8 rand[8]; u8 val[16]; - u8 pin_len; - u8 dlen; - u8 data[0]; } __packed; struct link_key { @@ -104,8 +101,6 @@ struct link_key { u8 type; u8 val[16]; u8 pin_len; - u8 dlen; - u8 data[0]; }; struct oob_data { @@ -227,6 +222,8 @@ struct hci_dev { struct list_head link_keys; + struct list_head ltks; + struct list_head remote_oob_data; struct list_head adv_entries; @@ -628,12 +625,14 @@ int hci_link_keys_clear(struct hci_dev *hdev); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); -struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); -struct link_key *hci_find_link_key_type(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 type); -int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]); +int hci_smp_ltks_clear(struct hci_dev *hdev); +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key, + u8 pin_len, u8 tk[16], u8 enc_size, + u16 ediv, u8 rand[8]); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remote_oob_data_clear(struct hci_dev *hdev); struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index fb3feeb..0f3e534 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1017,6 +1017,18 @@ int hci_link_keys_clear(struct hci_dev *hdev) return 0; } +int hci_smp_ltks_clear(struct hci_dev *hdev) +{ + struct smp_ltk *k, *tmp; + + list_for_each_entry_safe(k, tmp, &hdev->ltks, list) { + list_del(&k->list); + kfree(k); + } + + return 0; +} + struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) { struct link_key *k; @@ -1064,41 +1076,38 @@ static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, return 0; } -struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) +/* If the returned key is a STK it should be free'd by the caller */ +struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) { - struct link_key *k; - - list_for_each_entry(k, &hdev->link_keys, list) { - struct key_master_id *id; + struct smp_ltk *k, *tmp; - if (k->type != HCI_LK_SMP_LTK) + list_for_each_entry_safe(k, tmp, &hdev->ltks, list) { + if (k->ediv != ediv || + memcmp(rand, k->rand, sizeof(k->rand))) continue; - if (k->dlen != sizeof(*id)) - continue; + /* The STK should only be used once, no need to keep it */ + if (k->type == HCI_LK_SMP_STK) + list_del(&k->list); - id = (void *) &k->data; - if (id->ediv == ediv && - (memcmp(rand, id->rand, sizeof(id->rand)) == 0)) - return k; + return k; } return NULL; } EXPORT_SYMBOL(hci_find_ltk); -struct link_key *hci_find_link_key_type(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 type) +struct smp_ltk *hci_find_ltk_addr(struct hci_dev *hdev, bdaddr_t *bdaddr) { - struct link_key *k; + struct smp_ltk *k; - list_for_each_entry(k, &hdev->link_keys, list) - if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0) + list_for_each_entry(k, &hdev->ltks, list) + if (bacmp(bdaddr, &k->bdaddr) == 0) return k; return NULL; } -EXPORT_SYMBOL(hci_find_link_key_type); +EXPORT_SYMBOL(hci_find_ltk_addr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) @@ -1155,40 +1164,31 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, return 0; } -int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]) +int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int new_key, + u8 pin_len, u8 tk[16], u8 enc_size, + u16 ediv, u8 rand[8]) { - struct link_key *key, *old_key; - struct key_master_id *id; - u8 old_key_type; + struct smp_ltk *key, *old_key; - BT_DBG("%s addr %s", hdev->name, batostr(bdaddr)); + if (type != HCI_LK_SMP_STK && type != HCI_LK_SMP_LTK) + return 0; - old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK); - if (old_key) { + old_key = hci_find_ltk_addr(hdev, bdaddr); + if (old_key) key = old_key; - old_key_type = old_key->type; - } else { - key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC); + else { + key = kzalloc(sizeof(*key), GFP_ATOMIC); if (!key) return -ENOMEM; - list_add(&key->list, &hdev->link_keys); - old_key_type = 0xff; + list_add(&key->list, &hdev->ltks); } - key->dlen = sizeof(*id); - bacpy(&key->bdaddr, bdaddr); - memcpy(key->val, ltk, sizeof(key->val)); - key->type = HCI_LK_SMP_LTK; - key->pin_len = key_size; - - id = (void *) &key->data; - id->ediv = ediv; - memcpy(id->rand, rand, sizeof(id->rand)); - - if (new_key) - mgmt_new_link_key(hdev, key, old_key_type); + memcpy(key->val, tk, sizeof(key->val)); + key->pin_len = pin_len; + key->ediv = ediv; + key->enc_size = enc_size; + memcpy(key->rand, rand, sizeof(key->rand)); return 0; } @@ -1209,6 +1209,23 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) return 0; } +int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr) +{ + struct smp_ltk *k, *tmp; + + list_for_each_entry_safe(k, tmp, &hdev->ltks, list) { + if (bacmp(bdaddr, &k->bdaddr)) + continue; + + BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); + + list_del(&k->list); + kfree(k); + } + + return 0; +} + /* HCI command timer function */ static void hci_cmd_timer(unsigned long arg) { @@ -1493,6 +1510,7 @@ int hci_register_dev(struct hci_dev *hdev) INIT_LIST_HEAD(&hdev->uuids); INIT_LIST_HEAD(&hdev->link_keys); + INIT_LIST_HEAD(&hdev->ltks); INIT_LIST_HEAD(&hdev->remote_oob_data); @@ -1593,6 +1611,7 @@ void hci_unregister_dev(struct hci_dev *hdev) hci_blacklist_clear(hdev); hci_uuids_clear(hdev); hci_link_keys_clear(hdev); + hci_smp_ltks_clear(hdev); hci_remote_oob_data_clear(hdev); hci_adv_entries_clear(hdev); hci_dev_unlock_bh(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0d55d00..3df4ec7 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2919,7 +2919,7 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, struct hci_cp_le_ltk_reply cp; struct hci_cp_le_ltk_neg_reply neg; struct hci_conn *conn; - struct link_key *ltk; + struct smp_ltk *ltk; BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); @@ -2939,6 +2939,9 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); + if (ltk->type == HCI_LK_SMP_STK) + kfree(ltk); + hci_dev_unlock(hdev); return; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 5562c21..7378d22 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -981,6 +981,12 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data, memset(&rp, 0, sizeof(rp)); bacpy(&rp.bdaddr, &cp->bdaddr); + err = hci_remove_ltk(hdev, &cp->bdaddr); + if (err < 0) { + err = cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, -err); + goto unlock; + } + err = hci_remove_link_key(hdev, &cp->bdaddr); if (err < 0) goto unlock; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index e30bf6a..028de8e 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -347,8 +347,8 @@ static void random_work(struct work_struct *work) memset(stk + smp->enc_size, 0, SMP_MAX_ENC_KEY_SIZE - smp->enc_size); - hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_size, - ediv, rand, stk); + hci_add_ltk(hcon->hdev, conn->dst, HCI_LK_SMP_STK, 0, + 0, stk, smp->enc_size, ediv, rand); } return; @@ -502,12 +502,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) static u8 smp_ltk_encrypt(struct l2cap_conn *conn) { - struct link_key *key; - struct key_master_id *master; + struct smp_ltk *key; struct hci_conn *hcon = conn->hcon; - key = hci_find_link_key_type(hcon->hdev, conn->dst, - HCI_LK_SMP_LTK); + key = hci_find_ltk_addr(hcon->hdev, conn->dst); if (!key) return 0; @@ -515,10 +513,8 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn) &hcon->pend)) return 1; - master = (void *) key->data; - hci_le_start_enc(hcon, master->ediv, master->rand, - key->val); - hcon->enc_key_size = key->pin_len; + hci_le_start_enc(hcon, key->ediv, key->rand, key->val); + hcon->enc_key_size = key->enc_size; return 1; @@ -616,11 +612,15 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; + struct hci_dev *hdev = conn->hcon->hdev; skb_pull(skb, sizeof(*rp)); - hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->enc_size, - rp->ediv, rp->rand, smp->tk); + hci_dev_lock(hdev); + hci_add_ltk(conn->hcon->hdev, conn->dst, HCI_LK_SMP_LTK, 1, + conn->hcon->pin_length, smp->tk, + smp->enc_size, rp->ediv, rp->rand); + hci_dev_unlock(hdev); smp_distribute_keys(conn, 1); @@ -703,6 +703,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) { struct smp_cmd_pairing *req, *rsp; struct smp_chan *smp = conn->smp_chan; + struct hci_dev *hdev = conn->hcon->hdev; __u8 *keydist; BT_DBG("conn %p force %d", conn, force); @@ -740,8 +741,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); - hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_size, - ediv, ident.rand, enc.ltk); + hci_dev_lock(hdev); + hci_add_ltk(conn->hcon->hdev, conn->src, HCI_LK_SMP_LTK, 1, + conn->hcon->pin_length, enc.ltk, + smp->enc_size, ediv, ident.rand); + hci_dev_unlock(hdev); ident.ediv = cpu_to_le16(ediv); -- 1.7.7 ^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2011-12-13 3:28 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-12-07 0:48 [PATCH 0/8] Bluetooth: SMP Key Exchange Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 1/8] Bluetooth: Add structures for the new LTK exchange messages Vinicius Costa Gomes 2011-12-07 15:44 ` Hemant Gupta 2011-12-12 13:17 ` Vinicius Costa Gomes 2011-12-13 3:28 ` Hemant Gupta 2011-12-07 17:39 ` Brian Gix 2011-12-12 13:07 ` Vinicius Costa Gomes 2011-12-12 17:37 ` Brian Gix 2011-12-12 15:16 ` Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 2/8] Bluetooth: Add a custom type for Short Term Keys Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 3/8] Bluetooth: Rename smp_key_size to enc_key_size Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures Vinicius Costa Gomes 2011-12-07 7:49 ` Andrei Emeltchenko 2011-12-07 0:48 ` [PATCH 5/8] Bluetooth: Add new mgmt handlers for Long Term Keys Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 6/8] Bluetooth: Add support for reusing the same hci_conn for LE links Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 7/8] Bluetooth: Disconnect the link if encryption fails Vinicius Costa Gomes 2011-12-07 0:48 ` [PATCH 8/8] Bluetooth: Only increase the connection sec-level if encryption is successful Vinicius Costa Gomes -- strict thread matches above, loose matches on Subject: below -- 2011-11-11 1:03 [PATCH 0/8] New LTK messages Vinicius Costa Gomes 2011-11-11 1:03 ` [PATCH 4/8] Bluetooth: Change SMP procedures to use the new key structures Vinicius Costa Gomes
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).