Hi,
This patch series implement the Just Works SMP procedures for LE links.
These patches can also be reached from here[1].
Cheers,
--
Vinicius
[1] http://git.infradead.org/users/vcgomes/linux-2.6.git (for-next branch)
Anderson Briglia (7):
Bluetooth: Implement the first SMP commands
Bluetooth: Start SMP procedure
Bluetooth: simple SMP pairing negotiation
Bluetooth: LE SMP Cryptoolbox functions
Bluetooth: Add SMP confirmation structs
Bluetooth: Add SMP confirmation checks methods
Bluetooth: Minor fix in SMP methods
Vinicius Costa Gomes (8):
Bluetooth: Add support for using the crypto subsystem
Bluetooth: Add support for LE Start Encryption
Bluetooth: Add support for resuming socket when SMP is finished
Bluetooth: Fix initial security level of LE links
Bluetooth: Update the security level when link is encrypted
Bluetooth: Add support for Pairing features exchange
Bluetooth: Add support for SMP timeout
Bluetooth: Add key size checks for SMP
include/net/bluetooth/hci.h | 34 +++
include/net/bluetooth/hci_core.h | 10 +
include/net/bluetooth/l2cap.h | 9 +
include/net/bluetooth/smp.h | 46 ++++
net/bluetooth/Kconfig | 6 +
net/bluetooth/Makefile | 2 +-
net/bluetooth/hci_conn.c | 47 ++++
net/bluetooth/hci_core.c | 22 ++
net/bluetooth/hci_event.c | 69 +++++
net/bluetooth/l2cap_core.c | 137 ++++++----
net/bluetooth/l2cap_sock.c | 17 ++
net/bluetooth/smp.c | 535 ++++++++++++++++++++++++++++++++++++++
12 files changed, 876 insertions(+), 58 deletions(-)
create mode 100644 net/bluetooth/smp.c
--
1.7.4.1
On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
> Hi Vinicius,
>
> * Vinicius Gomes <[email protected]> [2011-02-27 21:49:39 -0300]:
>
[ ... ]
> >
> > I have a couple of points against it:
> >
> > 1. it's only used for one purpose, it says whether to try or not to
> > allocate the block cypher, which is done during the adapter
> > registration;
> >
> > 2. If the current way is ok, it would mean that I would need to export
> > another method from smp.c, that was something that I tried to
> > minimize;
> >
> > 3. and my weakest argument, seems that there are other similar uses,
> > for example enable_mgmt.
>
> A similar example here is enable_ertm inside l2cap_core.c. It's a L2CAP
> related option and should reside inside L2CAP code.
>
> >
> > But if you think the code will be clearer moving that to smp.c, will
> > be glad to change.
>
> I don't see the point on have it on hci code. SMP and Block cypher has
> not much to do with HCI. I prefer it on smp.c
Fair enough. Will change.
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
Cheers,
--
Vinicius
Hi Vinicius,
* Vinicius Gomes <[email protected]> [2011-02-27 21:49:39 -0300]:
> Hi Gustavo,
>
> On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
> <[email protected]> wrote:
> > Hi Vinicius,
> >
> > * Vinicius Costa Gomes <[email protected]> [2011-02-21 14:23:51 -0300]:
> >
> >> This will allow using the crypto subsystem for encrypting data. As SMP
> >> (Security Manager Protocol) is implemented almost entirely on the host
> >> side and the crypto module already implements the needed methods
> >> (AES-128), it makes sense to use it.
> >>
> >> This patch also adds a new Kconfig option to toggle the SMP support.
> >>
> >> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> >> Signed-off-by: Anderson Briglia <[email protected]>
> >> ---
> >> ?include/net/bluetooth/hci_core.h | ? ?2 ++
> >> ?net/bluetooth/Kconfig ? ? ? ? ? ?| ? ?6 ++++++
> >> ?net/bluetooth/hci_core.c ? ? ? ? | ? 22 ++++++++++++++++++++++
> >> ?net/bluetooth/smp.c ? ? ? ? ? ? ?| ? 17 +++++++++++++++--
> >> ?4 files changed, 45 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> >> index d5d8454..e8dbde8 100644
> >> --- a/include/net/bluetooth/hci_core.h
> >> +++ b/include/net/bluetooth/hci_core.h
> >> @@ -161,6 +161,8 @@ struct hci_dev {
> >>
> >> ? ? ? __u16 ? ? ? ? ? ? ? ? ? init_last_cmd;
> >>
> >> + ? ? struct crypto_blkcipher *tfm;
> >> +
> >> ? ? ? struct inquiry_cache ? ?inq_cache;
> >> ? ? ? struct hci_conn_hash ? ?conn_hash;
> >> ? ? ? struct list_head ? ? ? ?blacklist;
> >> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
> >> index c6f9c2f..e9f40af 100644
> >> --- a/net/bluetooth/Kconfig
> >> +++ b/net/bluetooth/Kconfig
> >> @@ -22,6 +22,7 @@ menuconfig BT
> >> ? ? ? ? ? ?BNEP Module (Bluetooth Network Encapsulation Protocol)
> >> ? ? ? ? ? ?CMTP Module (CAPI Message Transport Protocol)
> >> ? ? ? ? ? ?HIDP Module (Human Interface Device Protocol)
> >> + ? ? ? ? ?SMP Module (Security Manager Protocol)
> >>
> >> ? ? ? ? Say Y here to compile Bluetooth support into the kernel or say M to
> >> ? ? ? ? compile it as module (bluetooth).
> >> @@ -35,11 +36,16 @@ config BT_L2CAP
> >> ? ? ? bool "L2CAP protocol support"
> >> ? ? ? depends on BT
> >> ? ? ? select CRC16
> >> + ? ? select CRYPTO_BLKCIPHER
> >> + ? ? select CRYPTO_AES
> >> ? ? ? help
> >> ? ? ? ? L2CAP (Logical Link Control and Adaptation Protocol) provides
> >> ? ? ? ? connection oriented and connection-less data transport. ?L2CAP
> >> ? ? ? ? support is required for most Bluetooth applications.
> >>
> >> + ? ? ? Also included is support for SMP (Security Manager Protocol) which
> >> + ? ? ? is the security layer on top of LE (Low Energy) links.
> >> +
> >> ?config BT_SCO
> >> ? ? ? bool "SCO links support"
> >> ? ? ? depends on BT
> >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> >> index b372fb8..ff67843 100644
> >> --- a/net/bluetooth/hci_core.c
> >> +++ b/net/bluetooth/hci_core.c
> >> @@ -42,6 +42,7 @@
> >> ?#include <linux/notifier.h>
> >> ?#include <linux/rfkill.h>
> >> ?#include <linux/timer.h>
> >> +#include <linux/crypto.h>
> >> ?#include <net/sock.h>
> >>
> >> ?#include <asm/system.h>
> >> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
> >>
> >> ?static DEFINE_RWLOCK(hci_task_lock);
> >>
> >> +static int enable_smp;
> >> +
> >> ?/* HCI device list */
> >> ?LIST_HEAD(hci_dev_list);
> >> ?DEFINE_RWLOCK(hci_dev_list_lock);
> >> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
> >> ? ? ? tasklet_schedule(&hdev->cmd_task);
> >> ?}
> >>
> >> +static struct crypto_blkcipher *alloc_cypher(void)
> >> +{
> >> + ? ? if (enable_smp)
> >> + ? ? ? ? ? ? return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> >> +
> >> + ? ? return ERR_PTR(-ENOTSUPP);
> >> +}
> >> +
> >> ?/* Register HCI device */
> >> ?int hci_register_dev(struct hci_dev *hdev)
> >> ?{
> >> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
> >> ? ? ? if (!hdev->workqueue)
> >> ? ? ? ? ? ? ? goto nomem;
> >>
> >> + ? ? hdev->tfm = alloc_cypher();
> >> + ? ? if (IS_ERR(hdev->tfm))
> >> + ? ? ? ? ? ? BT_INFO("Failed to load transform for ecb(aes): %ld",
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PTR_ERR(hdev->tfm));
> >> +
> >> ? ? ? hci_register_sysfs(hdev);
> >>
> >> ? ? ? hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> >> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
> >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !test_bit(HCI_SETUP, &hdev->flags))
> >> ? ? ? ? ? ? ? mgmt_index_removed(hdev->id);
> >>
> >> + ? ? if (!IS_ERR(hdev->tfm))
> >> + ? ? ? ? ? ? crypto_free_blkcipher(hdev->tfm);
> >> +
> >> ? ? ? hci_notify(hdev, HCI_DEV_UNREG);
> >>
> >> ? ? ? if (hdev->rfkill) {
> >> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
> >> ? ? ? ? ? ? ? }
> >> ? ? ? }
> >> ?}
> >> +
> >> +module_param(enable_smp, bool, 0644);
> >> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
> >
> > This all should be obviously inside smp.c
>
> I have a couple of points against it:
>
> 1. it's only used for one purpose, it says whether to try or not to
> allocate the block cypher, which is done during the adapter
> registration;
>
> 2. If the current way is ok, it would mean that I would need to export
> another method from smp.c, that was something that I tried to
> minimize;
>
> 3. and my weakest argument, seems that there are other similar uses,
> for example enable_mgmt.
A similar example here is enable_ertm inside l2cap_core.c. It's a L2CAP
related option and should reside inside L2CAP code.
>
> But if you think the code will be clearer moving that to smp.c, will
> be glad to change.
I don't see the point on have it on hci code. SMP and Block cypher has
not much to do with HCI. I prefer it on smp.c
--
Gustavo F. Padovan
http://profusion.mobi
Hi Gustavo,
On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
<[email protected]> wrote:
> Hi Vinicius,
>
> * Vinicius Costa Gomes <[email protected]> [2011-02-21 14:23:51 -0300]:
>
>> This will allow using the crypto subsystem for encrypting data. As SMP
>> (Security Manager Protocol) is implemented almost entirely on the host
>> side and the crypto module already implements the needed methods
>> (AES-128), it makes sense to use it.
>>
>> This patch also adds a new Kconfig option to toggle the SMP support.
>>
>> Signed-off-by: Vinicius Costa Gomes <[email protected]>
>> Signed-off-by: Anderson Briglia <[email protected]>
>> ---
>> include/net/bluetooth/hci_core.h | 2 ++
>> net/bluetooth/Kconfig | 6 ++++++
>> net/bluetooth/hci_core.c | 22 ++++++++++++++++++++++
>> net/bluetooth/smp.c | 17 +++++++++++++++--
>> 4 files changed, 45 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> index d5d8454..e8dbde8 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -161,6 +161,8 @@ struct hci_dev {
>>
>> __u16 init_last_cmd;
>>
>> + struct crypto_blkcipher *tfm;
>> +
>> struct inquiry_cache inq_cache;
>> struct hci_conn_hash conn_hash;
>> struct list_head blacklist;
>> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
>> index c6f9c2f..e9f40af 100644
>> --- a/net/bluetooth/Kconfig
>> +++ b/net/bluetooth/Kconfig
>> @@ -22,6 +22,7 @@ menuconfig BT
>> BNEP Module (Bluetooth Network Encapsulation Protocol)
>> CMTP Module (CAPI Message Transport Protocol)
>> HIDP Module (Human Interface Device Protocol)
>> + SMP Module (Security Manager Protocol)
>>
>> Say Y here to compile Bluetooth support into the kernel or say M to
>> compile it as module (bluetooth).
>> @@ -35,11 +36,16 @@ config BT_L2CAP
>> bool "L2CAP protocol support"
>> depends on BT
>> select CRC16
>> + select CRYPTO_BLKCIPHER
>> + select CRYPTO_AES
>> help
>> L2CAP (Logical Link Control and Adaptation Protocol) provides
>> connection oriented and connection-less data transport. L2CAP
>> support is required for most Bluetooth applications.
>>
>> + Also included is support for SMP (Security Manager Protocol) which
>> + is the security layer on top of LE (Low Energy) links.
>> +
>> config BT_SCO
>> bool "SCO links support"
>> depends on BT
>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> index b372fb8..ff67843 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -42,6 +42,7 @@
>> #include <linux/notifier.h>
>> #include <linux/rfkill.h>
>> #include <linux/timer.h>
>> +#include <linux/crypto.h>
>> #include <net/sock.h>
>>
>> #include <asm/system.h>
>> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
>>
>> static DEFINE_RWLOCK(hci_task_lock);
>>
>> +static int enable_smp;
>> +
>> /* HCI device list */
>> LIST_HEAD(hci_dev_list);
>> DEFINE_RWLOCK(hci_dev_list_lock);
>> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
>> tasklet_schedule(&hdev->cmd_task);
>> }
>>
>> +static struct crypto_blkcipher *alloc_cypher(void)
>> +{
>> + if (enable_smp)
>> + return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
>> +
>> + return ERR_PTR(-ENOTSUPP);
>> +}
>> +
>> /* Register HCI device */
>> int hci_register_dev(struct hci_dev *hdev)
>> {
>> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
>> if (!hdev->workqueue)
>> goto nomem;
>>
>> + hdev->tfm = alloc_cypher();
>> + if (IS_ERR(hdev->tfm))
>> + BT_INFO("Failed to load transform for ecb(aes): %ld",
>> + PTR_ERR(hdev->tfm));
>> +
>> hci_register_sysfs(hdev);
>>
>> hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
>> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
>> !test_bit(HCI_SETUP, &hdev->flags))
>> mgmt_index_removed(hdev->id);
>>
>> + if (!IS_ERR(hdev->tfm))
>> + crypto_free_blkcipher(hdev->tfm);
>> +
>> hci_notify(hdev, HCI_DEV_UNREG);
>>
>> if (hdev->rfkill) {
>> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
>> }
>> }
>> }
>> +
>> +module_param(enable_smp, bool, 0644);
>> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
>
> This all should be obviously inside smp.c
I have a couple of points against it:
1. it's only used for one purpose, it says whether to try or not to
allocate the block cypher, which is done during the adapter
registration;
2. If the current way is ok, it would mean that I would need to export
another method from smp.c, that was something that I tried to
minimize;
3. and my weakest argument, seems that there are other similar uses,
for example enable_mgmt.
But if you think the code will be clearer moving that to smp.c, will
be glad to change.
>
> Regards,
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
>
Cheers,
--
Vinicius
Hi Vinicius,
* Vinicius Costa Gomes <[email protected]> [2011-02-21 14:23:51 -0300]:
> This will allow using the crypto subsystem for encrypting data. As SMP
> (Security Manager Protocol) is implemented almost entirely on the host
> side and the crypto module already implements the needed methods
> (AES-128), it makes sense to use it.
>
> This patch also adds a new Kconfig option to toggle the SMP support.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> Signed-off-by: Anderson Briglia <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 2 ++
> net/bluetooth/Kconfig | 6 ++++++
> net/bluetooth/hci_core.c | 22 ++++++++++++++++++++++
> net/bluetooth/smp.c | 17 +++++++++++++++--
> 4 files changed, 45 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index d5d8454..e8dbde8 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -161,6 +161,8 @@ struct hci_dev {
>
> __u16 init_last_cmd;
>
> + struct crypto_blkcipher *tfm;
> +
> struct inquiry_cache inq_cache;
> struct hci_conn_hash conn_hash;
> struct list_head blacklist;
> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
> index c6f9c2f..e9f40af 100644
> --- a/net/bluetooth/Kconfig
> +++ b/net/bluetooth/Kconfig
> @@ -22,6 +22,7 @@ menuconfig BT
> BNEP Module (Bluetooth Network Encapsulation Protocol)
> CMTP Module (CAPI Message Transport Protocol)
> HIDP Module (Human Interface Device Protocol)
> + SMP Module (Security Manager Protocol)
>
> Say Y here to compile Bluetooth support into the kernel or say M to
> compile it as module (bluetooth).
> @@ -35,11 +36,16 @@ config BT_L2CAP
> bool "L2CAP protocol support"
> depends on BT
> select CRC16
> + select CRYPTO_BLKCIPHER
> + select CRYPTO_AES
> help
> L2CAP (Logical Link Control and Adaptation Protocol) provides
> connection oriented and connection-less data transport. L2CAP
> support is required for most Bluetooth applications.
>
> + Also included is support for SMP (Security Manager Protocol) which
> + is the security layer on top of LE (Low Energy) links.
> +
> config BT_SCO
> bool "SCO links support"
> depends on BT
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index b372fb8..ff67843 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -42,6 +42,7 @@
> #include <linux/notifier.h>
> #include <linux/rfkill.h>
> #include <linux/timer.h>
> +#include <linux/crypto.h>
> #include <net/sock.h>
>
> #include <asm/system.h>
> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
>
> static DEFINE_RWLOCK(hci_task_lock);
>
> +static int enable_smp;
> +
> /* HCI device list */
> LIST_HEAD(hci_dev_list);
> DEFINE_RWLOCK(hci_dev_list_lock);
> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
> tasklet_schedule(&hdev->cmd_task);
> }
>
> +static struct crypto_blkcipher *alloc_cypher(void)
> +{
> + if (enable_smp)
> + return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> +
> + return ERR_PTR(-ENOTSUPP);
> +}
> +
> /* Register HCI device */
> int hci_register_dev(struct hci_dev *hdev)
> {
> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
> if (!hdev->workqueue)
> goto nomem;
>
> + hdev->tfm = alloc_cypher();
> + if (IS_ERR(hdev->tfm))
> + BT_INFO("Failed to load transform for ecb(aes): %ld",
> + PTR_ERR(hdev->tfm));
> +
> hci_register_sysfs(hdev);
>
> hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
> !test_bit(HCI_SETUP, &hdev->flags))
> mgmt_index_removed(hdev->id);
>
> + if (!IS_ERR(hdev->tfm))
> + crypto_free_blkcipher(hdev->tfm);
> +
> hci_notify(hdev, HCI_DEV_UNREG);
>
> if (hdev->rfkill) {
> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
> }
> }
> }
> +
> +module_param(enable_smp, bool, 0644);
> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
This all should be obviously inside smp.c
Regards,
--
Gustavo F. Padovan
http://profusion.mobi
Hi,
On 09:21 Fri 25 Feb, Brian Gix wrote:
> Hi Gustavo, Vinicius,
>
> I would like to add my support for promoting these LE Security
> Manager patches into the bluetooth-next tip.
>
I would like to add my support as well :-)
On the other hand I did some (minor) improvements on the error handling.
It can be found on my personal repository[1].
As the difference is just a couple of lines, I am not spammig this list again.
> On 2/21/2011 9:23 AM, Vinicius Costa Gomes wrote:
> >Hi,
> >
> >This patch series implement the Just Works SMP procedures for LE links.
> >
> >These patches can also be reached from here[1].
> >
>
[ ... ]
>
> --
> Brian Gix
> [email protected]
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
--
Vinicius
[1] git://git.infradead.org/users/vcgomes/linux-2.6.git for-next
http://git.infradead.org/users/vcgomes/linux-2.6.git (for-next branch)
http://gitorious.org/bluetooth-next/bluetooth-next (mirror)
Hi Gustavo, Vinicius,
I would like to add my support for promoting these LE Security Manager
patches into the bluetooth-next tip.
On 2/21/2011 9:23 AM, Vinicius Costa Gomes wrote:
> Hi,
>
> This patch series implement the Just Works SMP procedures for LE links.
>
> These patches can also be reached from here[1].
>
>
> Cheers,
> --
> Vinicius
>
> [1] http://git.infradead.org/users/vcgomes/linux-2.6.git (for-next branch)
>
> Anderson Briglia (7):
> Bluetooth: Implement the first SMP commands
> Bluetooth: Start SMP procedure
> Bluetooth: simple SMP pairing negotiation
> Bluetooth: LE SMP Cryptoolbox functions
> Bluetooth: Add SMP confirmation structs
> Bluetooth: Add SMP confirmation checks methods
> Bluetooth: Minor fix in SMP methods
>
> Vinicius Costa Gomes (8):
> Bluetooth: Add support for using the crypto subsystem
> Bluetooth: Add support for LE Start Encryption
> Bluetooth: Add support for resuming socket when SMP is finished
> Bluetooth: Fix initial security level of LE links
> Bluetooth: Update the security level when link is encrypted
> Bluetooth: Add support for Pairing features exchange
> Bluetooth: Add support for SMP timeout
> Bluetooth: Add key size checks for SMP
>
> include/net/bluetooth/hci.h | 34 +++
> include/net/bluetooth/hci_core.h | 10 +
> include/net/bluetooth/l2cap.h | 9 +
> include/net/bluetooth/smp.h | 46 ++++
> net/bluetooth/Kconfig | 6 +
> net/bluetooth/Makefile | 2 +-
> net/bluetooth/hci_conn.c | 47 ++++
> net/bluetooth/hci_core.c | 22 ++
> net/bluetooth/hci_event.c | 69 +++++
> net/bluetooth/l2cap_core.c | 137 ++++++----
> net/bluetooth/l2cap_sock.c | 17 ++
> net/bluetooth/smp.c | 535 ++++++++++++++++++++++++++++++++++++++
> 12 files changed, 876 insertions(+), 58 deletions(-)
> create mode 100644 net/bluetooth/smp.c
>
> --
> 1.7.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
This adds support for starting SMP Phase 2 Encryption, when the initial
SMP negotiation is successful. This adds the LE Start Encryption and LE
Long Term Key Request commands and related events.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
Now this should apply cleanly after Johan's patches now in bluetooth-next.
include/net/bluetooth/hci.h | 34 +++++++++++++++++++
include/net/bluetooth/hci_core.h | 5 +++
net/bluetooth/hci_conn.c | 46 ++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 67 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/smp.c | 9 ++++-
5 files changed, 160 insertions(+), 1 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ec6acf2..d851f8b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -699,6 +699,33 @@ struct hci_cp_le_conn_update {
__le16 max_ce_len;
} __packed;
+#define HCI_OP_LE_START_ENC 0x2019
+struct hci_cp_le_start_enc {
+ __le16 handle;
+ __u8 rand[8];
+ __le16 ediv;
+ __u8 ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY 0x201a
+struct hci_cp_le_ltk_reply {
+ __le16 handle;
+ __u8 ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY 0x201b
+struct hci_cp_le_ltk_neg_reply {
+ __le16 handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
@@ -984,6 +1011,13 @@ struct hci_ev_le_conn_complete {
__u8 clk_accurancy;
} __packed;
+#define HCI_EV_LE_LTK_REQ 0x05
+struct hci_ev_le_ltk_req {
+ __le16 handle;
+ __u8 random[8];
+ __le16 ediv;
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cf33856..e049d0e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -226,6 +226,7 @@ struct hci_conn {
__u8 power_save;
__u16 disc_timeout;
unsigned long pend;
+ __u8 ltk[16];
__u8 remote_cap;
__u8 remote_oob;
@@ -802,4 +803,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_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
#endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4504cb6..5f0844d 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -203,6 +203,52 @@ 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])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_start_enc cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_neg_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3fbfa50..8c6cafa 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -819,6 +819,30 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
rp->status);
}
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1186,6 +1210,11 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1761,6 +1790,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_user_confirm_neg_reply(hdev, skb);
break;
+ case HCI_OP_LE_LTK_REPLY:
+ hci_cc_le_ltk_reply(hdev, skb);
+ break;
+
+ case HCI_OP_LE_LTK_NEG_REPLY:
+ hci_cc_le_ltk_neg_reply(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -1839,6 +1876,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_le_create_conn(hdev, ev->status);
break;
+ case HCI_OP_LE_START_ENC:
+ hci_cs_le_start_enc(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -2491,6 +2532,28 @@ unlock:
hci_dev_unlock(hdev);
}
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+ struct hci_cp_le_ltk_reply cp;
+ struct hci_conn *conn;
+
+ 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));
+
+ memset(&cp, 0, sizeof(cp));
+ 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);
+}
+
static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2502,6 +2565,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_conn_complete_evt(hdev, skb);
break;
+ case HCI_EV_LE_LTK_REQ:
+ hci_le_ltk_request_evt(hdev, skb);
+ break;
+
default:
break;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 52241fd..6d32bcc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -280,13 +280,16 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+ struct hci_conn *hcon = conn->hcon;
+ struct crypto_blkcipher *tfm = hcon->hdev->tfm;
int ret;
u8 key[16], res[16], random[16], confirm[16], buf[128];
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);
@@ -311,6 +314,9 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (conn->hcon->out) {
smp_s1(tfm, conn->tk, random, conn->prnd, key);
+ swap128(key, hcon->ltk);
+
+ hci_le_start_enc(hcon, hcon->ltk);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
@@ -321,6 +327,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
smp_s1(tfm, conn->tk, conn->prnd, random, key);
+ swap128(key, hcon->ltk);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
--
1.7.4.1
This patch adds support for disconnecting the link when SMP procedure
takes more than 30 seconds.
SMP begins when either the Pairing Request command is sent or the
Pairing Response is received, and it ends when the link is encrypted
(or terminated). Vol 3, Part H Section 3.4.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/l2cap.h | 2 +
net/bluetooth/l2cap_core.c | 70 ++++++++++++++++++++++++----------------
net/bluetooth/smp.c | 14 ++++++++
3 files changed, 58 insertions(+), 28 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index ed65d65..c2d4ff4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -313,6 +313,8 @@ struct l2cap_conn {
__u8 pcnf[16]; /* SMP Pairing Confirm */
__u8 tk[16]; /* SMP Temporary Key */
+ struct timer_list security_timer;
+
struct l2cap_chan_list chan_list;
};
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 991b349..d781703 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -733,6 +733,36 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
read_unlock(&l->lock);
}
+static void l2cap_conn_del(struct hci_conn *hcon, int err)
+{
+ struct l2cap_conn *conn = hcon->l2cap_data;
+ struct sock *sk;
+
+ if (!conn)
+ return;
+
+ BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
+
+ kfree_skb(conn->rx_skb);
+
+ /* Kill channels */
+ while ((sk = conn->chan_list.head)) {
+ bh_lock_sock(sk);
+ l2cap_chan_del(sk, err);
+ bh_unlock_sock(sk);
+ l2cap_sock_kill(sk);
+ }
+
+ if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
+ del_timer_sync(&conn->info_timer);
+
+ if (hcon->type == LE_LINK)
+ del_timer(&conn->security_timer);
+
+ hcon->l2cap_data = NULL;
+ kfree(conn);
+}
+
static void l2cap_info_timeout(unsigned long arg)
{
struct l2cap_conn *conn = (void *) arg;
@@ -743,6 +773,13 @@ static void l2cap_info_timeout(unsigned long arg)
l2cap_conn_start(conn);
}
+static void security_timeout(unsigned long arg)
+{
+ struct l2cap_conn *conn = (void *) arg;
+
+ l2cap_conn_del(conn->hcon, ETIMEDOUT);
+}
+
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -772,7 +809,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
spin_lock_init(&conn->lock);
rwlock_init(&conn->chan_list.lock);
- if (hcon->type != LE_LINK)
+ if (hcon->type == LE_LINK)
+ setup_timer(&conn->security_timer, security_timeout,
+ (unsigned long) conn);
+ else
setup_timer(&conn->info_timer, l2cap_info_timeout,
(unsigned long) conn);
@@ -781,33 +821,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
return conn;
}
-static void l2cap_conn_del(struct hci_conn *hcon, int err)
-{
- struct l2cap_conn *conn = hcon->l2cap_data;
- struct sock *sk;
-
- if (!conn)
- return;
-
- BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
-
- kfree_skb(conn->rx_skb);
-
- /* Kill channels */
- while ((sk = conn->chan_list.head)) {
- bh_lock_sock(sk);
- l2cap_chan_del(sk, err);
- bh_unlock_sock(sk);
- l2cap_sock_kill(sk);
- }
-
- if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
- del_timer_sync(&conn->info_timer);
-
- hcon->l2cap_data = NULL;
- kfree(conn);
-}
-
static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
{
struct l2cap_chan_list *l = &conn->chan_list;
@@ -3794,6 +3807,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
if (!status && encrypt) {
l2cap_pi(sk)->sec_level = hcon->sec_level;
+ del_timer(&conn->security_timer);
l2cap_chan_ready(sk);
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 496a1ba..33a2932 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -27,6 +27,8 @@
#include <linux/crypto.h>
#include <crypto/b128ops.h>
+#define SMP_TIMEOUT 30000 /* 30 seconds */
+
static inline void swap128(u8 src[16], u8 dst[16])
{
int i;
@@ -232,6 +234,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
return 0;
}
@@ -306,6 +311,9 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
return 0;
}
@@ -384,6 +392,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
return 0;
@@ -417,6 +428,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
conn->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&conn->preq[1], &cp, sizeof(cp));
+ mod_timer(&conn->security_timer, jiffies +
+ msecs_to_jiffies(SMP_TIMEOUT));
+
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
} else {
struct smp_cmd_security_req cp;
--
1.7.4.1
If the pending security level is greater than the current security
level and the link is now encrypted, we should update the link
security level.
This is only useful for LE links, when the only event generated
when SMP is sucessful in the Encrypt Change event.
---
include/net/bluetooth/hci_core.h | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index aeae4b4..c949073 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -679,6 +679,9 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;
+ if (conn->pending_sec_level > conn->sec_level)
+ conn->sec_level = conn->pending_sec_level;
+
hci_proto_encrypt_cfm(conn, status, encrypt);
read_lock_bh(&hci_cb_list_lock);
--
1.7.4.1
From: Anderson Briglia <[email protected]>
Start SMP procedure for LE connections. This modification intercepts
l2cap received frames and call proper SMP functions to start the SMP
procedure. By now, no keys are being used.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
Signed-off-by: Anderson Briglia <[email protected]>
---
net/bluetooth/l2cap_core.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index efcef0d..66988b8 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -54,6 +54,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
int disable_ertm;
@@ -684,6 +685,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
l2cap_sock_clear_timer(sk);
sk->sk_state = BT_CONNECTED;
sk->sk_state_change(sk);
+ if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
+ BT_DBG("Insufficient security");
}
if (sk->sk_type != SOCK_SEQPACKET &&
@@ -3673,6 +3676,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
l2cap_conless_channel(conn, psm, skb);
break;
+ case L2CAP_CID_SMP:
+ if (smp_sig_channel(conn, skb))
+ l2cap_conn_del(conn->hcon, EACCES);
+ break;
+
default:
l2cap_data_channel(conn, cid, skb);
break;
--
1.7.4.1
This adds support for resuming the user space traffic when SMP
negotiation is complete.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/l2cap_core.c | 61 ++++++++++++++++++++++---------------------
net/bluetooth/l2cap_sock.c | 17 ++++++++++++
net/bluetooth/smp.c | 40 ++++++++++++++++++++--------
3 files changed, 76 insertions(+), 42 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 66988b8..991b349 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -666,6 +666,22 @@ clean:
bh_unlock_sock(parent);
}
+static void l2cap_chan_ready(struct sock *sk)
+{
+ struct sock *parent = bt_sk(sk)->parent;
+
+ BT_DBG("sk %p, parent %p", sk, parent);
+
+ l2cap_pi(sk)->conf_state = 0;
+ l2cap_sock_clear_timer(sk);
+
+ sk->sk_state = 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_list *l = &conn->chan_list;
@@ -681,15 +697,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
bh_lock_sock(sk);
- if (conn->hcon->type == LE_LINK) {
- l2cap_sock_clear_timer(sk);
- sk->sk_state = BT_CONNECTED;
- sk->sk_state_change(sk);
+ if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
- BT_DBG("Insufficient security");
- }
+ l2cap_chan_ready(sk);
- if (sk->sk_type != SOCK_SEQPACKET &&
+ } else if (sk->sk_type != SOCK_SEQPACKET &&
sk->sk_type != SOCK_STREAM) {
l2cap_sock_clear_timer(sk);
sk->sk_state = BT_CONNECTED;
@@ -1360,29 +1372,6 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
return size;
}
-static void l2cap_chan_ready(struct sock *sk)
-{
- struct sock *parent = bt_sk(sk)->parent;
-
- BT_DBG("sk %p, parent %p", sk, parent);
-
- l2cap_pi(sk)->conf_state = 0;
- l2cap_sock_clear_timer(sk);
-
- if (!parent) {
- /* Outgoing channel.
- * Wake up socket sleeping on connect.
- */
- sk->sk_state = BT_CONNECTED;
- sk->sk_state_change(sk);
- } else {
- /* Incoming channel.
- * Wake up socket sleeping on accept.
- */
- parent->sk_data_ready(parent, 0);
- }
-}
-
/* Copy frame to all raw sockets on that connection */
static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
{
@@ -3800,6 +3789,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
bh_lock_sock(sk);
+ BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
+
+ if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
+ if (!status && encrypt) {
+ l2cap_pi(sk)->sec_level = hcon->sec_level;
+ l2cap_chan_ready(sk);
+ }
+
+ bh_unlock_sock(sk);
+ continue;
+ }
+
if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
bh_unlock_sock(sk);
continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index fc85e7a..3abf678 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -29,6 +29,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
/* ---- L2CAP timers ---- */
static void l2cap_sock_timeout(unsigned long arg)
@@ -614,6 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
{
struct sock *sk = sock->sk;
struct bt_security sec;
+ struct l2cap_conn *conn;
int len, err = 0;
u32 opt;
@@ -650,6 +652,21 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
l2cap_pi(sk)->sec_level = sec.level;
+
+ conn = l2cap_pi(sk)->conn;
+ if (conn && l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
+ if (!conn->hcon->out) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (!smp_conn_security(conn, sec.level)) {
+ err = -EINVAL;
+ break;
+ }
+
+ sk->sk_state = BT_CONFIG;
+ }
break;
case BT_DEFER_SETUP:
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6d32bcc..1fd338b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -338,9 +338,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_security_req *rp = (void *) skb->data;
struct smp_cmd_pairing cp;
+ struct hci_conn *hcon = conn->hcon;
BT_DBG("conn %p", conn);
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+ return;
+
skb_pull(skb, sizeof(*rp));
memset(&cp, 0, sizeof(cp));
@@ -355,6 +359,20 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(&conn->preq[1], &cp, sizeof(cp));
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+
+ set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+}
+
+static __u8 seclevel_to_authreq(__u8 level)
+{
+ switch (level) {
+ case BT_SECURITY_HIGH:
+ /* For now we don't support bonding */
+ return SMP_AUTH_MITM;
+
+ default:
+ return SMP_AUTH_NONE;
+ }
}
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
@@ -367,21 +385,16 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
if (IS_ERR(hcon->hdev->tfm))
return PTR_ERR(hcon->hdev->tfm);
- switch (sec_level) {
- case BT_SECURITY_MEDIUM:
- /* Encrypted, no MITM protection */
- authreq = HCI_AT_NO_BONDING_MITM;
- break;
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+ return -EINPROGRESS;
- case BT_SECURITY_HIGH:
- /* Bonding, MITM protection */
- authreq = HCI_AT_GENERAL_BONDING_MITM;
- break;
+ if (sec_level == BT_SECURITY_LOW)
+ return 1;
- case BT_SECURITY_LOW:
- default:
+ if (hcon->sec_level > sec_level)
return 1;
- }
+
+ authreq = seclevel_to_authreq(sec_level);
if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;
@@ -402,6 +415,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
}
+ hcon->pending_sec_level = sec_level;
+ set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
return 0;
}
--
1.7.4.1
This patch implements a check in smp cmd pairing request and pairing
response to verify if encryption key maximum size is compatible in both
slave and master when SMP Pairing is requested. Keys are also masked to
the correct negotiated size.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
Signed-off-by: Anderson Briglia <[email protected]>
---
include/net/bluetooth/l2cap.h | 1 +
include/net/bluetooth/smp.h | 3 ++
net/bluetooth/smp.c | 54 +++++++++++++++++++++++++++++++----------
3 files changed, 45 insertions(+), 13 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index c2d4ff4..577948f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -312,6 +312,7 @@ struct l2cap_conn {
__u8 prnd[16]; /* SMP Pairing Random */
__u8 pcnf[16]; /* SMP Pairing Confirm */
__u8 tk[16]; /* SMP Temporary Key */
+ __u8 smp_key_size;
struct timer_list security_timer;
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 111853a..4fb7d19 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -112,6 +112,9 @@ struct smp_cmd_security_req {
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
+#define SMP_MIN_ENC_KEY_SIZE 7
+#define SMP_MAX_ENC_KEY_SIZE 16
+
/* 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);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 33a2932..f94b480 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -204,35 +204,51 @@ static void build_pairing_cmd(struct l2cap_conn *conn, struct smp_cmd_pairing *c
{
cmd->io_capability = SMP_IO_NO_INPUT_OUTPUT;
cmd->oob_flag = SMP_OOB_NOT_PRESENT;
- cmd->max_key_size = 16;
+ cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
cmd->init_key_dist = 0x00;
cmd->resp_key_dist = 0x00;
cmd->auth_req = authreq;
}
+static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
+{
+ if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
+ (max_key_size < SMP_MIN_ENC_KEY_SIZE))
+ return SMP_ENC_KEY_SIZE;
+
+ conn->smp_key_size = max_key_size;
+
+ return 0;
+}
+
static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct smp_cmd_pairing *rp = (void *) skb->data;
+ struct smp_cmd_pairing rsp, *req = (void *) skb->data;
+ u8 key_size;
BT_DBG("conn %p", conn);
conn->preq[0] = SMP_CMD_PAIRING_REQ;
- memcpy(&conn->preq[1], rp, sizeof(*rp));
- skb_pull(skb, sizeof(*rp));
+ memcpy(&conn->preq[1], req, sizeof(*req));
+ skb_pull(skb, sizeof(*req));
- if (rp->oob_flag)
+ if (req->oob_flag)
return SMP_OOB_NOT_AVAIL;
/* We didn't start the pairing, so no requirements */
- build_pairing_cmd(conn, rp, SMP_AUTH_NONE);
+ build_pairing_cmd(conn, &rsp, SMP_AUTH_NONE);
+
+ key_size = min(req->max_key_size, rsp.max_key_size);
+ if (check_enc_key_size(conn, key_size))
+ return SMP_ENC_KEY_SIZE;
/* Just works */
memset(conn->tk, 0, sizeof(conn->tk));
conn->prsp[0] = SMP_CMD_PAIRING_RSP;
- memcpy(&conn->prsp[1], rp, sizeof(*rp));
+ memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
- smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
mod_timer(&conn->security_timer, jiffies +
msecs_to_jiffies(SMP_TIMEOUT));
@@ -242,24 +258,30 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct smp_cmd_pairing *rp = (void *) skb->data;
+ struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
struct smp_cmd_pairing_confirm cp;
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
int ret;
- u8 res[16];
+ u8 res[16], key_size;
BT_DBG("conn %p", conn);
- skb_pull(skb, sizeof(*rp));
+ skb_pull(skb, sizeof(*rsp));
+
+ req = (void *) &conn->preq[1];
- if (rp->oob_flag)
+ key_size = min(req->max_key_size, rsp->max_key_size);
+ if (check_enc_key_size(conn, key_size))
+ return SMP_ENC_KEY_SIZE;
+
+ if (rsp->oob_flag)
return SMP_OOB_NOT_AVAIL;
/* Just works */
memset(conn->tk, 0, sizeof(conn->tk));
conn->prsp[0] = SMP_CMD_PAIRING_RSP;
- memcpy(&conn->prsp[1], rp, sizeof(*rp));
+ memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
ret = smp_rand(conn->prnd);
if (ret)
@@ -351,6 +373,9 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
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);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
@@ -364,6 +389,9 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
smp_s1(tfm, conn->tk, conn->prnd, random, key);
swap128(key, hcon->ltk);
+ memset(hcon->ltk + conn->smp_key_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
}
--
1.7.4.1
This patch implements a simple version of the SMP Pairing Features
exchange procedure (Vol. 3 Part H, Section 2.3.5.1).
For now, everything that would cause a Pairing Method different of
Just Works to be chosen is rejected.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/hci_event.c | 1 +
net/bluetooth/smp.c | 115 ++++++++++++++++++++++++--------------------
2 files changed, 64 insertions(+), 52 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0637755..890177f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1510,6 +1510,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
/* Encryption implies authentication */
conn->link_mode |= HCI_LM_AUTH;
conn->link_mode |= HCI_LM_ENCRYPT;
+ conn->sec_level = conn->pending_sec_level;
} else
conn->link_mode &= ~HCI_LM_ENCRYPT;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 1fd338b..496a1ba 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -186,7 +186,29 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
hci_send_acl(conn->hcon, skb, 0);
}
-static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
+static __u8 seclevel_to_authreq(__u8 level)
+{
+ switch (level) {
+ case BT_SECURITY_HIGH:
+ /* Right now we don't support bonding */
+ return SMP_AUTH_MITM;
+
+ default:
+ return SMP_AUTH_NONE;
+ }
+}
+
+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->oob_flag = SMP_OOB_NOT_PRESENT;
+ cmd->max_key_size = 16;
+ cmd->init_key_dist = 0x00;
+ cmd->resp_key_dist = 0x00;
+ cmd->auth_req = authreq;
+}
+
+static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *rp = (void *) skb->data;
@@ -196,12 +218,11 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(&conn->preq[1], rp, sizeof(*rp));
skb_pull(skb, sizeof(*rp));
- rp->io_capability = 0x00;
- rp->oob_flag = 0x00;
- rp->max_key_size = 16;
- rp->init_key_dist = 0x00;
- rp->resp_key_dist = 0x00;
- rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+ if (rp->oob_flag)
+ return SMP_OOB_NOT_AVAIL;
+
+ /* We didn't start the pairing, so no requirements */
+ build_pairing_cmd(conn, rp, SMP_AUTH_NONE);
/* Just works */
memset(conn->tk, 0, sizeof(conn->tk));
@@ -210,9 +231,11 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(&conn->prsp[1], rp, sizeof(*rp));
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
+
+ return 0;
}
-static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
+static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *rp = (void *) skb->data;
struct smp_cmd_pairing_confirm cp;
@@ -222,28 +245,34 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG("conn %p", conn);
+ skb_pull(skb, sizeof(*rp));
+
+ if (rp->oob_flag)
+ return SMP_OOB_NOT_AVAIL;
+
/* Just works */
memset(conn->tk, 0, sizeof(conn->tk));
conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp));
- skb_pull(skb, sizeof(*rp));
ret = smp_rand(conn->prnd);
if (ret)
- return;
+ return SMP_UNSPECIFIED;
ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
conn->src, 0, conn->dst, res);
if (ret)
- return;
+ return SMP_UNSPECIFIED;
swap128(res, cp.confirm_val);
smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+
+ return 0;
}
-static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
+static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
@@ -265,20 +294,22 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
ret = smp_rand(conn->prnd);
if (ret)
- return;
+ return SMP_UNSPECIFIED;
ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
0, conn->dst, 0, conn->src, res);
if (ret)
- return;
+ return SMP_CONFIRM_FAILED;
swap128(res, cp.confirm_val);
smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}
+
+ return 0;
}
-static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
+static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct hci_conn *hcon = conn->hcon;
struct crypto_blkcipher *tfm = hcon->hdev->tfm;
@@ -297,19 +328,15 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
conn->dst, 0, conn->src, res);
if (ret)
- return;
+ return SMP_UNSPECIFIED;
BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
swap128(res, confirm);
if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
- struct smp_cmd_pairing_fail cp;
-
BT_ERR("Pairing failed (confirmation values mismatch)");
- cp.reason = SMP_CONFIRM_FAILED;
- smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(cp), &cp);
- return;
+ return SMP_CONFIRM_FAILED;
}
if (conn->hcon->out) {
@@ -332,9 +359,11 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
}
+
+ return 0;
}
-static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
+static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_security_req *rp = (void *) skb->data;
struct smp_cmd_pairing cp;
@@ -343,17 +372,12 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG("conn %p", conn);
if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
- return;
+ return 0;
skb_pull(skb, sizeof(*rp));
- memset(&cp, 0, sizeof(cp));
- cp.io_capability = 0x00;
- cp.oob_flag = 0x00;
- cp.max_key_size = 16;
- cp.init_key_dist = 0x00;
- cp.resp_key_dist = 0x00;
- cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+ memset(&cp, 0, sizeof(cp));
+ build_pairing_cmd(conn, &cp, rp->auth_req);
conn->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&conn->preq[1], &cp, sizeof(cp));
@@ -361,18 +385,8 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
-}
-static __u8 seclevel_to_authreq(__u8 level)
-{
- switch (level) {
- case BT_SECURITY_HIGH:
- /* For now we don't support bonding */
- return SMP_AUTH_MITM;
-
- default:
- return SMP_AUTH_NONE;
- }
+ return 0;
}
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
@@ -398,13 +412,8 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;
- cp.io_capability = 0x00;
- cp.oob_flag = 0x00;
- cp.max_key_size = 16;
- cp.init_key_dist = 0x00;
- cp.resp_key_dist = 0x00;
- cp.auth_req = authreq;
+ build_pairing_cmd(conn, &cp, authreq);
conn->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&conn->preq[1], &cp, sizeof(cp));
@@ -437,26 +446,28 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
switch (code) {
case SMP_CMD_PAIRING_REQ:
- smp_cmd_pairing_req(conn, skb);
+ reason = smp_cmd_pairing_req(conn, skb);
break;
case SMP_CMD_PAIRING_FAIL:
+ reason = 0;
+ err = -EPERM;
break;
case SMP_CMD_PAIRING_RSP:
- smp_cmd_pairing_rsp(conn, skb);
+ reason = smp_cmd_pairing_rsp(conn, skb);
break;
case SMP_CMD_SECURITY_REQ:
- smp_cmd_security_req(conn, skb);
+ reason = smp_cmd_security_req(conn, skb);
break;
case SMP_CMD_PAIRING_CONFIRM:
- smp_cmd_pairing_confirm(conn, skb);
+ reason = smp_cmd_pairing_confirm(conn, skb);
break;
case SMP_CMD_PAIRING_RANDOM:
- smp_cmd_pairing_random(conn, skb);
+ reason = smp_cmd_pairing_random(conn, skb);
break;
case SMP_CMD_ENCRYPT_INFO:
--
1.7.4.1
As the default security level (BT_SECURITY_SDP) doesn't make sense for
LE links, initialize LE links with something that makes sense.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/hci_conn.c | 1 +
net/bluetooth/hci_event.c | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index e75b2a6..160c60c 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -53,6 +53,7 @@ static void hci_le_connect(struct hci_conn *conn)
conn->state = BT_CONNECT;
conn->out = 1;
conn->link_mode |= HCI_LM_MASTER;
+ conn->sec_level = BT_SECURITY_LOW;
memset(&cp, 0, sizeof(cp));
cp.scan_interval = cpu_to_le16(0x0004);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 829ba49..0637755 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2461,6 +2461,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
goto unlock;
}
+ conn->sec_level = BT_SECURITY_LOW;
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
--
1.7.4.1
From: Anderson Briglia <[email protected]>
Minor fix in smp_conn_security function.
Signed-off-by: Anderson Briglia <[email protected]>
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/smp.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 37224a7..52241fd 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -352,12 +352,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
{
+ struct hci_conn *hcon = conn->hcon;
__u8 authreq;
- BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
+ BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
- if (IS_ERR(conn->hcon->hdev->tfm))
- return PTR_ERR(conn->hcon->hdev->tfm);
+ if (IS_ERR(hcon->hdev->tfm))
+ return PTR_ERR(hcon->hdev->tfm);
switch (sec_level) {
case BT_SECURITY_MEDIUM:
@@ -375,7 +376,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
return 1;
}
- if (conn->hcon->link_mode & HCI_LM_MASTER) {
+ if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;
cp.io_capability = 0x00;
cp.oob_flag = 0x00;
--
1.7.4.1
This adds support for starting SMP Phase 2 Encryption, when the initial
SMP negotiation is successful. This adds the LE Start Encryption and LE
Long Term Key Request commands and related events.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/hci.h | 34 +++++++++++++++++++
include/net/bluetooth/hci_core.h | 5 +++
net/bluetooth/hci_conn.c | 46 ++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 67 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/smp.c | 9 ++++-
5 files changed, 160 insertions(+), 1 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index a5f8c46..f95b1e6 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -688,6 +688,33 @@ struct hci_cp_le_conn_update {
__le16 max_ce_len;
} __packed;
+#define HCI_OP_LE_START_ENC 0x2019
+struct hci_cp_le_start_enc {
+ __le16 handle;
+ __u8 rand[8];
+ __le16 ediv;
+ __u8 ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY 0x201a
+struct hci_cp_le_ltk_reply {
+ __le16 handle;
+ __u8 ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY 0x201b
+struct hci_cp_le_ltk_neg_reply {
+ __le16 handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
@@ -967,6 +994,13 @@ struct hci_ev_le_conn_complete {
__u8 clk_accurancy;
} __packed;
+#define HCI_EV_LE_LTK_REQ 0x05
+struct hci_ev_le_ltk_req {
+ __le16 handle;
+ __u8 random[8];
+ __le16 ediv;
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e8dbde8..aeae4b4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -226,6 +226,7 @@ struct hci_conn {
__u8 power_save;
__u16 disc_timeout;
unsigned long pend;
+ __u8 ltk[16];
__u8 remote_cap;
__u8 remote_oob;
@@ -781,4 +782,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_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
#endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index a050a69..e75b2a6 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -203,6 +203,52 @@ 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])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_start_enc cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_neg_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 98b5764..829ba49 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -796,6 +796,30 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
}
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1163,6 +1187,11 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1728,6 +1757,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_le_read_buffer_size(hdev, skb);
break;
+ case HCI_OP_LE_LTK_REPLY:
+ hci_cc_le_ltk_reply(hdev, skb);
+ break;
+
+ case HCI_OP_LE_LTK_NEG_REPLY:
+ hci_cc_le_ltk_neg_reply(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -1806,6 +1843,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_le_create_conn(hdev, ev->status);
break;
+ case HCI_OP_LE_START_ENC:
+ hci_cs_le_start_enc(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -2432,6 +2473,28 @@ unlock:
hci_dev_unlock(hdev);
}
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+ struct hci_cp_le_ltk_reply cp;
+ struct hci_conn *conn;
+
+ 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));
+
+ memset(&cp, 0, sizeof(cp));
+ 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);
+}
+
static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2443,6 +2506,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_conn_complete_evt(hdev, skb);
break;
+ case HCI_EV_LE_LTK_REQ:
+ hci_le_ltk_request_evt(hdev, skb);
+ break;
+
default:
break;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 52241fd..6d32bcc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -280,13 +280,16 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+ struct hci_conn *hcon = conn->hcon;
+ struct crypto_blkcipher *tfm = hcon->hdev->tfm;
int ret;
u8 key[16], res[16], random[16], confirm[16], buf[128];
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);
@@ -311,6 +314,9 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (conn->hcon->out) {
smp_s1(tfm, conn->tk, random, conn->prnd, key);
+ swap128(key, hcon->ltk);
+
+ hci_le_start_enc(hcon, hcon->ltk);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
@@ -321,6 +327,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
smp_s1(tfm, conn->tk, conn->prnd, random, key);
+ swap128(key, hcon->ltk);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
--
1.7.4.1
From: Anderson Briglia <[email protected]>
This patch includes support for generating and sending the random value
used to produce the confirmation value.
Signed-off-by: Anderson Briglia <[email protected]>
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/smp.c | 92 ++++++++++++++++++++++++++++++++++------
2 files changed, 79 insertions(+), 14 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 82508ed..ed65d65 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -311,6 +311,7 @@ struct l2cap_conn {
__u8 prsp[7]; /* SMP Pairing Response */
__u8 prnd[16]; /* SMP Pairing Random */
__u8 pcnf[16]; /* SMP Pairing Confirm */
+ __u8 tk[16]; /* SMP Temporary Key */
struct l2cap_chan_list chan_list;
};
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 31ee1c0..37224a7 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -203,6 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
rp->resp_key_dist = 0x00;
rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+ /* Just works */
+ memset(conn->tk, 0, sizeof(conn->tk));
+
conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp));
@@ -213,53 +216,114 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *rp = (void *) skb->data;
struct smp_cmd_pairing_confirm cp;
+ struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+ int ret;
+ u8 res[16];
BT_DBG("conn %p", conn);
- memset(&cp, 0, sizeof(cp));
+ /* Just works */
+ memset(conn->tk, 0, sizeof(conn->tk));
conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp));
skb_pull(skb, sizeof(*rp));
+ ret = smp_rand(conn->prnd);
+ if (ret)
+ return;
+
+ ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
+ conn->src, 0, conn->dst, res);
+ if (ret)
+ return;
+
+ swap128(res, cp.confirm_val);
+
smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}
static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
{
+ struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+
BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
- if (conn->hcon->out) {
- struct smp_cmd_pairing_random random;
+ memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
+ skb_pull(skb, sizeof(conn->pcnf));
- memset(&random, 0, sizeof(random));
+ if (conn->hcon->out) {
+ u8 random[16];
+ swap128(conn->prnd, random);
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
- &random);
+ random);
} else {
- struct smp_cmd_pairing_confirm confirm;
+ struct smp_cmd_pairing_confirm cp;
+ int ret;
+ u8 res[16];
- memset(&confirm, 0, sizeof(confirm));
+ ret = smp_rand(conn->prnd);
+ if (ret)
+ return;
- smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
- &confirm);
+ ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
+ 0, conn->dst, 0, conn->src, res);
+ if (ret)
+ return;
+
+ swap128(res, cp.confirm_val);
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}
}
static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct smp_cmd_pairing_random cp;
+ struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+ int ret;
+ u8 key[16], res[16], random[16], confirm[16], buf[128];
+
+ swap128(skb->data, random);
+ skb_pull(skb, sizeof(random));
+
+ if (conn->hcon->out)
+ ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+ conn->src, 0, conn->dst, res);
+ else
+ ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+ conn->dst, 0, conn->src, res);
+ if (ret)
+ return;
BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
- skb_pull(skb, sizeof(cp));
+ swap128(res, confirm);
+
+ if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
+ struct smp_cmd_pairing_fail cp;
+
+ BT_ERR("Pairing failed (confirmation values mismatch)");
+ cp.reason = SMP_CONFIRM_FAILED;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(cp), &cp);
+ return;
+ }
if (conn->hcon->out) {
- /* FIXME: start encryption */
+ smp_s1(tfm, conn->tk, random, conn->prnd, key);
+
+ hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
+ BT_DBG("key %s", buf);
} else {
- memset(&cp, 0, sizeof(cp));
+ 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);
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
+ hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
+ BT_DBG("key %s", buf);
}
}
--
1.7.4.1
This will allow using the crypto subsystem for encrypting data. As SMP
(Security Manager Protocol) is implemented almost entirely on the host
side and the crypto module already implements the needed methods
(AES-128), it makes sense to use it.
This patch also adds a new Kconfig option to toggle the SMP support.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
Signed-off-by: Anderson Briglia <[email protected]>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/Kconfig | 6 ++++++
net/bluetooth/hci_core.c | 22 ++++++++++++++++++++++
net/bluetooth/smp.c | 17 +++++++++++++++--
4 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d5d8454..e8dbde8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -161,6 +161,8 @@ struct hci_dev {
__u16 init_last_cmd;
+ struct crypto_blkcipher *tfm;
+
struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
struct list_head blacklist;
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index c6f9c2f..e9f40af 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -22,6 +22,7 @@ menuconfig BT
BNEP Module (Bluetooth Network Encapsulation Protocol)
CMTP Module (CAPI Message Transport Protocol)
HIDP Module (Human Interface Device Protocol)
+ SMP Module (Security Manager Protocol)
Say Y here to compile Bluetooth support into the kernel or say M to
compile it as module (bluetooth).
@@ -35,11 +36,16 @@ config BT_L2CAP
bool "L2CAP protocol support"
depends on BT
select CRC16
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_AES
help
L2CAP (Logical Link Control and Adaptation Protocol) provides
connection oriented and connection-less data transport. L2CAP
support is required for most Bluetooth applications.
+ Also included is support for SMP (Security Manager Protocol) which
+ is the security layer on top of LE (Low Energy) links.
+
config BT_SCO
bool "SCO links support"
depends on BT
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b372fb8..ff67843 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -42,6 +42,7 @@
#include <linux/notifier.h>
#include <linux/rfkill.h>
#include <linux/timer.h>
+#include <linux/crypto.h>
#include <net/sock.h>
#include <asm/system.h>
@@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
static DEFINE_RWLOCK(hci_task_lock);
+static int enable_smp;
+
/* HCI device list */
LIST_HEAD(hci_dev_list);
DEFINE_RWLOCK(hci_dev_list_lock);
@@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
tasklet_schedule(&hdev->cmd_task);
}
+static struct crypto_blkcipher *alloc_cypher(void)
+{
+ if (enable_smp)
+ return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+
+ return ERR_PTR(-ENOTSUPP);
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
if (!hdev->workqueue)
goto nomem;
+ hdev->tfm = alloc_cypher();
+ if (IS_ERR(hdev->tfm))
+ BT_INFO("Failed to load transform for ecb(aes): %ld",
+ PTR_ERR(hdev->tfm));
+
hci_register_sysfs(hdev);
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
!test_bit(HCI_SETUP, &hdev->flags))
mgmt_index_removed(hdev->id);
+ if (!IS_ERR(hdev->tfm))
+ crypto_free_blkcipher(hdev->tfm);
+
hci_notify(hdev, HCI_DEV_UNREG);
if (hdev->rfkill) {
@@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
}
}
}
+
+module_param(enable_smp, bool, 0644);
+MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 0d04c7a..7f275bf 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -157,6 +157,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
+ if (IS_ERR(conn->hcon->hdev->tfm))
+ return PTR_ERR(conn->hcon->hdev->tfm);
+
switch (sec_level) {
case BT_SECURITY_MEDIUM:
/* Encrypted, no MITM protection */
@@ -197,6 +200,12 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
__u8 reason;
int err = 0;
+ if (IS_ERR(conn->hcon->hdev->tfm)) {
+ err = PTR_ERR(conn->hcon->hdev->tfm);
+ reason = SMP_PAIRING_NOTSUPP;
+ goto done;
+ }
+
skb_pull(skb, sizeof(code));
switch (code) {
@@ -232,11 +241,15 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG("Unknown command code 0x%2.2x", code);
reason = SMP_CMD_NOTSUPP;
- smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
- &reason);
err = -EOPNOTSUPP;
+ goto done;
}
+done:
+ if (reason)
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+ &reason);
+
kfree_skb(skb);
return err;
}
--
1.7.4.1
From: Anderson Briglia <[email protected]>
This patch adds initial support for verifying the confirmation value
that the remote side has sent.
Signed-off-by: Anderson Briglia <[email protected]>
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/l2cap.h | 5 +++++
net/bluetooth/smp.c | 17 +++++++++++++++++
2 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 4f4bff1..82508ed 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -307,6 +307,11 @@ struct l2cap_conn {
__u8 disc_reason;
+ __u8 preq[7]; /* SMP Pairing Request */
+ __u8 prsp[7]; /* SMP Pairing Response */
+ __u8 prnd[16]; /* SMP Pairing Random */
+ __u8 pcnf[16]; /* SMP Pairing Confirm */
+
struct l2cap_chan_list chan_list;
};
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 740f579..31ee1c0 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -192,6 +192,8 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG("conn %p", conn);
+ conn->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&conn->preq[1], rp, sizeof(*rp));
skb_pull(skb, sizeof(*rp));
rp->io_capability = 0x00;
@@ -201,17 +203,25 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
rp->resp_key_dist = 0x00;
rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+ conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&conn->prsp[1], rp, sizeof(*rp));
+
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
}
static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
+ struct smp_cmd_pairing *rp = (void *) skb->data;
struct smp_cmd_pairing_confirm cp;
BT_DBG("conn %p", conn);
memset(&cp, 0, sizeof(cp));
+ conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&conn->prsp[1], rp, sizeof(*rp));
+ skb_pull(skb, sizeof(*rp));
+
smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}
@@ -270,6 +280,9 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
cp.resp_key_dist = 0x00;
cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+ conn->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&conn->preq[1], &cp, sizeof(cp));
+
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
}
@@ -306,6 +319,10 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
cp.init_key_dist = 0x00;
cp.resp_key_dist = 0x00;
cp.auth_req = authreq;
+
+ conn->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&conn->preq[1], &cp, sizeof(cp));
+
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
} else {
struct smp_cmd_security_req cp;
--
1.7.4.1
From: Anderson Briglia <[email protected]>
This patch implements SMP crypto functions called ah, c1, s1 and e.
It also implements auxiliary functions. All These functions are needed
for SMP keys generation.
Signed-off-by: Anderson Briglia <[email protected]>
Signed-off-by: Anderson Lizardo <[email protected]>
Signed-off-by: Bruna Moreira <[email protected]>
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
net/bluetooth/smp.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 122 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 7f275bf..740f579 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -24,6 +24,128 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/smp.h>
+#include <linux/crypto.h>
+#include <crypto/b128ops.h>
+
+static inline void swap128(u8 src[16], u8 dst[16])
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ dst[15 - i] = src[i];
+}
+
+static inline void swap56(u8 src[7], u8 dst[7])
+{
+ int i;
+ for (i = 0; i < 7; i++)
+ dst[6 - i] = src[i];
+}
+
+static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
+{
+ struct blkcipher_desc desc;
+ struct scatterlist sg;
+ int err, iv_len;
+ unsigned char iv[128];
+
+ if (tfm == NULL) {
+ BT_ERR("tfm %p", tfm);
+ return -EINVAL;
+ }
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+
+ err = crypto_blkcipher_setkey(tfm, k, 16);
+ if (err) {
+ BT_ERR("cipher setkey failed: %d", err);
+ return err;
+ }
+
+ sg_init_one(&sg, r, 16);
+
+ iv_len = crypto_blkcipher_ivsize(tfm);
+ if (iv_len) {
+ memset(&iv, 0xff, iv_len);
+ crypto_blkcipher_set_iv(tfm, iv, iv_len);
+ }
+
+ err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
+ if (err)
+ BT_ERR("Encrypt data error %d", err);
+
+ return err;
+}
+
+static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
+ u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
+ u8 _rat, bdaddr_t *ra, u8 res[16])
+{
+ u8 p1[16], p2[16], pair[7];
+ bdaddr_t addr;
+ int err;
+
+ /* p1 = pres || preq || _rat || _iat */
+ memset(p1, 0, 16);
+ swap56(pres, pair);
+
+ memcpy(p1, pair, 7);
+ swap56(preq, pair);
+
+ memcpy(p1 + 7, pair, 7);
+ *(p1 + 14) = _rat;
+ *(p1 + 15) = _iat;
+
+ /* p2 = padding || ia || ra */
+ memset(p2, 0, 16);
+ baswap(&addr, ia);
+ memcpy(p2 + 4, &addr, 6);
+ baswap(&addr, ra);
+ memcpy(p2 + 10, &addr, 6);
+
+ /* res = r XOR p1 */
+ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+ /* res = e(k, res) */
+ err = smp_e(tfm, k, res);
+ if (err) {
+ BT_ERR("Encrypt data error");
+ return err;
+ }
+
+ /* res = res XOR p2 */
+ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+ /* res = e(k, res) */
+ err = smp_e(tfm, k, res);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
+ u8 r1[16], u8 r2[16], u8 _r[16])
+{
+ int err;
+
+ /* Just least significant octets from r1 and r2 are considered */
+ memcpy(_r, r1 + 8, 8);
+ memcpy(_r + 8, r2 + 8, 8);
+
+ err = smp_e(tfm, k, _r);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
+static int smp_rand(u8 *buf)
+{
+ get_random_bytes(buf, 16);
+
+ return 0;
+}
static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
u16 dlen, void *data)
--
1.7.4.1
From: Anderson Briglia <[email protected]>
This implementation only exchanges SMP messages between the Host and the
Remote. No keys are being generated. TK and STK generation will be
provided in further patches.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
---
include/net/bluetooth/smp.h | 17 +++++++
net/bluetooth/smp.c | 106 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 36bdd6e..111853a 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -38,6 +38,23 @@ struct smp_cmd_pairing {
__u8 resp_key_dist;
} __packed;
+#define SMP_IO_DISPLAY_ONLY 0x00
+#define SMP_IO_DISPLAY_YESNO 0x01
+#define SMP_IO_KEYBOARD_ONLY 0x02
+#define SMP_IO_NO_INPUT_OUTPUT 0x03
+#define SMP_IO_KEYBOARD_DISPLAY 0x04
+
+#define SMP_OOB_NOT_PRESENT 0x00
+#define SMP_OOB_PRESENT 0x01
+
+#define SMP_DIST_ENC_KEY 0x01
+#define SMP_DIST_ID_KEY 0x02
+#define SMP_DIST_SIGN 0x04
+
+#define SMP_AUTH_NONE 0x00
+#define SMP_AUTH_BONDING 0x01
+#define SMP_AUTH_MITM 0x04
+
#define SMP_CMD_PAIRING_CONFIRM 0x03
struct smp_cmd_pairing_confirm {
__u8 confirm_val[16];
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 8b67a56..0d04c7a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -64,6 +64,93 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
hci_send_acl(conn->hcon, skb, 0);
}
+static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_pairing *rp = (void *) skb->data;
+
+ BT_DBG("conn %p", conn);
+
+ skb_pull(skb, sizeof(*rp));
+
+ rp->io_capability = 0x00;
+ rp->oob_flag = 0x00;
+ rp->max_key_size = 16;
+ rp->init_key_dist = 0x00;
+ rp->resp_key_dist = 0x00;
+ rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
+}
+
+static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_pairing_confirm cp;
+
+ BT_DBG("conn %p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+}
+
+static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+ if (conn->hcon->out) {
+ struct smp_cmd_pairing_random random;
+
+ memset(&random, 0, sizeof(random));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
+ &random);
+ } else {
+ struct smp_cmd_pairing_confirm confirm;
+
+ memset(&confirm, 0, sizeof(confirm));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
+ &confirm);
+ }
+}
+
+static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_pairing_random cp;
+
+ BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+ skb_pull(skb, sizeof(cp));
+
+ if (conn->hcon->out) {
+ /* FIXME: start encryption */
+ } else {
+ memset(&cp, 0, sizeof(cp));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
+ }
+}
+
+static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_security_req *rp = (void *) skb->data;
+ struct smp_cmd_pairing cp;
+
+ BT_DBG("conn %p", conn);
+
+ skb_pull(skb, sizeof(*rp));
+ memset(&cp, 0, sizeof(cp));
+
+ cp.io_capability = 0x00;
+ cp.oob_flag = 0x00;
+ cp.max_key_size = 16;
+ cp.init_key_dist = 0x00;
+ cp.resp_key_dist = 0x00;
+ cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+}
+
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
{
__u8 authreq;
@@ -114,24 +201,33 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
switch (code) {
case SMP_CMD_PAIRING_REQ:
- reason = SMP_PAIRING_NOTSUPP;
- smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
- &reason);
- err = -EOPNOTSUPP;
+ smp_cmd_pairing_req(conn, skb);
break;
case SMP_CMD_PAIRING_FAIL:
break;
case SMP_CMD_PAIRING_RSP:
+ smp_cmd_pairing_rsp(conn, skb);
+ break;
+
+ case SMP_CMD_SECURITY_REQ:
+ smp_cmd_security_req(conn, skb);
+ break;
+
case SMP_CMD_PAIRING_CONFIRM:
+ smp_cmd_pairing_confirm(conn, skb);
+ break;
+
case SMP_CMD_PAIRING_RANDOM:
+ smp_cmd_pairing_random(conn, skb);
+ break;
+
case SMP_CMD_ENCRYPT_INFO:
case SMP_CMD_MASTER_IDENT:
case SMP_CMD_IDENT_INFO:
case SMP_CMD_IDENT_ADDR_INFO:
case SMP_CMD_SIGN_INFO:
- case SMP_CMD_SECURITY_REQ:
default:
BT_DBG("Unknown command code 0x%2.2x", code);
--
1.7.4.1
From: Anderson Briglia <[email protected]>
These simple commands will allow the SMP procedure to be started
and terminated with a not supported error. This is the first step
toward something useful.
Signed-off-by: Vinicius Costa Gomes <[email protected]>
Signed-off-by: Anderson Briglia <[email protected]>
---
include/net/bluetooth/smp.h | 26 ++++++++
net/bluetooth/Makefile | 2 +-
net/bluetooth/smp.c | 146 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 173 insertions(+), 1 deletions(-)
create mode 100644 net/bluetooth/smp.c
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 8f2edbf..36bdd6e 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -1,3 +1,25 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
#ifndef __SMP_H
#define __SMP_H
@@ -73,4 +95,8 @@ struct smp_cmd_security_req {
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
+/* 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);
+
#endif /* __SMP_H */
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index f04fe9a..9b67f3d 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -9,5 +9,5 @@ obj-$(CONFIG_BT_CMTP) += cmtp/
obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-bluetooth-$(CONFIG_BT_L2CAP) += l2cap_core.o l2cap_sock.o
+bluetooth-$(CONFIG_BT_L2CAP) += l2cap_core.o l2cap_sock.o smp.o
bluetooth-$(CONFIG_BT_SCO) += sco.o
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644
index 0000000..8b67a56
--- /dev/null
+++ b/net/bluetooth/smp.c
@@ -0,0 +1,146 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
+
+static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
+ u16 dlen, void *data)
+{
+ struct sk_buff *skb;
+ struct l2cap_hdr *lh;
+ int len;
+
+ len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
+
+ if (len > conn->mtu)
+ return NULL;
+
+ skb = bt_skb_alloc(len, GFP_ATOMIC);
+ if (!skb)
+ return NULL;
+
+ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+ lh->len = cpu_to_le16(sizeof(code) + dlen);
+ lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+ memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+
+ memcpy(skb_put(skb, dlen), data, dlen);
+
+ return skb;
+}
+
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
+{
+ struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+
+ BT_DBG("code 0x%2.2x", code);
+
+ if (!skb)
+ return;
+
+ hci_send_acl(conn->hcon, skb, 0);
+}
+
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+{
+ __u8 authreq;
+
+ BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
+
+ switch (sec_level) {
+ case BT_SECURITY_MEDIUM:
+ /* Encrypted, no MITM protection */
+ authreq = HCI_AT_NO_BONDING_MITM;
+ break;
+
+ case BT_SECURITY_HIGH:
+ /* Bonding, MITM protection */
+ authreq = HCI_AT_GENERAL_BONDING_MITM;
+ break;
+
+ case BT_SECURITY_LOW:
+ default:
+ return 1;
+ }
+
+ if (conn->hcon->link_mode & HCI_LM_MASTER) {
+ struct smp_cmd_pairing cp;
+ cp.io_capability = 0x00;
+ cp.oob_flag = 0x00;
+ cp.max_key_size = 16;
+ cp.init_key_dist = 0x00;
+ cp.resp_key_dist = 0x00;
+ cp.auth_req = authreq;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+ } else {
+ struct smp_cmd_security_req cp;
+ cp.auth_req = authreq;
+ smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
+ }
+
+ return 0;
+}
+
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ __u8 code = skb->data[0];
+ __u8 reason;
+ int err = 0;
+
+ skb_pull(skb, sizeof(code));
+
+ switch (code) {
+ case SMP_CMD_PAIRING_REQ:
+ reason = SMP_PAIRING_NOTSUPP;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+ &reason);
+ err = -EOPNOTSUPP;
+ break;
+
+ case SMP_CMD_PAIRING_FAIL:
+ break;
+
+ case SMP_CMD_PAIRING_RSP:
+ case SMP_CMD_PAIRING_CONFIRM:
+ case SMP_CMD_PAIRING_RANDOM:
+ case SMP_CMD_ENCRYPT_INFO:
+ case SMP_CMD_MASTER_IDENT:
+ case SMP_CMD_IDENT_INFO:
+ case SMP_CMD_IDENT_ADDR_INFO:
+ case SMP_CMD_SIGN_INFO:
+ case SMP_CMD_SECURITY_REQ:
+ default:
+ BT_DBG("Unknown command code 0x%2.2x", code);
+
+ reason = SMP_CMD_NOTSUPP;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+ &reason);
+ err = -EOPNOTSUPP;
+ }
+
+ kfree_skb(skb);
+ return err;
+}
--
1.7.4.1
On 16:07 Thu 24 Mar, Brian Gix wrote:
> On 3/24/2011 7:14 AM, Claudio Takahasi wrote:
> >Hi all developers interested on LE,
> >
[ ... ]
> >
> >Patches not upstream(bluetooth-next) are available here:
> >git://gitorious.org/bluetooth-next/for-upstream.git
> >
> >Contains patches for SM just works method, advertising cache and MTU.
>
> Are these rebased off of bluetooth-next on kernel.org?
>
Now they are.
I also pushed the patches that add support for storing (and using) LTKs
to this repository. It needs a userspace that supports this[1].
I am not sending them for proper review yet, because they depend
strongly on the first SMP patches. But comments are welcome.
>
> >BR,
> >Claudio
>
>
> --
> Brian Gix
> [email protected]
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Cheers,
--
Vinicius
[1] git://gitorious.org/~vcgomes/bluez/vcgomes-bluez.git (branch mgmt)
On 3/24/2011 7:14 AM, Claudio Takahasi wrote:
> Hi all developers interested on LE,
>
> On Tue, Mar 15, 2011 at 4:12 PM, Brian Gix<[email protected]> wrote:
>> On 3/15/2011 12:03 PM, Anderson Briglia wrote:
>>>
>>> Hi all,
>>>
>>> On Wed, Mar 9, 2011 at 6:52 PM, Vinicius Costa Gomes
>>> <[email protected]> wrote:
>>>>
>>>> On 14:45 Thu 03 Mar, Vinicius Costa Gomes wrote:
>>>>>
>>>>> Hi Marcel,
>>>>>
>>>>> On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
>>>>>>
>>>>>> Hi Vinicius,
>>>>>>
>>>>>> * Vinicius Gomes<[email protected]> [2011-02-27 21:49:39
>>>>>> -0300]:
>>>>>>
>>>>>>> Hi Gustavo,
>>>>>>>
>>>>>>> On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
>>>>>>> <[email protected]> wrote:
>>>>>>>>
>>>>>>>> Hi Vinicius,
>>>>>>>>
>>>>>>>> * Vinicius Costa Gomes<[email protected]> [2011-02-21
>>>>>>>> 14:23:51 -0300]:
>>>>>>>>
>>
>> [...]
>>
>>>>>
>>>>> Any ideas?
>>>>
>>>> Still no ideas?
>>>>
>>>
>>> We at INdT have some patches based on top of this series. What is the
>>> maintainer's opinion about this series? I'm asking it because should
>>> be great to know if we are doing the right stuff or we need to change
>>> our approach. The number of features and patches that have this series
>>> as dependency is growing.
>>
>> I am also developing patches off of this series and have signed off on their
>> baseline functionality.
>>
>>> Regards,
>>>
>>> Anderson Briglia
>>
>>
>> --
>> Brian Gix
>> [email protected]
>> Employee of Qualcomm Innovation Center, Inc.
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
>> in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
> Patches not upstream(bluetooth-next) are available here:
> git://gitorious.org/bluetooth-next/for-upstream.git
>
> Contains patches for SM just works method, advertising cache and MTU.
Are these rebased off of bluetooth-next on kernel.org?
> BR,
> Claudio
--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Hi all developers interested on LE,
On Tue, Mar 15, 2011 at 4:12 PM, Brian Gix <[email protected]> wrote:
> On 3/15/2011 12:03 PM, Anderson Briglia wrote:
>>
>> Hi all,
>>
>> On Wed, Mar 9, 2011 at 6:52 PM, Vinicius Costa Gomes
>> <[email protected]> wrote:
>>>
>>> On 14:45 Thu 03 Mar, Vinicius Costa Gomes wrote:
>>>>
>>>> Hi Marcel,
>>>>
>>>> On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
>>>>>
>>>>> Hi Vinicius,
>>>>>
>>>>> * Vinicius Gomes<[email protected]> [2011-02-27 21:49:39
>>>>> -0300]:
>>>>>
>>>>>> Hi Gustavo,
>>>>>>
>>>>>> On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
>>>>>> <[email protected]> wrote:
>>>>>>>
>>>>>>> Hi Vinicius,
>>>>>>>
>>>>>>> * Vinicius Costa Gomes<[email protected]> [2011-02-21
>>>>>>> 14:23:51 -0300]:
>>>>>>>
>
> [...]
>
>>>>
>>>> Any ideas?
>>>
>>> Still no ideas?
>>>
>>
>> We at INdT have some patches based on top of this series. What is the
>> maintainer's opinion about this series? I'm asking it because should
>> be great to know if we are doing the right stuff or we need to change
>> our approach. The number of features and patches that have this series
>> as dependency is growing.
>
> I am also developing patches off of this series and have signed off on their
> baseline functionality.
>
>> Regards,
>>
>> Anderson Briglia
>
>
> --
> Brian Gix
> [email protected]
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Patches not upstream(bluetooth-next) are available here:
git://gitorious.org/bluetooth-next/for-upstream.git
Contains patches for SM just works method, advertising cache and MTU.
BR,
Claudio
On 3/15/2011 12:03 PM, Anderson Briglia wrote:
> Hi all,
>
> On Wed, Mar 9, 2011 at 6:52 PM, Vinicius Costa Gomes
> <[email protected]> wrote:
>> On 14:45 Thu 03 Mar, Vinicius Costa Gomes wrote:
>>> Hi Marcel,
>>>
>>> On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
>>>> Hi Vinicius,
>>>>
>>>> * Vinicius Gomes<[email protected]> [2011-02-27 21:49:39 -0300]:
>>>>
>>>>> Hi Gustavo,
>>>>>
>>>>> On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
>>>>> <[email protected]> wrote:
>>>>>> Hi Vinicius,
>>>>>>
>>>>>> * Vinicius Costa Gomes<[email protected]> [2011-02-21 14:23:51 -0300]:
>>>>>>
[...]
>>>
>>> Any ideas?
>>
>> Still no ideas?
>>
>
> We at INdT have some patches based on top of this series. What is the
> maintainer's opinion about this series? I'm asking it because should
> be great to know if we are doing the right stuff or we need to change
> our approach. The number of features and patches that have this series
> as dependency is growing.
I am also developing patches off of this series and have signed off on
their baseline functionality.
> Regards,
>
> Anderson Briglia
--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Hi all,
On Wed, Mar 9, 2011 at 6:52 PM, Vinicius Costa Gomes
<[email protected]> wrote:
> On 14:45 Thu 03 Mar, Vinicius Costa Gomes wrote:
>> Hi Marcel,
>>
>> On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
>> > Hi Vinicius,
>> >
>> > * Vinicius Gomes <[email protected]> [2011-02-27 21:49:39 -0300]:
>> >
>> > > Hi Gustavo,
>> > >
>> > > On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
>> > > <[email protected]> wrote:
>> > > > Hi Vinicius,
>> > > >
>> > > > * Vinicius Costa Gomes <[email protected]> [2011-02-21 14:23:51 -0300]:
>> > > >
>> > > >> This will allow using the crypto subsystem for encrypting data. As SMP
>> > > >> (Security Manager Protocol) is implemented almost entirely on the host
>> > > >> side and the crypto module already implements the needed methods
>> > > >> (AES-128), it makes sense to use it.
>> > > >>
>> > > >> This patch also adds a new Kconfig option to toggle the SMP support.
>> > > >>
>> > > >> Signed-off-by: Vinicius Costa Gomes <[email protected]>
>> > > >> Signed-off-by: Anderson Briglia <[email protected]>
>> > > >> ---
>> > > >> ?include/net/bluetooth/hci_core.h | ? ?2 ++
>> > > >> ?net/bluetooth/Kconfig ? ? ? ? ? ?| ? ?6 ++++++
>> > > >> ?net/bluetooth/hci_core.c ? ? ? ? | ? 22 ++++++++++++++++++++++
>> > > >> ?net/bluetooth/smp.c ? ? ? ? ? ? ?| ? 17 +++++++++++++++--
>> > > >> ?4 files changed, 45 insertions(+), 2 deletions(-)
>> > > >>
>> > > >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> > > >> index d5d8454..e8dbde8 100644
>> > > >> --- a/include/net/bluetooth/hci_core.h
>> > > >> +++ b/include/net/bluetooth/hci_core.h
>> > > >> @@ -161,6 +161,8 @@ struct hci_dev {
>> > > >>
>> > > >> ? ? ? __u16 ? ? ? ? ? ? ? ? ? init_last_cmd;
>> > > >>
>> > > >> + ? ? struct crypto_blkcipher *tfm;
>> > > >> +
>> > > >> ? ? ? struct inquiry_cache ? ?inq_cache;
>> > > >> ? ? ? struct hci_conn_hash ? ?conn_hash;
>> > > >> ? ? ? struct list_head ? ? ? ?blacklist;
>> > > >> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
>> > > >> index c6f9c2f..e9f40af 100644
>> > > >> --- a/net/bluetooth/Kconfig
>> > > >> +++ b/net/bluetooth/Kconfig
>> > > >> @@ -22,6 +22,7 @@ menuconfig BT
>> > > >> ? ? ? ? ? ?BNEP Module (Bluetooth Network Encapsulation Protocol)
>> > > >> ? ? ? ? ? ?CMTP Module (CAPI Message Transport Protocol)
>> > > >> ? ? ? ? ? ?HIDP Module (Human Interface Device Protocol)
>> > > >> + ? ? ? ? ?SMP Module (Security Manager Protocol)
>> > > >>
>> > > >> ? ? ? ? Say Y here to compile Bluetooth support into the kernel or say M to
>> > > >> ? ? ? ? compile it as module (bluetooth).
>> > > >> @@ -35,11 +36,16 @@ config BT_L2CAP
>> > > >> ? ? ? bool "L2CAP protocol support"
>> > > >> ? ? ? depends on BT
>> > > >> ? ? ? select CRC16
>> > > >> + ? ? select CRYPTO_BLKCIPHER
>> > > >> + ? ? select CRYPTO_AES
>> > > >> ? ? ? help
>> > > >> ? ? ? ? L2CAP (Logical Link Control and Adaptation Protocol) provides
>> > > >> ? ? ? ? connection oriented and connection-less data transport. ?L2CAP
>> > > >> ? ? ? ? support is required for most Bluetooth applications.
>> > > >>
>> > > >> + ? ? ? Also included is support for SMP (Security Manager Protocol) which
>> > > >> + ? ? ? is the security layer on top of LE (Low Energy) links.
>> > > >> +
>> > > >> ?config BT_SCO
>> > > >> ? ? ? bool "SCO links support"
>> > > >> ? ? ? depends on BT
>> > > >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> > > >> index b372fb8..ff67843 100644
>> > > >> --- a/net/bluetooth/hci_core.c
>> > > >> +++ b/net/bluetooth/hci_core.c
>> > > >> @@ -42,6 +42,7 @@
>> > > >> ?#include <linux/notifier.h>
>> > > >> ?#include <linux/rfkill.h>
>> > > >> ?#include <linux/timer.h>
>> > > >> +#include <linux/crypto.h>
>> > > >> ?#include <net/sock.h>
>> > > >>
>> > > >> ?#include <asm/system.h>
>> > > >> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
>> > > >>
>> > > >> ?static DEFINE_RWLOCK(hci_task_lock);
>> > > >>
>> > > >> +static int enable_smp;
>> > > >> +
>> > > >> ?/* HCI device list */
>> > > >> ?LIST_HEAD(hci_dev_list);
>> > > >> ?DEFINE_RWLOCK(hci_dev_list_lock);
>> > > >> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
>> > > >> ? ? ? tasklet_schedule(&hdev->cmd_task);
>> > > >> ?}
>> > > >>
>> > > >> +static struct crypto_blkcipher *alloc_cypher(void)
>> > > >> +{
>> > > >> + ? ? if (enable_smp)
>> > > >> + ? ? ? ? ? ? return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
>> > > >> +
>> > > >> + ? ? return ERR_PTR(-ENOTSUPP);
>> > > >> +}
>> > > >> +
>> > > >> ?/* Register HCI device */
>> > > >> ?int hci_register_dev(struct hci_dev *hdev)
>> > > >> ?{
>> > > >> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
>> > > >> ? ? ? if (!hdev->workqueue)
>> > > >> ? ? ? ? ? ? ? goto nomem;
>> > > >>
>> > > >> + ? ? hdev->tfm = alloc_cypher();
>> > > >> + ? ? if (IS_ERR(hdev->tfm))
>> > > >> + ? ? ? ? ? ? BT_INFO("Failed to load transform for ecb(aes): %ld",
>> > > >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PTR_ERR(hdev->tfm));
>> > > >> +
>> > > >> ? ? ? hci_register_sysfs(hdev);
>> > > >>
>> > > >> ? ? ? hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
>> > > >> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
>> > > >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !test_bit(HCI_SETUP, &hdev->flags))
>> > > >> ? ? ? ? ? ? ? mgmt_index_removed(hdev->id);
>> > > >>
>> > > >> + ? ? if (!IS_ERR(hdev->tfm))
>> > > >> + ? ? ? ? ? ? crypto_free_blkcipher(hdev->tfm);
>> > > >> +
>> > > >> ? ? ? hci_notify(hdev, HCI_DEV_UNREG);
>> > > >>
>> > > >> ? ? ? if (hdev->rfkill) {
>> > > >> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
>> > > >> ? ? ? ? ? ? ? }
>> > > >> ? ? ? }
>> > > >> ?}
>> > > >> +
>> > > >> +module_param(enable_smp, bool, 0644);
>> > > >> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
>> > > >
>> > > > This all should be obviously inside smp.c
>> > >
>> > > I have a couple of points against it:
>> > >
>> > > 1. it's only used for one purpose, it says whether to try or not to
>> > > allocate the block cypher, which is done during the adapter
>> > > registration;
>> > >
>> > > 2. If the current way is ok, it would mean that I would need to export
>> > > another method from smp.c, that was something that I tried to
>> > > minimize;
>> > >
>> > > 3. and my weakest argument, seems that there are other similar uses,
>> > > for example enable_mgmt.
>> >
>> > A similar example here is enable_ertm inside l2cap_core.c. It's a L2CAP
>> > related option and should reside inside L2CAP code.
>> >
>> > >
>> > > But if you think the code will be clearer moving that to smp.c, will
>> > > be glad to change.
>> >
>> > I don't see the point on have it on hci code. SMP and Block cypher has
>> > not much to do with HCI. I prefer it on smp.c
>>
>> Gustavo and I were talking on IRC and couldn't come to a solution, so
>> we ask you for some input.
>>
>> So, just to give a little more context, the problem is that the crypto
>> functions used in SMP depend on the allocation of a block cypher "transform",
>> this allocation must happen during user context.
>>
>> The current solution is that the allocation is done in hci_core.c during the
>> adapter registration, but only when the enable_smp module parameter is enabled.
>> When the parameter is disabled the allocation method just returns an invalid
>> pointer and everything happens the same as if the allocation has failed.
>>
>> Gustavo has a preference for an ondemand aproach, for example, using a
>> workqueue for doing the allocation, and trying the allocation just when SMP is
>> going to be used, e.g. when we receive the first SMP message or when some
>> security level is activated for that socket.
>>
>> Any ideas?
>
> Still no ideas?
>
We at INdT have some patches based on top of this series. What is the
maintainer's opinion about this series? I'm asking it because should
be great to know if we are doing the right stuff or we need to change
our approach. The number of features and patches that have this series
as dependency is growing.
Regards,
Anderson Briglia
>>
>> >
>> > --
>> > Gustavo F. Padovan
>> > http://profusion.mobi
>>
>>
>> Cheers,
>> --
>> Vinicius
>
> --
> Vinicius
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
--
INdT - Instituto Nokia de tecnologia
+55 2126 1122
http://techblog.briglia.net
On 14:45 Thu 03 Mar, Vinicius Costa Gomes wrote:
> Hi Marcel,
>
> On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
> > Hi Vinicius,
> >
> > * Vinicius Gomes <[email protected]> [2011-02-27 21:49:39 -0300]:
> >
> > > Hi Gustavo,
> > >
> > > On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
> > > <[email protected]> wrote:
> > > > Hi Vinicius,
> > > >
> > > > * Vinicius Costa Gomes <[email protected]> [2011-02-21 14:23:51 -0300]:
> > > >
> > > >> This will allow using the crypto subsystem for encrypting data. As SMP
> > > >> (Security Manager Protocol) is implemented almost entirely on the host
> > > >> side and the crypto module already implements the needed methods
> > > >> (AES-128), it makes sense to use it.
> > > >>
> > > >> This patch also adds a new Kconfig option to toggle the SMP support.
> > > >>
> > > >> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > > >> Signed-off-by: Anderson Briglia <[email protected]>
> > > >> ---
> > > >> ?include/net/bluetooth/hci_core.h | ? ?2 ++
> > > >> ?net/bluetooth/Kconfig ? ? ? ? ? ?| ? ?6 ++++++
> > > >> ?net/bluetooth/hci_core.c ? ? ? ? | ? 22 ++++++++++++++++++++++
> > > >> ?net/bluetooth/smp.c ? ? ? ? ? ? ?| ? 17 +++++++++++++++--
> > > >> ?4 files changed, 45 insertions(+), 2 deletions(-)
> > > >>
> > > >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > > >> index d5d8454..e8dbde8 100644
> > > >> --- a/include/net/bluetooth/hci_core.h
> > > >> +++ b/include/net/bluetooth/hci_core.h
> > > >> @@ -161,6 +161,8 @@ struct hci_dev {
> > > >>
> > > >> ? ? ? __u16 ? ? ? ? ? ? ? ? ? init_last_cmd;
> > > >>
> > > >> + ? ? struct crypto_blkcipher *tfm;
> > > >> +
> > > >> ? ? ? struct inquiry_cache ? ?inq_cache;
> > > >> ? ? ? struct hci_conn_hash ? ?conn_hash;
> > > >> ? ? ? struct list_head ? ? ? ?blacklist;
> > > >> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
> > > >> index c6f9c2f..e9f40af 100644
> > > >> --- a/net/bluetooth/Kconfig
> > > >> +++ b/net/bluetooth/Kconfig
> > > >> @@ -22,6 +22,7 @@ menuconfig BT
> > > >> ? ? ? ? ? ?BNEP Module (Bluetooth Network Encapsulation Protocol)
> > > >> ? ? ? ? ? ?CMTP Module (CAPI Message Transport Protocol)
> > > >> ? ? ? ? ? ?HIDP Module (Human Interface Device Protocol)
> > > >> + ? ? ? ? ?SMP Module (Security Manager Protocol)
> > > >>
> > > >> ? ? ? ? Say Y here to compile Bluetooth support into the kernel or say M to
> > > >> ? ? ? ? compile it as module (bluetooth).
> > > >> @@ -35,11 +36,16 @@ config BT_L2CAP
> > > >> ? ? ? bool "L2CAP protocol support"
> > > >> ? ? ? depends on BT
> > > >> ? ? ? select CRC16
> > > >> + ? ? select CRYPTO_BLKCIPHER
> > > >> + ? ? select CRYPTO_AES
> > > >> ? ? ? help
> > > >> ? ? ? ? L2CAP (Logical Link Control and Adaptation Protocol) provides
> > > >> ? ? ? ? connection oriented and connection-less data transport. ?L2CAP
> > > >> ? ? ? ? support is required for most Bluetooth applications.
> > > >>
> > > >> + ? ? ? Also included is support for SMP (Security Manager Protocol) which
> > > >> + ? ? ? is the security layer on top of LE (Low Energy) links.
> > > >> +
> > > >> ?config BT_SCO
> > > >> ? ? ? bool "SCO links support"
> > > >> ? ? ? depends on BT
> > > >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > >> index b372fb8..ff67843 100644
> > > >> --- a/net/bluetooth/hci_core.c
> > > >> +++ b/net/bluetooth/hci_core.c
> > > >> @@ -42,6 +42,7 @@
> > > >> ?#include <linux/notifier.h>
> > > >> ?#include <linux/rfkill.h>
> > > >> ?#include <linux/timer.h>
> > > >> +#include <linux/crypto.h>
> > > >> ?#include <net/sock.h>
> > > >>
> > > >> ?#include <asm/system.h>
> > > >> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
> > > >>
> > > >> ?static DEFINE_RWLOCK(hci_task_lock);
> > > >>
> > > >> +static int enable_smp;
> > > >> +
> > > >> ?/* HCI device list */
> > > >> ?LIST_HEAD(hci_dev_list);
> > > >> ?DEFINE_RWLOCK(hci_dev_list_lock);
> > > >> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
> > > >> ? ? ? tasklet_schedule(&hdev->cmd_task);
> > > >> ?}
> > > >>
> > > >> +static struct crypto_blkcipher *alloc_cypher(void)
> > > >> +{
> > > >> + ? ? if (enable_smp)
> > > >> + ? ? ? ? ? ? return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> > > >> +
> > > >> + ? ? return ERR_PTR(-ENOTSUPP);
> > > >> +}
> > > >> +
> > > >> ?/* Register HCI device */
> > > >> ?int hci_register_dev(struct hci_dev *hdev)
> > > >> ?{
> > > >> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
> > > >> ? ? ? if (!hdev->workqueue)
> > > >> ? ? ? ? ? ? ? goto nomem;
> > > >>
> > > >> + ? ? hdev->tfm = alloc_cypher();
> > > >> + ? ? if (IS_ERR(hdev->tfm))
> > > >> + ? ? ? ? ? ? BT_INFO("Failed to load transform for ecb(aes): %ld",
> > > >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PTR_ERR(hdev->tfm));
> > > >> +
> > > >> ? ? ? hci_register_sysfs(hdev);
> > > >>
> > > >> ? ? ? hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> > > >> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
> > > >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !test_bit(HCI_SETUP, &hdev->flags))
> > > >> ? ? ? ? ? ? ? mgmt_index_removed(hdev->id);
> > > >>
> > > >> + ? ? if (!IS_ERR(hdev->tfm))
> > > >> + ? ? ? ? ? ? crypto_free_blkcipher(hdev->tfm);
> > > >> +
> > > >> ? ? ? hci_notify(hdev, HCI_DEV_UNREG);
> > > >>
> > > >> ? ? ? if (hdev->rfkill) {
> > > >> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
> > > >> ? ? ? ? ? ? ? }
> > > >> ? ? ? }
> > > >> ?}
> > > >> +
> > > >> +module_param(enable_smp, bool, 0644);
> > > >> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
> > > >
> > > > This all should be obviously inside smp.c
> > >
> > > I have a couple of points against it:
> > >
> > > 1. it's only used for one purpose, it says whether to try or not to
> > > allocate the block cypher, which is done during the adapter
> > > registration;
> > >
> > > 2. If the current way is ok, it would mean that I would need to export
> > > another method from smp.c, that was something that I tried to
> > > minimize;
> > >
> > > 3. and my weakest argument, seems that there are other similar uses,
> > > for example enable_mgmt.
> >
> > A similar example here is enable_ertm inside l2cap_core.c. It's a L2CAP
> > related option and should reside inside L2CAP code.
> >
> > >
> > > But if you think the code will be clearer moving that to smp.c, will
> > > be glad to change.
> >
> > I don't see the point on have it on hci code. SMP and Block cypher has
> > not much to do with HCI. I prefer it on smp.c
>
> Gustavo and I were talking on IRC and couldn't come to a solution, so
> we ask you for some input.
>
> So, just to give a little more context, the problem is that the crypto
> functions used in SMP depend on the allocation of a block cypher "transform",
> this allocation must happen during user context.
>
> The current solution is that the allocation is done in hci_core.c during the
> adapter registration, but only when the enable_smp module parameter is enabled.
> When the parameter is disabled the allocation method just returns an invalid
> pointer and everything happens the same as if the allocation has failed.
>
> Gustavo has a preference for an ondemand aproach, for example, using a
> workqueue for doing the allocation, and trying the allocation just when SMP is
> going to be used, e.g. when we receive the first SMP message or when some
> security level is activated for that socket.
>
> Any ideas?
Still no ideas?
>
> >
> > --
> > Gustavo F. Padovan
> > http://profusion.mobi
>
>
> Cheers,
> --
> Vinicius
--
Vinicius
Hi Marcel,
On 14:28 Mon 28 Feb, Gustavo F. Padovan wrote:
> Hi Vinicius,
>
> * Vinicius Gomes <[email protected]> [2011-02-27 21:49:39 -0300]:
>
> > Hi Gustavo,
> >
> > On Sun, Feb 27, 2011 at 5:20 PM, Gustavo F. Padovan
> > <[email protected]> wrote:
> > > Hi Vinicius,
> > >
> > > * Vinicius Costa Gomes <[email protected]> [2011-02-21 14:23:51 -0300]:
> > >
> > >> This will allow using the crypto subsystem for encrypting data. As SMP
> > >> (Security Manager Protocol) is implemented almost entirely on the host
> > >> side and the crypto module already implements the needed methods
> > >> (AES-128), it makes sense to use it.
> > >>
> > >> This patch also adds a new Kconfig option to toggle the SMP support.
> > >>
> > >> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > >> Signed-off-by: Anderson Briglia <[email protected]>
> > >> ---
> > >> ?include/net/bluetooth/hci_core.h | ? ?2 ++
> > >> ?net/bluetooth/Kconfig ? ? ? ? ? ?| ? ?6 ++++++
> > >> ?net/bluetooth/hci_core.c ? ? ? ? | ? 22 ++++++++++++++++++++++
> > >> ?net/bluetooth/smp.c ? ? ? ? ? ? ?| ? 17 +++++++++++++++--
> > >> ?4 files changed, 45 insertions(+), 2 deletions(-)
> > >>
> > >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > >> index d5d8454..e8dbde8 100644
> > >> --- a/include/net/bluetooth/hci_core.h
> > >> +++ b/include/net/bluetooth/hci_core.h
> > >> @@ -161,6 +161,8 @@ struct hci_dev {
> > >>
> > >> ? ? ? __u16 ? ? ? ? ? ? ? ? ? init_last_cmd;
> > >>
> > >> + ? ? struct crypto_blkcipher *tfm;
> > >> +
> > >> ? ? ? struct inquiry_cache ? ?inq_cache;
> > >> ? ? ? struct hci_conn_hash ? ?conn_hash;
> > >> ? ? ? struct list_head ? ? ? ?blacklist;
> > >> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
> > >> index c6f9c2f..e9f40af 100644
> > >> --- a/net/bluetooth/Kconfig
> > >> +++ b/net/bluetooth/Kconfig
> > >> @@ -22,6 +22,7 @@ menuconfig BT
> > >> ? ? ? ? ? ?BNEP Module (Bluetooth Network Encapsulation Protocol)
> > >> ? ? ? ? ? ?CMTP Module (CAPI Message Transport Protocol)
> > >> ? ? ? ? ? ?HIDP Module (Human Interface Device Protocol)
> > >> + ? ? ? ? ?SMP Module (Security Manager Protocol)
> > >>
> > >> ? ? ? ? Say Y here to compile Bluetooth support into the kernel or say M to
> > >> ? ? ? ? compile it as module (bluetooth).
> > >> @@ -35,11 +36,16 @@ config BT_L2CAP
> > >> ? ? ? bool "L2CAP protocol support"
> > >> ? ? ? depends on BT
> > >> ? ? ? select CRC16
> > >> + ? ? select CRYPTO_BLKCIPHER
> > >> + ? ? select CRYPTO_AES
> > >> ? ? ? help
> > >> ? ? ? ? L2CAP (Logical Link Control and Adaptation Protocol) provides
> > >> ? ? ? ? connection oriented and connection-less data transport. ?L2CAP
> > >> ? ? ? ? support is required for most Bluetooth applications.
> > >>
> > >> + ? ? ? Also included is support for SMP (Security Manager Protocol) which
> > >> + ? ? ? is the security layer on top of LE (Low Energy) links.
> > >> +
> > >> ?config BT_SCO
> > >> ? ? ? bool "SCO links support"
> > >> ? ? ? depends on BT
> > >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > >> index b372fb8..ff67843 100644
> > >> --- a/net/bluetooth/hci_core.c
> > >> +++ b/net/bluetooth/hci_core.c
> > >> @@ -42,6 +42,7 @@
> > >> ?#include <linux/notifier.h>
> > >> ?#include <linux/rfkill.h>
> > >> ?#include <linux/timer.h>
> > >> +#include <linux/crypto.h>
> > >> ?#include <net/sock.h>
> > >>
> > >> ?#include <asm/system.h>
> > >> @@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
> > >>
> > >> ?static DEFINE_RWLOCK(hci_task_lock);
> > >>
> > >> +static int enable_smp;
> > >> +
> > >> ?/* HCI device list */
> > >> ?LIST_HEAD(hci_dev_list);
> > >> ?DEFINE_RWLOCK(hci_dev_list_lock);
> > >> @@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
> > >> ? ? ? tasklet_schedule(&hdev->cmd_task);
> > >> ?}
> > >>
> > >> +static struct crypto_blkcipher *alloc_cypher(void)
> > >> +{
> > >> + ? ? if (enable_smp)
> > >> + ? ? ? ? ? ? return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> > >> +
> > >> + ? ? return ERR_PTR(-ENOTSUPP);
> > >> +}
> > >> +
> > >> ?/* Register HCI device */
> > >> ?int hci_register_dev(struct hci_dev *hdev)
> > >> ?{
> > >> @@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
> > >> ? ? ? if (!hdev->workqueue)
> > >> ? ? ? ? ? ? ? goto nomem;
> > >>
> > >> + ? ? hdev->tfm = alloc_cypher();
> > >> + ? ? if (IS_ERR(hdev->tfm))
> > >> + ? ? ? ? ? ? BT_INFO("Failed to load transform for ecb(aes): %ld",
> > >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PTR_ERR(hdev->tfm));
> > >> +
> > >> ? ? ? hci_register_sysfs(hdev);
> > >>
> > >> ? ? ? hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> > >> @@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
> > >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !test_bit(HCI_SETUP, &hdev->flags))
> > >> ? ? ? ? ? ? ? mgmt_index_removed(hdev->id);
> > >>
> > >> + ? ? if (!IS_ERR(hdev->tfm))
> > >> + ? ? ? ? ? ? crypto_free_blkcipher(hdev->tfm);
> > >> +
> > >> ? ? ? hci_notify(hdev, HCI_DEV_UNREG);
> > >>
> > >> ? ? ? if (hdev->rfkill) {
> > >> @@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
> > >> ? ? ? ? ? ? ? }
> > >> ? ? ? }
> > >> ?}
> > >> +
> > >> +module_param(enable_smp, bool, 0644);
> > >> +MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
> > >
> > > This all should be obviously inside smp.c
> >
> > I have a couple of points against it:
> >
> > 1. it's only used for one purpose, it says whether to try or not to
> > allocate the block cypher, which is done during the adapter
> > registration;
> >
> > 2. If the current way is ok, it would mean that I would need to export
> > another method from smp.c, that was something that I tried to
> > minimize;
> >
> > 3. and my weakest argument, seems that there are other similar uses,
> > for example enable_mgmt.
>
> A similar example here is enable_ertm inside l2cap_core.c. It's a L2CAP
> related option and should reside inside L2CAP code.
>
> >
> > But if you think the code will be clearer moving that to smp.c, will
> > be glad to change.
>
> I don't see the point on have it on hci code. SMP and Block cypher has
> not much to do with HCI. I prefer it on smp.c
Gustavo and I were talking on IRC and couldn't come to a solution, so
we ask you for some input.
So, just to give a little more context, the problem is that the crypto
functions used in SMP depend on the allocation of a block cypher "transform",
this allocation must happen during user context.
The current solution is that the allocation is done in hci_core.c during the
adapter registration, but only when the enable_smp module parameter is enabled.
When the parameter is disabled the allocation method just returns an invalid
pointer and everything happens the same as if the allocation has failed.
Gustavo has a preference for an ondemand aproach, for example, using a
workqueue for doing the allocation, and trying the allocation just when SMP is
going to be used, e.g. when we receive the first SMP message or when some
security level is activated for that socket.
Any ideas?
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
Cheers,
--
Vinicius
Hi Gustavo,
On 20:36 Wed 06 Apr, Gustavo F. Padovan wrote:
> Hi Vinicius,
>
> * Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:47 -0300]:
>
> > From: Anderson Briglia <[email protected]>
> >
> > This patch adds initial support for verifying the confirmation value
> > that the remote side has sent.
> >
> > Signed-off-by: Anderson Briglia <[email protected]>
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > include/net/bluetooth/l2cap.h | 5 +++++
> > net/bluetooth/smp.c | 17 +++++++++++++++++
> > 2 files changed, 22 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> > index 2b9ca0d..dc4aa63 100644
> > --- a/include/net/bluetooth/l2cap.h
> > +++ b/include/net/bluetooth/l2cap.h
> > @@ -305,6 +305,11 @@ struct l2cap_conn {
> >
> > __u8 disc_reason;
> >
> > + __u8 preq[7]; /* SMP Pairing Request */
> > + __u8 prsp[7]; /* SMP Pairing Response */
> > + __u8 prnd[16]; /* SMP Pairing Random */
> > + __u8 pcnf[16]; /* SMP Pairing Confirm */
> > +
> > struct l2cap_chan_list chan_list;
> > };
> >
> > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> > index 58047e8..7fa3542 100644
> > --- a/net/bluetooth/smp.c
> > +++ b/net/bluetooth/smp.c
> > @@ -192,6 +192,8 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> >
> > BT_DBG("conn %p", conn);
> >
> > + conn->preq[0] = SMP_CMD_PAIRING_REQ;
> > + memcpy(&conn->preq[1], rp, sizeof(*rp));
> > skb_pull(skb, sizeof(*rp));
> >
> > rp->io_capability = 0x00;
> > @@ -201,17 +203,25 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> > rp->resp_key_dist = 0x00;
> > rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
> >
> > + conn->prsp[0] = SMP_CMD_PAIRING_RSP;
> > + memcpy(&conn->prsp[1], rp, sizeof(*rp));
> > +
> > smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
> > }
> >
> > static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
> > {
> > + struct smp_cmd_pairing *rp = (void *) skb->data;
>
> No need for cast here.
Yes, the cast is needed. The pointers types are incompatible.
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
Cheers,
--
Vinicius
Hi Gustavo,
> > This adds support for resuming the user space traffic when SMP
> > negotiation is complete.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > net/bluetooth/l2cap_core.c | 61 ++++++++++++++++++++++---------------------
> > net/bluetooth/l2cap_sock.c | 16 +++++++++++
> > net/bluetooth/smp.c | 40 ++++++++++++++++++++--------
> > 3 files changed, 75 insertions(+), 42 deletions(-)
> >
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 0cec292..a5062f14 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -665,6 +665,22 @@ clean:
> > bh_unlock_sock(parent);
> > }
> >
> > +static void l2cap_chan_ready(struct sock *sk)
> > +{
> > + struct sock *parent = bt_sk(sk)->parent;
> > +
> > + BT_DBG("sk %p, parent %p", sk, parent);
> > +
> > + l2cap_pi(sk)->conf_state = 0;
> > + l2cap_sock_clear_timer(sk);
> > +
> > + sk->sk_state = 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_list *l = &conn->chan_list;
> > @@ -680,15 +696,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
> > for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
> > bh_lock_sock(sk);
> >
> > - if (conn->hcon->type == LE_LINK) {
> > - l2cap_sock_clear_timer(sk);
> > - sk->sk_state = BT_CONNECTED;
> > - sk->sk_state_change(sk);
> > + if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> > if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
> > - BT_DBG("Insufficient security");
> > - }
> > + l2cap_chan_ready(sk);
> >
> > - if (sk->sk_type != SOCK_SEQPACKET &&
> > + } else if (sk->sk_type != SOCK_SEQPACKET &&
> > sk->sk_type != SOCK_STREAM) {
> > l2cap_sock_clear_timer(sk);
> > sk->sk_state = BT_CONNECTED;
> > @@ -1362,29 +1374,6 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
> > return size;
> > }
> >
> > -static void l2cap_chan_ready(struct sock *sk)
> > -{
> > - struct sock *parent = bt_sk(sk)->parent;
> > -
> > - BT_DBG("sk %p, parent %p", sk, parent);
> > -
> > - l2cap_pi(sk)->conf_state = 0;
> > - l2cap_sock_clear_timer(sk);
> > -
> > - if (!parent) {
> > - /* Outgoing channel.
> > - * Wake up socket sleeping on connect.
> > - */
> > - sk->sk_state = BT_CONNECTED;
> > - sk->sk_state_change(sk);
> > - } else {
> > - /* Incoming channel.
> > - * Wake up socket sleeping on accept.
> > - */
> > - parent->sk_data_ready(parent, 0);
> > - }
> > -}
> > -
> > /* Copy frame to all raw sockets on that connection */
> > static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
> > {
> > @@ -3810,6 +3799,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
> > for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
> > bh_lock_sock(sk);
> >
> > + BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
> > +
> > + if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> > + if (!status && encrypt) {
> > + l2cap_pi(sk)->sec_level = hcon->sec_level;
> > + l2cap_chan_ready(sk);
> > + }
> > +
> > + bh_unlock_sock(sk);
> > + continue;
> > + }
> > +
> > if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
> > bh_unlock_sock(sk);
> > continue;
> > diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> > index f77308e..14e491a 100644
> > --- a/net/bluetooth/l2cap_sock.c
> > +++ b/net/bluetooth/l2cap_sock.c
> > @@ -29,6 +29,7 @@
> > #include <net/bluetooth/bluetooth.h>
> > #include <net/bluetooth/hci_core.h>
> > #include <net/bluetooth/l2cap.h>
> > +#include <net/bluetooth/smp.h>
> >
> > /* ---- L2CAP timers ---- */
> > static void l2cap_sock_timeout(unsigned long arg)
> > @@ -614,6 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> > {
> > struct sock *sk = sock->sk;
> > struct bt_security sec;
> > + struct l2cap_conn *conn;
> > int len, err = 0;
> > u32 opt;
> >
> > @@ -650,6 +652,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> > }
> >
> > l2cap_pi(sk)->sec_level = sec.level;
> > +
> > + conn = l2cap_pi(sk)->conn;
> > + if (conn && l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> > + if (!conn->hcon->out) {
> > + err = -EINVAL;
> > + break;
> > + }
> > +
> > + if (smp_conn_security(conn, sec.level))
> > + break;
> > +
> > + err = 0;
> > + sk->sk_state = BT_CONFIG;
> > + }
>
> I don't like the idea of bring SMP stuff to l2cap_sock.c, we are working now
> to clean up that file and keep only socket related stuff there, and only
> channel related stuff in l2cap_core.c. I've already sent a patchset on that
> direction to mailing list. However, I don't have any idea now on how to remove
> smp_conn_security() from here.
I don't think we have much choice here. We could abstract this out with
drivers, but in the end we want direct functions call and not some heavy
abstracted framework. Since lets face it, this is all pretty static.
However we might need some better function naming for this. Some of the
naming inside L2CAP is a bit odd and not really clear what it does.
Regards
Marcel
Hi Gustavo,
On 21:11 Wed 06 Apr, Gustavo F. Padovan wrote:
> Hi Vinicius,
>
> * Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:51 -0300]:
>
> > This adds support for resuming the user space traffic when SMP
> > negotiation is complete.
> >
> > Signed-off-by: Vinicius Costa Gomes <[email protected]>
> > ---
> > net/bluetooth/l2cap_core.c | 61 ++++++++++++++++++++++---------------------
> > net/bluetooth/l2cap_sock.c | 16 +++++++++++
> > net/bluetooth/smp.c | 40 ++++++++++++++++++++--------
> > 3 files changed, 75 insertions(+), 42 deletions(-)
> >
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 0cec292..a5062f14 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -665,6 +665,22 @@ clean:
> > bh_unlock_sock(parent);
> > }
> >
> > +static void l2cap_chan_ready(struct sock *sk)
> > +{
> > + struct sock *parent = bt_sk(sk)->parent;
> > +
> > + BT_DBG("sk %p, parent %p", sk, parent);
> > +
> > + l2cap_pi(sk)->conf_state = 0;
> > + l2cap_sock_clear_timer(sk);
> > +
> > + sk->sk_state = 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_list *l = &conn->chan_list;
> > @@ -680,15 +696,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
> > for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
> > bh_lock_sock(sk);
> >
> > - if (conn->hcon->type == LE_LINK) {
> > - l2cap_sock_clear_timer(sk);
> > - sk->sk_state = BT_CONNECTED;
> > - sk->sk_state_change(sk);
> > + if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> > if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
> > - BT_DBG("Insufficient security");
> > - }
> > + l2cap_chan_ready(sk);
> >
> > - if (sk->sk_type != SOCK_SEQPACKET &&
> > + } else if (sk->sk_type != SOCK_SEQPACKET &&
> > sk->sk_type != SOCK_STREAM) {
> > l2cap_sock_clear_timer(sk);
> > sk->sk_state = BT_CONNECTED;
> > @@ -1362,29 +1374,6 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
> > return size;
> > }
> >
> > -static void l2cap_chan_ready(struct sock *sk)
> > -{
> > - struct sock *parent = bt_sk(sk)->parent;
> > -
> > - BT_DBG("sk %p, parent %p", sk, parent);
> > -
> > - l2cap_pi(sk)->conf_state = 0;
> > - l2cap_sock_clear_timer(sk);
> > -
> > - if (!parent) {
> > - /* Outgoing channel.
> > - * Wake up socket sleeping on connect.
> > - */
> > - sk->sk_state = BT_CONNECTED;
> > - sk->sk_state_change(sk);
> > - } else {
> > - /* Incoming channel.
> > - * Wake up socket sleeping on accept.
> > - */
> > - parent->sk_data_ready(parent, 0);
> > - }
> > -}
> > -
> > /* Copy frame to all raw sockets on that connection */
> > static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
> > {
> > @@ -3810,6 +3799,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
> > for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
> > bh_lock_sock(sk);
> >
> > + BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
> > +
> > + if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> > + if (!status && encrypt) {
> > + l2cap_pi(sk)->sec_level = hcon->sec_level;
> > + l2cap_chan_ready(sk);
> > + }
> > +
> > + bh_unlock_sock(sk);
> > + continue;
> > + }
> > +
> > if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
> > bh_unlock_sock(sk);
> > continue;
> > diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> > index f77308e..14e491a 100644
> > --- a/net/bluetooth/l2cap_sock.c
> > +++ b/net/bluetooth/l2cap_sock.c
> > @@ -29,6 +29,7 @@
> > #include <net/bluetooth/bluetooth.h>
> > #include <net/bluetooth/hci_core.h>
> > #include <net/bluetooth/l2cap.h>
> > +#include <net/bluetooth/smp.h>
> >
> > /* ---- L2CAP timers ---- */
> > static void l2cap_sock_timeout(unsigned long arg)
> > @@ -614,6 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> > {
> > struct sock *sk = sock->sk;
> > struct bt_security sec;
> > + struct l2cap_conn *conn;
> > int len, err = 0;
> > u32 opt;
> >
> > @@ -650,6 +652,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> > }
> >
> > l2cap_pi(sk)->sec_level = sec.level;
> > +
> > + conn = l2cap_pi(sk)->conn;
> > + if (conn && l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> > + if (!conn->hcon->out) {
> > + err = -EINVAL;
> > + break;
> > + }
> > +
> > + if (smp_conn_security(conn, sec.level))
> > + break;
> > +
> > + err = 0;
> > + sk->sk_state = BT_CONFIG;
> > + }
>
> I don't like the idea of bring SMP stuff to l2cap_sock.c, we are working now
> to clean up that file and keep only socket related stuff there, and only
> channel related stuff in l2cap_core.c. I've already sent a patchset on that
> direction to mailing list. However, I don't have any idea now on how to remove
> smp_conn_security() from here.
I understand, but I guess that in order to solve some problems there will be
need for having some points of contact between those parts.
For this security case, one solution is having some kind of mechanism that
checks if the security level of the link/channel attends the security level
requested by the socket. And, in principle, this could even work for BR/EDR
links.
Another thing, is that in the LE case the MTU is negotiated over GATT, so
in our architecture, if we want to support this there will be need for
changing MTU from userspace, most probably setting one socket option.
I think that these are the examples I have against keeping the channel
and the socket *totally* isolated from each other.
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
Cheers,
--
Vinicius
Hi Gustavo,
On 21:14 Wed 06 Apr, Gustavo F. Padovan wrote:
> * Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:55 -0300]:
>
> > This patch adds support for disconnecting the link when SMP procedure
> > takes more than 30 seconds.
>
> As this is a SMP procedure, doesn't make more sense put this timer in SMP
> code? It does not fit quite well to me in l2cap.
The only reason is that SMP code isn't able to tell that the pairing
finished or not. We only can tell that the pairing finished when we receive
the Encryption Changed HCI event or the connection is terminated.
And I don't think that SMP code has to be informed of any of these conditions.
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
Cheers,
--
Vinicius
* Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:55 -0300]:
> This patch adds support for disconnecting the link when SMP procedure
> takes more than 30 seconds.
As this is a SMP procedure, doesn't make more sense put this timer in SMP
code? It does not fit quite well to me in l2cap.
--
Gustavo F. Padovan
http://profusion.mobi
Hi Vinicius,
* Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:51 -0300]:
> This adds support for resuming the user space traffic when SMP
> negotiation is complete.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> net/bluetooth/l2cap_core.c | 61 ++++++++++++++++++++++---------------------
> net/bluetooth/l2cap_sock.c | 16 +++++++++++
> net/bluetooth/smp.c | 40 ++++++++++++++++++++--------
> 3 files changed, 75 insertions(+), 42 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 0cec292..a5062f14 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -665,6 +665,22 @@ clean:
> bh_unlock_sock(parent);
> }
>
> +static void l2cap_chan_ready(struct sock *sk)
> +{
> + struct sock *parent = bt_sk(sk)->parent;
> +
> + BT_DBG("sk %p, parent %p", sk, parent);
> +
> + l2cap_pi(sk)->conf_state = 0;
> + l2cap_sock_clear_timer(sk);
> +
> + sk->sk_state = 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_list *l = &conn->chan_list;
> @@ -680,15 +696,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
> for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
> bh_lock_sock(sk);
>
> - if (conn->hcon->type == LE_LINK) {
> - l2cap_sock_clear_timer(sk);
> - sk->sk_state = BT_CONNECTED;
> - sk->sk_state_change(sk);
> + if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
> - BT_DBG("Insufficient security");
> - }
> + l2cap_chan_ready(sk);
>
> - if (sk->sk_type != SOCK_SEQPACKET &&
> + } else if (sk->sk_type != SOCK_SEQPACKET &&
> sk->sk_type != SOCK_STREAM) {
> l2cap_sock_clear_timer(sk);
> sk->sk_state = BT_CONNECTED;
> @@ -1362,29 +1374,6 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
> return size;
> }
>
> -static void l2cap_chan_ready(struct sock *sk)
> -{
> - struct sock *parent = bt_sk(sk)->parent;
> -
> - BT_DBG("sk %p, parent %p", sk, parent);
> -
> - l2cap_pi(sk)->conf_state = 0;
> - l2cap_sock_clear_timer(sk);
> -
> - if (!parent) {
> - /* Outgoing channel.
> - * Wake up socket sleeping on connect.
> - */
> - sk->sk_state = BT_CONNECTED;
> - sk->sk_state_change(sk);
> - } else {
> - /* Incoming channel.
> - * Wake up socket sleeping on accept.
> - */
> - parent->sk_data_ready(parent, 0);
> - }
> -}
> -
> /* Copy frame to all raw sockets on that connection */
> static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
> {
> @@ -3810,6 +3799,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
> for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
> bh_lock_sock(sk);
>
> + BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
> +
> + if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> + if (!status && encrypt) {
> + l2cap_pi(sk)->sec_level = hcon->sec_level;
> + l2cap_chan_ready(sk);
> + }
> +
> + bh_unlock_sock(sk);
> + continue;
> + }
> +
> if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
> bh_unlock_sock(sk);
> continue;
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index f77308e..14e491a 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -29,6 +29,7 @@
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> #include <net/bluetooth/l2cap.h>
> +#include <net/bluetooth/smp.h>
>
> /* ---- L2CAP timers ---- */
> static void l2cap_sock_timeout(unsigned long arg)
> @@ -614,6 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> {
> struct sock *sk = sock->sk;
> struct bt_security sec;
> + struct l2cap_conn *conn;
> int len, err = 0;
> u32 opt;
>
> @@ -650,6 +652,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> }
>
> l2cap_pi(sk)->sec_level = sec.level;
> +
> + conn = l2cap_pi(sk)->conn;
> + if (conn && l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
> + if (!conn->hcon->out) {
> + err = -EINVAL;
> + break;
> + }
> +
> + if (smp_conn_security(conn, sec.level))
> + break;
> +
> + err = 0;
> + sk->sk_state = BT_CONFIG;
> + }
I don't like the idea of bring SMP stuff to l2cap_sock.c, we are working now
to clean up that file and keep only socket related stuff there, and only
channel related stuff in l2cap_core.c. I've already sent a patchset on that
direction to mailing list. However, I don't have any idea now on how to remove
smp_conn_security() from here.
--
Gustavo F. Padovan
http://profusion.mobi
Hi Vinicius,
* Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:47 -0300]:
> From: Anderson Briglia <[email protected]>
>
> This patch adds initial support for verifying the confirmation value
> that the remote side has sent.
>
> Signed-off-by: Anderson Briglia <[email protected]>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> include/net/bluetooth/l2cap.h | 5 +++++
> net/bluetooth/smp.c | 17 +++++++++++++++++
> 2 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 2b9ca0d..dc4aa63 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -305,6 +305,11 @@ struct l2cap_conn {
>
> __u8 disc_reason;
>
> + __u8 preq[7]; /* SMP Pairing Request */
> + __u8 prsp[7]; /* SMP Pairing Response */
> + __u8 prnd[16]; /* SMP Pairing Random */
> + __u8 pcnf[16]; /* SMP Pairing Confirm */
> +
> struct l2cap_chan_list chan_list;
> };
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 58047e8..7fa3542 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -192,6 +192,8 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>
> BT_DBG("conn %p", conn);
>
> + conn->preq[0] = SMP_CMD_PAIRING_REQ;
> + memcpy(&conn->preq[1], rp, sizeof(*rp));
> skb_pull(skb, sizeof(*rp));
>
> rp->io_capability = 0x00;
> @@ -201,17 +203,25 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> rp->resp_key_dist = 0x00;
> rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
>
> + conn->prsp[0] = SMP_CMD_PAIRING_RSP;
> + memcpy(&conn->prsp[1], rp, sizeof(*rp));
> +
> smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
> }
>
> static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
> {
> + struct smp_cmd_pairing *rp = (void *) skb->data;
No need for cast here.
--
Gustavo F. Padovan
http://profusion.mobi
Hi Vinicius,
* Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:46 -0300]:
> From: Anderson Briglia <[email protected]>
>
> This patch implements SMP crypto functions called ah, c1, s1 and e.
> It also implements auxiliary functions. All These functions are needed
> for SMP keys generation.
>
> Signed-off-by: Anderson Briglia <[email protected]>
> Signed-off-by: Anderson Lizardo <[email protected]>
> Signed-off-by: Bruna Moreira <[email protected]>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> net/bluetooth/smp.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 122 insertions(+), 0 deletions(-)
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 42aed82..58047e8 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -24,6 +24,128 @@
> #include <net/bluetooth/hci_core.h>
> #include <net/bluetooth/l2cap.h>
> #include <net/bluetooth/smp.h>
> +#include <linux/crypto.h>
> +#include <crypto/b128ops.h>
> +
> +static inline void swap128(u8 src[16], u8 dst[16])
> +{
> + int i;
> + for (i = 0; i < 16; i++)
> + dst[15 - i] = src[i];
> +}
> +
> +static inline void swap56(u8 src[7], u8 dst[7])
> +{
> + int i;
> + for (i = 0; i < 7; i++)
> + dst[6 - i] = src[i];
> +}
> +
> +static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
> +{
> + struct blkcipher_desc desc;
> + struct scatterlist sg;
> + int err, iv_len;
> + unsigned char iv[128];
> +
> + if (tfm == NULL) {
> + BT_ERR("tfm %p", tfm);
> + return -EINVAL;
> + }
> +
> + desc.tfm = tfm;
> + desc.flags = 0;
> +
> + err = crypto_blkcipher_setkey(tfm, k, 16);
> + if (err) {
> + BT_ERR("cipher setkey failed: %d", err);
> + return err;
> + }
> +
> + sg_init_one(&sg, r, 16);
> +
> + iv_len = crypto_blkcipher_ivsize(tfm);
> + if (iv_len) {
> + memset(&iv, 0xff, iv_len);
> + crypto_blkcipher_set_iv(tfm, iv, iv_len);
> + }
> +
> + err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
> + if (err)
> + BT_ERR("Encrypt data error %d", err);
> +
> + return err;
> +}
> +
> +static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
> + u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
> + u8 _rat, bdaddr_t *ra, u8 res[16])
> +{
> + u8 p1[16], p2[16], pair[7];
> + bdaddr_t addr;
> + int err;
> +
> + /* p1 = pres || preq || _rat || _iat */
> + memset(p1, 0, 16);
> + swap56(pres, pair);
> +
> + memcpy(p1, pair, 7);
> + swap56(preq, pair);
> +
> + memcpy(p1 + 7, pair, 7);
swap56(pres, p1)
swap56(preq, pi + 7)
> + *(p1 + 14) = _rat;
> + *(p1 + 15) = _iat;
Isn't p1[14] = _rat better?
btw, if fill all 16 bytes here, there is no need for a memset(p1)
> +
> + /* p2 = padding || ia || ra */
> + memset(p2, 0, 16);
> + baswap(&addr, ia);
> + memcpy(p2 + 4, &addr, 6);
> + baswap(&addr, ra);
> + memcpy(p2 + 10, &addr, 6);
baswap(p2 + 4, ia) should have the same effect.
> + /* res = r XOR p1 */
> + u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
> +
> + /* res = e(k, res) */
> + err = smp_e(tfm, k, res);
> + if (err) {
> + BT_ERR("Encrypt data error");
> + return err;
> + }
> +
> + /* res = res XOR p2 */
> + u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
> +
> + /* res = e(k, res) */
> + err = smp_e(tfm, k, res);
> + if (err)
> + BT_ERR("Encrypt data error");
> +
> + return err;
> +}
> +
> +static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
> + u8 r1[16], u8 r2[16], u8 _r[16])
> +{
> + int err;
> +
> + /* Just least significant octets from r1 and r2 are considered */
> + memcpy(_r, r1 + 8, 8);
> + memcpy(_r + 8, r2 + 8, 8);
> +
> + err = smp_e(tfm, k, _r);
> + if (err)
> + BT_ERR("Encrypt data error");
> +
> + return err;
> +}
> +
> +static int smp_rand(u8 *buf)
This can be void.
> +{
> + get_random_bytes(buf, 16);
> +
> + return 0;
> +}
>
--
Gustavo F. Padovan
http://profusion.mobi
Hi Vin?cius,
* Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:54 -0300]:
> This patch implements a simple version of the SMP Pairing Features
> exchange procedure (Vol. 3 Part H, Section 2.3.5.1).
>
> For now, everything that would cause a Pairing Method different of
> Just Works to be chosen is rejected.
>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> net/bluetooth/hci_event.c | 1 +
> net/bluetooth/smp.c | 117 ++++++++++++++++++++++++--------------------
> 2 files changed, 65 insertions(+), 53 deletions(-)
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index aa0d013..e40ce9a 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1555,6 +1555,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
> /* Encryption implies authentication */
> conn->link_mode |= HCI_LM_AUTH;
> conn->link_mode |= HCI_LM_ENCRYPT;
> + conn->sec_level = conn->pending_sec_level;
> } else
> conn->link_mode &= ~HCI_LM_ENCRYPT;
> }
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 2724b70..b6f52ab 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -186,7 +186,30 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
> hci_send_acl(conn->hcon, skb, 0);
> }
>
> -static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> +static __u8 seclevel_to_authreq(__u8 level)
> +{
> + switch (level) {
> + case BT_SECURITY_HIGH:
> + /* Right now we don't support bonding */
> + return SMP_AUTH_MITM;
> +
> + default:
> + return SMP_AUTH_NONE;
> + }
> +}
> +
> +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->oob_flag = SMP_OOB_NOT_PRESENT;
> + cmd->max_key_size = 16;
> + cmd->init_key_dist = 0x00;
> + cmd->resp_key_dist = 0x00;
> + cmd->auth_req = authreq;
> +}
> +
Separate the creation of build_pairing_cmd() in a new commit.
--
Gustavo F. Padovan
http://profusion.mobi
Hi Vinicius,
* Vinicius Costa Gomes <[email protected]> [2011-04-05 22:51:49 -0300]:
> From: Anderson Briglia <[email protected]>
>
> Minor fix in smp_conn_security function.
>
> Signed-off-by: Anderson Briglia <[email protected]>
> Signed-off-by: Vinicius Costa Gomes <[email protected]>
> ---
> net/bluetooth/smp.c | 7 ++++---
> 1 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index fd9c3ff..f03513d 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -355,11 +355,12 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
>
> int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
> {
> + struct hci_conn *hcon = conn->hcon;
> __u8 authreq;
>
> - BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
> + BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
>
> - if (IS_ERR(conn->hcon->hdev->tfm))
> + if (IS_ERR(hcon->hdev->tfm))
Merge these changes in the commits that add this code for the first time,
patch 01 and others.
> return 1;
>
> switch (sec_level) {
> @@ -378,7 +379,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
> return 1;
> }
>
> - if (conn->hcon->link_mode & HCI_LM_MASTER) {
> + if (hcon->link_mode & HCI_LM_MASTER) {
Same here.
--
Gustavo F. Padovan
http://profusion.mobi