All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 0/9] SMP Implementation
@ 2010-12-06 21:43 Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 1/9] Bluetooth: Add SMP command structures Vinicius Costa Gomes
                   ` (8 more replies)
  0 siblings, 9 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

Hi,


Here goes just the SMP implementation (excluding Ville's LE patches).

Ville, I took the liberty of making the changes that Gustavo suggested to your
patches, the final result is here:

git://git.infradead.org/users/vcgomes/linux-2.6.git for-next

This tree is rebased on top of bluetooth-next.


Cheers
--

Anderson Briglia (3):
  Bluetooth: Start SMP procedure
  Bluetooth: simple SMP pairing negotiation
  Bluetooth: LE SMP Cryptoolbox functions

Ville Tervo (1):
  Bluetooth: Add SMP command structures

Vinicius Costa Gomes (5):
  Bluetooth: Implement the first SMP commands
  Bluetooth: Add support for using the crypto subsystem
  Bluetooth: Add support for SMP confirmation checks
  Bluetooth: Add support for LE Start Encryption
  Bluetooth: Add support for resuming socket when SMP is finished

 include/net/bluetooth/hci.h             |   34 +++
 include/net/bluetooth/hci_core.h        |    7 +
 include/net/bluetooth/l2cap.h           |    5 +
 include/net/bluetooth/smp.h             |   80 ++++++
 net/bluetooth/Makefile                  |    1 +
 net/bluetooth/hci_conn.c                |   47 +++
 net/bluetooth/hci_core.c                |   10 +
 net/bluetooth/hci_event.c               |   67 +++++
 net/bluetooth/{l2cap.c => l2cap_core.c} |   78 ++++--
 net/bluetooth/smp.c                     |  469 +++++++++++++++++++++++++++++++
 10 files changed, 769 insertions(+), 29 deletions(-)
 create mode 100644 include/net/bluetooth/smp.h
 rename net/bluetooth/{l2cap.c => l2cap_core.c} (99%)
 create mode 100644 net/bluetooth/smp.c

-- 
1.7.3.2


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [RFC v2 1/9] Bluetooth: Add SMP command structures
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 2/9] Bluetooth: Implement the first SMP commands Vinicius Costa Gomes
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ville Tervo

From: Ville Tervo <ville.tervo@nokia.com>

Add command structures for security manager protocol.

Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
 include/net/bluetooth/smp.h |   76 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)
 create mode 100644 include/net/bluetooth/smp.h

diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
new file mode 100644
index 0000000..8f2edbf
--- /dev/null
+++ b/include/net/bluetooth/smp.h
@@ -0,0 +1,76 @@
+#ifndef __SMP_H
+#define __SMP_H
+
+struct smp_command_hdr {
+	__u8	code;
+} __packed;
+
+#define SMP_CMD_PAIRING_REQ	0x01
+#define SMP_CMD_PAIRING_RSP	0x02
+struct smp_cmd_pairing {
+	__u8	io_capability;
+	__u8	oob_flag;
+	__u8	auth_req;
+	__u8	max_key_size;
+	__u8	init_key_dist;
+	__u8	resp_key_dist;
+} __packed;
+
+#define SMP_CMD_PAIRING_CONFIRM	0x03
+struct smp_cmd_pairing_confirm {
+	__u8	confirm_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_RANDOM	0x04
+struct smp_cmd_pairing_random {
+	__u8	rand_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_FAIL	0x05
+struct smp_cmd_pairing_fail {
+	__u8	reason;
+} __packed;
+
+#define SMP_CMD_ENCRYPT_INFO	0x06
+struct smp_cmd_encrypt_info {
+	__u8	ltk[16];
+} __packed;
+
+#define SMP_CMD_MASTER_IDENT	0x07
+struct smp_cmd_master_ident {
+	__u16	ediv;
+	__u8	rand[8];
+} __packed;
+
+#define SMP_CMD_IDENT_INFO	0x08
+struct smp_cmd_ident_info {
+	__u8	irk[16];
+} __packed;
+
+#define SMP_CMD_IDENT_ADDR_INFO	0x09
+struct smp_cmd_ident_addr_info {
+	__u8	addr_type;
+	bdaddr_t bdaddr;
+} __packed;
+
+#define SMP_CMD_SIGN_INFO	0x0a
+struct smp_cmd_sign_info {
+	__u8	csrk[16];
+} __packed;
+
+#define SMP_CMD_SECURITY_REQ	0x0b
+struct smp_cmd_security_req {
+	__u8	auth_req;
+} __packed;
+
+#define SMP_PASSKEY_ENTRY_FAILED	0x01
+#define SMP_OOB_NOT_AVAIL		0x02
+#define SMP_AUTH_REQUIREMENTS		0x03
+#define SMP_CONFIRM_FAILED		0x04
+#define SMP_PAIRING_NOTSUPP		0x05
+#define SMP_ENC_KEY_SIZE		0x06
+#define SMP_CMD_NOTSUPP		0x07
+#define SMP_UNSPECIFIED		0x08
+#define SMP_REPEATED_ATTEMPTS		0x09
+
+#endif /* __SMP_H */
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 2/9] Bluetooth: Implement the first SMP commands
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 1/9] Bluetooth: Add SMP command structures Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-07 16:03   ` Gustavo F. Padovan
  2010-12-07 16:10   ` Gustavo F. Padovan
  2010-12-06 21:43 ` [RFC v2 3/9] Bluetooth: Start SMP procedure Vinicius Costa Gomes
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes, Anderson Briglia

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 <vinicius.gomes@openbossa.org>
Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/smp.h             |    4 +
 net/bluetooth/Makefile                  |    1 +
 net/bluetooth/{l2cap.c => l2cap_core.c} |    0
 net/bluetooth/smp.c                     |  144 +++++++++++++++++++++++++++++++
 4 files changed, 149 insertions(+), 0 deletions(-)
 rename net/bluetooth/{l2cap.c => l2cap_core.c} (100%)
 create mode 100644 net/bluetooth/smp.c

diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 8f2edbf..b9603cc 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -73,4 +73,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 d1e433f..d138b23 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
 obj-$(CONFIG_BT_HIDP)	+= hidp/
 
 bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
+l2cap-objs := l2cap_core.o smp.o
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap_core.c
similarity index 100%
rename from net/bluetooth/l2cap.c
rename to net/bluetooth/l2cap_core.c
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644
index 0000000..e427d11
--- /dev/null
+++ b/net/bluetooth/smp.c
@@ -0,0 +1,144 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2010 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 + 1 + 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(1 + dlen);
+	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+	memcpy(skb_put(skb, 1), &code, 1);
+
+	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 = 0x01;
+		break;
+
+	case BT_SECURITY_HIGH:
+		/* Bonding, MITM protection */
+		authreq = 0x05;
+		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, 1);
+
+	switch (code) {
+	case SMP_CMD_PAIRING_REQ:
+		reason = SMP_PAIRING_NOTSUPP;
+		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, 1, &reason);
+		err = -1;
+		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, 1, &reason);
+		err = -1;
+	}
+
+	kfree_skb(skb);
+	return err;
+}
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 3/9] Bluetooth: Start SMP procedure
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 1/9] Bluetooth: Add SMP command structures Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 2/9] Bluetooth: Implement the first SMP commands Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-07 16:11   ` Gustavo F. Padovan
  2010-12-06 21:43 ` [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation Vinicius Costa Gomes
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes

From: Anderson Briglia <anderson.briglia@openbossa.org>

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 <vinicius.gomes@openbossa.org>
Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 net/bluetooth/l2cap_core.c |    7 +++++++
 net/bluetooth/smp.c        |    2 +-
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 69e5f80..674799c 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>
 
 #define VERSION "2.15"
 
@@ -642,6 +643,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 &&
@@ -4626,6 +4629,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 		l2cap_conless_channel(conn, psm, skb);
 		break;
 
+	case L2CAP_CID_SMP:
+		smp_sig_channel(conn, skb);
+		break;
+
 	default:
 		l2cap_data_channel(conn, cid, skb);
 		break;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e427d11..e9dde5f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -86,7 +86,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 		return 1;
 	}
 
-	if (conn->hcon->link_mode & HCI_LM_MASTER) {
+	if (conn->hcon->out) {
 		struct smp_cmd_pairing cp;
 		cp.io_capability = 0x00;
 		cp.oob_flag = 0x00;
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
                   ` (2 preceding siblings ...)
  2010-12-06 21:43 ` [RFC v2 3/9] Bluetooth: Start SMP procedure Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-07 16:39   ` Gustavo F. Padovan
  2010-12-07 18:26   ` Brian Gix
  2010-12-06 21:43 ` [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem Vinicius Costa Gomes
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes

From: Anderson Briglia <anderson.briglia@openbossa.org>

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 <vinicius.gomes@openbossa.org>
---
 net/bluetooth/l2cap_core.c |    3 +-
 net/bluetooth/smp.c        |  114 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 674799c..da4f13d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4630,7 +4630,8 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 		break;
 
 	case L2CAP_CID_SMP:
-		smp_sig_channel(conn, skb);
+		if (smp_sig_channel(conn, skb))
+			l2cap_conn_del(conn->hcon, 0x05);
 		break;
 
 	default:
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e9dde5f..b25010f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -64,6 +64,102 @@ 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("");
+
+	skb_pull(skb, sizeof(struct smp_cmd_pairing));
+
+	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 &= 0x05;
+
+	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("");
+
+	memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
+
+	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("");
+
+	if (conn->hcon->out) {
+		struct smp_cmd_pairing_random random;
+
+		BT_DBG("master");
+
+		memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
+								&random);
+	} else {
+		struct smp_cmd_pairing_confirm confirm;
+
+		BT_DBG("slave");
+
+		memset(&confirm, 0, sizeof(struct smp_cmd_pairing_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("");
+
+	skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
+
+	/* FIXME: check if random matches */
+
+	if (conn->hcon->out) {
+		BT_DBG("master");
+		/* FIXME: start encryption */
+	} else {
+		BT_DBG("slave");
+
+		memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
+
+		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("");
+
+	skb_pull(skb, sizeof(struct smp_cmd_security_req));
+	memset(&cp, 0, sizeof(struct smp_cmd_pairing));
+
+	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 & 0x05;
+
+	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,23 +210,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, 1, &reason);
-		err = -1;
+		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.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
                   ` (3 preceding siblings ...)
  2010-12-06 21:43 ` [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-07 17:27   ` Gustavo F. Padovan
  2010-12-07 18:35   ` Brian Gix
  2010-12-06 21:43 ` [RFC v2 6/9] Bluetooth: LE SMP Cryptoolbox functions Vinicius Costa Gomes
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

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.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |    2 ++
 net/bluetooth/hci_core.c         |   10 ++++++++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 0687e2f..d0a9f5d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -135,6 +135,8 @@ struct hci_dev {
 	__u32			req_status;
 	__u32			req_result;
 
+	struct crypto_blkcipher	*tfm;
+
 	struct inquiry_cache	inq_cache;
 	struct hci_conn_hash	conn_hash;
 	struct list_head	blacklist;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 12c6735..b96c3dd 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/rfkill.h>
+#include <linux/crypto.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
 	if (!hdev->workqueue)
 		goto nomem;
 
+	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hdev->tfm)) {
+		BT_ERR("Failed to load transform for ecb(aes): %ld",
+							PTR_ERR(hdev->tfm));
+		goto nomem;
+	}
+
 	hci_register_sysfs(hdev);
 
 	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -1001,6 +1009,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
 	for (i = 0; i < NUM_REASSEMBLY; i++)
 		kfree_skb(hdev->reassembly[i]);
 
+	crypto_free_blkcipher(hdev->tfm);
+
 	hci_notify(hdev, HCI_DEV_UNREG);
 
 	if (hdev->rfkill) {
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 6/9] Bluetooth: LE SMP Cryptoolbox functions
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
                   ` (4 preceding siblings ...)
  2010-12-06 21:43 ` [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks Vinicius Costa Gomes
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Anderson Briglia, Anderson Lizardo, Bruna Moreira, Vinicius Costa Gomes

From: Anderson Briglia <anderson.briglia@openbossa.org>

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 <anderson.briglia@openbossa.org>
Signed-off-by: Anderson Lizardo <anderson.lizardo@openbossa.org>
Signed-off-by: Bruna Moreira <bruna.moreira@openbossa.org>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 net/bluetooth/smp.c |  133 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b25010f..b62160e 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -24,6 +24,139 @@
 #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);
+		err = -1;
+		goto out;
+	}
+
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	err = crypto_blkcipher_setkey(tfm, k, 16);
+	if (err) {
+		BT_ERR("cipher setkey failed: %d", err);
+		goto out;
+	}
+
+	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);
+
+out:
+	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");
+		goto out;
+	}
+
+	/* 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");
+		goto out;
+	}
+
+out:
+	return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
+			u8 r1[16], u8 r2[16], u8 _r[16])
+{
+	u8 r[16];
+	int err;
+
+	/* Just least significant octets from r1 and r2 are considered */
+	swap128(r1, r);
+	memcpy(_r, r + 8, 8);
+	swap128(r2, r);
+	memcpy(_r + 8, r + 8, 8);
+
+	err = smp_e(tfm, k, _r);
+	if (err) {
+		BT_ERR("smp_s1: Encrypt data error");
+		goto out;
+	}
+
+out:
+	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.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
                   ` (5 preceding siblings ...)
  2010-12-06 21:43 ` [RFC v2 6/9] Bluetooth: LE SMP Cryptoolbox functions Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-07 17:41   ` Gustavo F. Padovan
                     ` (2 more replies)
  2010-12-06 21:43 ` [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption Vinicius Costa Gomes
  2010-12-06 21:43 ` [RFC v2 9/9] Bluetooth: Add support for resuming socket when SMP is finished Vinicius Costa Gomes
  8 siblings, 3 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

This adds supports for verifying the confirmation value that the
remote side has sent. This includes support for generating and sending
the random value used to produce the confirmation value.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/l2cap.h |    5 ++
 net/bluetooth/smp.c           |  121 ++++++++++++++++++++++++++++++++---------
 2 files changed, 101 insertions(+), 25 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index a3cb1ab..bcda2aa 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -290,6 +290,11 @@ struct l2cap_conn {
 
 	__u8		disc_reason;
 
+	__u8		preq[7];
+	__u8		pres[7];
+	__u8		prnd[16];
+	__u8		pcnf[16];
+
 	struct l2cap_chan_list chan_list;
 };
 
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b62160e..7d7e8ad 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -203,7 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	BT_DBG("");
 
-	skb_pull(skb, sizeof(struct smp_cmd_pairing));
+	conn->preq[0] = SMP_CMD_PAIRING_REQ;
+	memcpy(&conn->preq[1], rp, sizeof(*rp));
+	skb_pull(skb, sizeof(*rp));
 
 	rp->io_capability = 0x00;
 	rp->oob_flag = 0x00;
@@ -212,64 +214,125 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 	rp->resp_key_dist = 0x00;
 	rp->auth_req &= 0x05;
 
+	conn->pres[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&conn->pres[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;
+	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+	int ret;
+	u8 k[16], res[16];
 
-	BT_DBG("");
+	/* Just Works */
+	memset(k, 0, sizeof(k));
+
+	conn->pres[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&conn->pres[1], rp, sizeof(*rp));
+	skb_pull(skb, sizeof(*rp));
+
+	ret = smp_rand(conn->prnd);
+	if (ret)
+		return;
 
-	memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
+	ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 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("");
 
-	if (conn->hcon->out) {
-		struct smp_cmd_pairing_random random;
+	memcpy(conn->pcnf, skb->data, 16);
+	skb_pull(skb, 16);
 
-		BT_DBG("master");
+	if (conn->hcon->out) {
+		u8 random[16];
 
-		memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
+		swap128(conn->prnd, random);
 
-		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
-								&random);
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, random);
 	} else {
-		struct smp_cmd_pairing_confirm confirm;
+		struct smp_cmd_pairing_confirm cp;
+		int ret;
+		u8 k[16], res[16];
+
+		/* Just Works */
+		memset(k, 0, sizeof(k));
 
-		BT_DBG("slave");
+		ret = smp_rand(conn->prnd);
+		if (ret)
+			return;
 
-		memset(&confirm, 0, sizeof(struct smp_cmd_pairing_confirm));
+		ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,
+				conn->dst, 0, conn->src, res);
+		if (ret)
+			return;
 
-		smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
-								&confirm);
+		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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
+
+	swap128(skb->data, random);
+	skb_pull(skb, 16);
+
+	memset(k, 0, sizeof(k));
+
+	if (conn->hcon->out)
+		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
+				conn->src, 0, conn->dst, res);
+	else
+		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
+				conn->dst, 0, conn->src, res);
+	if (ret)
+		return;
 
-	BT_DBG("");
+	swap128(res, confirm);
 
-	skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
+	if (memcmp(conn->pcnf, confirm, 16) != 0) {
+		struct smp_cmd_pairing_fail cp;
 
-	/* FIXME: check if random matches */
+		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) {
-		BT_DBG("master");
-		/* FIXME: start encryption */
+		smp_s1(tfm, k, random, conn->prnd, key);
+
+		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
+		BT_DBG("key %s", buf);
 	} else {
-		BT_DBG("slave");
+		u8 r[16];
 
-		memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
+		swap128(conn->prnd, r);
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
 
-		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
+		smp_s1(tfm, k, conn->prnd, random, key);
+
+		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
+		BT_DBG("key %s", buf);
 	}
 }
 
@@ -280,8 +343,9 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	BT_DBG("");
 
-	skb_pull(skb, sizeof(struct smp_cmd_security_req));
-	memset(&cp, 0, sizeof(struct smp_cmd_pairing));
+	skb_pull(skb, sizeof(*rp));
+
+	memset(&cp, 0, sizeof(cp));
 
 	cp.io_capability = 0x00;
 	cp.oob_flag = 0x00;
@@ -290,6 +354,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 & 0x05;
 
+	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);
 }
 
@@ -323,6 +390,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.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
                   ` (6 preceding siblings ...)
  2010-12-06 21:43 ` [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  2010-12-07 17:38   ` Gustavo F. Padovan
  2010-12-07 18:58   ` Brian Gix
  2010-12-06 21:43 ` [RFC v2 9/9] Bluetooth: Add support for resuming socket when SMP is finished Vinicius Costa Gomes
  8 siblings, 2 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

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 <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/hci.h      |   34 +++++++++++++++++++
 include/net/bluetooth/hci_core.h |    5 +++
 net/bluetooth/hci_conn.c         |   47 ++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |   67 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/smp.c              |    8 ++++-
 5 files changed, 160 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index dff6ded..e6bed3f 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -626,6 +626,33 @@ struct hci_cp_le_create_conn {
 
 #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
 
+#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
 
@@ -897,6 +924,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 d0a9f5d..c6c44eb 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -192,6 +192,7 @@ struct hci_conn {
 	__u8             sec_level;
 	__u8             power_save;
 	__u16            disc_timeout;
+	__u8		 ltk[16];
 	unsigned long	 pend;
 
 	unsigned int	 sent;
@@ -713,4 +714,8 @@ struct hci_sec_filter {
 
 void hci_req_complete(struct hci_dev *hdev, int result);
 
+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 edfb48b..f919ddb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -183,6 +183,53 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
 
+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, 16);
+
+	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);
+}
+EXPORT_SYMBOL(hci_le_ltk_neg_reply);
+
 /* 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 55cdd6a..c90696f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -559,6 +559,30 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 	hci_req_complete(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, 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, rp->status);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%x", hdev->name, status);
@@ -920,6 +944,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);
@@ -1440,6 +1469,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;
@@ -1510,6 +1547,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;
@@ -2013,6 +2054,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;
@@ -2024,6 +2087,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 7d7e8ad..d19b8a2 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -289,7 +289,8 @@ 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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
 
@@ -297,6 +298,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 	skb_pull(skb, 16);
 
 	memset(k, 0, sizeof(k));
+	memset(hcon->ltk, 0, sizeof(hcon->ltk));
 
 	if (conn->hcon->out)
 		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
@@ -320,6 +322,9 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	if (conn->hcon->out) {
 		smp_s1(tfm, k, random, conn->prnd, key);
+		swap128(key, hcon->ltk);
+
+		hci_le_start_enc(conn->hcon, hcon->ltk);
 
 		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
 		BT_DBG("key %s", buf);
@@ -330,6 +335,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
 
 		smp_s1(tfm, k, 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.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC v2 9/9] Bluetooth: Add support for resuming socket when SMP is finished
  2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
                   ` (7 preceding siblings ...)
  2010-12-06 21:43 ` [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption Vinicius Costa Gomes
@ 2010-12-06 21:43 ` Vinicius Costa Gomes
  8 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-06 21:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

This adds support for resuming the user space traffic when SMP
negotiation is complete.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 net/bluetooth/l2cap_core.c |   72 +++++++++++++++++++++++++------------------
 net/bluetooth/smp.c        |    9 +++++
 2 files changed, 51 insertions(+), 30 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index da4f13d..061248f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -624,6 +624,22 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 	}
 }
 
+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;
@@ -640,14 +656,10 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 		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 (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;
@@ -1199,7 +1211,7 @@ static int l2cap_do_connect(struct sock *sk)
 				sk->sk_type != SOCK_STREAM) {
 			l2cap_sock_clear_timer(sk);
 			sk->sk_state = BT_CONNECTED;
-		} else
+		} else if (hcon->type == ACL_LINK)
 			l2cap_do_start(sk);
 	}
 
@@ -2162,6 +2174,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;
 
@@ -2198,6 +2211,18 @@ 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 && conn->hcon->type == LE_LINK) {
+			if (!conn->hcon->out) {
+				err = -EINVAL;
+				break;
+			}
+
+			sk->sk_state = BT_CONFIG;
+			smp_conn_security(conn, sec.level);
+		}
+
 		break;
 
 	case BT_DEFER_SETUP:
@@ -2410,29 +2435,6 @@ static int l2cap_sock_release(struct socket *sock)
 	return err;
 }
 
-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)
 {
@@ -4753,6 +4755,16 @@ 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);
 
+		if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
+			if (!status && encrypt) {
+				l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
+				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/smp.c b/net/bluetooth/smp.c
index d19b8a2..c7a0e63 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -346,9 +346,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("");
 
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+		return;
+
 	skb_pull(skb, sizeof(*rp));
 
 	memset(&cp, 0, sizeof(cp));
@@ -364,10 +368,13 @@ 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);
 }
 
 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);
@@ -407,6 +414,8 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
 	}
 
+	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
 	return 0;
 }
 
-- 
1.7.3.2


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [RFC v2 2/9] Bluetooth: Implement the first SMP commands
  2010-12-06 21:43 ` [RFC v2 2/9] Bluetooth: Implement the first SMP commands Vinicius Costa Gomes
@ 2010-12-07 16:03   ` Gustavo F. Padovan
  2010-12-07 22:05     ` Vinicius Costa Gomes
  2010-12-07 16:10   ` Gustavo F. Padovan
  1 sibling, 1 reply; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 16:03 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Anderson Briglia

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:45 -0300]:

> 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 <vinicius.gomes@openbossa.org>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> ---
>  include/net/bluetooth/smp.h             |    4 +
>  net/bluetooth/Makefile                  |    1 +
>  net/bluetooth/{l2cap.c => l2cap_core.c} |    0

I want a separated patch for the l2cap.c rename.

>  net/bluetooth/smp.c                     |  144 +++++++++++++++++++++++++++++++
>  4 files changed, 149 insertions(+), 0 deletions(-)
>  rename net/bluetooth/{l2cap.c => l2cap_core.c} (100%)
>  create mode 100644 net/bluetooth/smp.c
> 
> diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
> index 8f2edbf..b9603cc 100644
> --- a/include/net/bluetooth/smp.h
> +++ b/include/net/bluetooth/smp.h
> @@ -73,4 +73,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 d1e433f..d138b23 100644
> --- a/net/bluetooth/Makefile
> +++ b/net/bluetooth/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
>  obj-$(CONFIG_BT_HIDP)	+= hidp/
>  
>  bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
> +l2cap-objs := l2cap_core.o smp.o
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap_core.c
> similarity index 100%
> rename from net/bluetooth/l2cap.c
> rename to net/bluetooth/l2cap_core.c
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> new file mode 100644
> index 0000000..e427d11
> --- /dev/null
> +++ b/net/bluetooth/smp.c
> @@ -0,0 +1,144 @@
> +/*
> +   BlueZ - Bluetooth protocol stack for Linux
> +   Copyright (C) 2010 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 + 1 + 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(1 + dlen);
> +	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
> +
> +	memcpy(skb_put(skb, 1), &code, 1);
> +
> +	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 = 0x01;
> +		break;
> +
> +	case BT_SECURITY_HIGH:
> +		/* Bonding, MITM protection */
> +		authreq = 0x05;
> +		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, 1);
> +
> +	switch (code) {
> +	case SMP_CMD_PAIRING_REQ:
> +		reason = SMP_PAIRING_NOTSUPP;
> +		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, 1, &reason);
> +		err = -1;

Don't use -1, use a proper error macro here.

> +		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, 1, &reason);
> +		err = -1;

Same here.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 2/9] Bluetooth: Implement the first SMP commands
  2010-12-06 21:43 ` [RFC v2 2/9] Bluetooth: Implement the first SMP commands Vinicius Costa Gomes
  2010-12-07 16:03   ` Gustavo F. Padovan
@ 2010-12-07 16:10   ` Gustavo F. Padovan
  2010-12-07 22:06     ` Vinicius Costa Gomes
  1 sibling, 1 reply; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 16:10 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Anderson Briglia

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:45 -0300]:

> 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 <vinicius.gomes@openbossa.org>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> ---
>  include/net/bluetooth/smp.h             |    4 +
>  net/bluetooth/Makefile                  |    1 +
>  net/bluetooth/{l2cap.c => l2cap_core.c} |    0
>  net/bluetooth/smp.c                     |  144 +++++++++++++++++++++++++++++++
>  4 files changed, 149 insertions(+), 0 deletions(-)
>  rename net/bluetooth/{l2cap.c => l2cap_core.c} (100%)
>  create mode 100644 net/bluetooth/smp.c
> 
> diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
> index 8f2edbf..b9603cc 100644
> --- a/include/net/bluetooth/smp.h
> +++ b/include/net/bluetooth/smp.h
> @@ -73,4 +73,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 d1e433f..d138b23 100644
> --- a/net/bluetooth/Makefile
> +++ b/net/bluetooth/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
>  obj-$(CONFIG_BT_HIDP)	+= hidp/
>  
>  bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
> +l2cap-objs := l2cap_core.o smp.o
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap_core.c
> similarity index 100%
> rename from net/bluetooth/l2cap.c
> rename to net/bluetooth/l2cap_core.c
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> new file mode 100644
> index 0000000..e427d11
> --- /dev/null
> +++ b/net/bluetooth/smp.c
> @@ -0,0 +1,144 @@
> +/*
> +   BlueZ - Bluetooth protocol stack for Linux
> +   Copyright (C) 2010 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 + 1 + 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(1 + dlen);
> +	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
> +
> +	memcpy(skb_put(skb, 1), &code, 1);
> +
> +	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 = 0x01;
> +		break;
> +
> +	case BT_SECURITY_HIGH:
> +		/* Bonding, MITM protection */
> +		authreq = 0x05;

It would be good have some defines for the authreq values.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 3/9] Bluetooth: Start SMP procedure
  2010-12-06 21:43 ` [RFC v2 3/9] Bluetooth: Start SMP procedure Vinicius Costa Gomes
@ 2010-12-07 16:11   ` Gustavo F. Padovan
  2010-12-07 22:08     ` Vinicius Costa Gomes
  0 siblings, 1 reply; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 16:11 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Anderson Briglia

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:46 -0300]:

> From: Anderson Briglia <anderson.briglia@openbossa.org>
> 
> 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 <vinicius.gomes@openbossa.org>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> ---
>  net/bluetooth/l2cap_core.c |    7 +++++++
>  net/bluetooth/smp.c        |    2 +-
>  2 files changed, 8 insertions(+), 1 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 69e5f80..674799c 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>
>  
>  #define VERSION "2.15"
>  
> @@ -642,6 +643,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 &&
> @@ -4626,6 +4629,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
>  		l2cap_conless_channel(conn, psm, skb);
>  		break;
>  
> +	case L2CAP_CID_SMP:
> +		smp_sig_channel(conn, skb);
> +		break;
> +
>  	default:
>  		l2cap_data_channel(conn, cid, skb);
>  		break;
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index e427d11..e9dde5f 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -86,7 +86,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
>  		return 1;
>  	}
>  
> -	if (conn->hcon->link_mode & HCI_LM_MASTER) {
> +	if (conn->hcon->out) {

This change should not belong to this patch.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation
  2010-12-06 21:43 ` [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation Vinicius Costa Gomes
@ 2010-12-07 16:39   ` Gustavo F. Padovan
  2010-12-07 18:26   ` Brian Gix
  1 sibling, 0 replies; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 16:39 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Anderson Briglia

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:47 -0300]:

> From: Anderson Briglia <anderson.briglia@openbossa.org>
> 
> 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 <vinicius.gomes@openbossa.org>
> ---
>  net/bluetooth/l2cap_core.c |    3 +-
>  net/bluetooth/smp.c        |  114 ++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 112 insertions(+), 5 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 674799c..da4f13d 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -4630,7 +4630,8 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
>  		break;
>  
>  	case L2CAP_CID_SMP:
> -		smp_sig_channel(conn, skb);
> +		if (smp_sig_channel(conn, skb))
> +			l2cap_conn_del(conn->hcon, 0x05);

So this could be in the previous patch instead of this one.

>  		break;
>  
>  	default:
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index e9dde5f..b25010f 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -64,6 +64,102 @@ 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("");

BT_DBG("conn %p", conn); is better. Same for the other functions below.

> +
> +	skb_pull(skb, sizeof(struct smp_cmd_pairing));
> +
> +	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 &= 0x05;
> +
> +	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("");
> +
> +	memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
> +
> +	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("");

	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 

Is better, no?

> +
> +	if (conn->hcon->out) {
> +		struct smp_cmd_pairing_random random;
> +
> +		BT_DBG("master");
> +
> +		memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
> +
> +		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
> +								&random);
> +	} else {
> +		struct smp_cmd_pairing_confirm confirm;
> +
> +		BT_DBG("slave");
> +
> +		memset(&confirm, 0, sizeof(struct smp_cmd_pairing_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("");
> +
> +	skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
> +
> +	/* FIXME: check if random matches */
> +
> +	if (conn->hcon->out) {
> +		BT_DBG("master");
> +		/* FIXME: start encryption */
> +	} else {
> +		BT_DBG("slave");
> +
> +		memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
> +
> +		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("");
> +
> +	skb_pull(skb, sizeof(struct smp_cmd_security_req));
> +	memset(&cp, 0, sizeof(struct smp_cmd_pairing));
> +
> +	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 & 0x05;
> +
> +	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,23 +210,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, 1, &reason);
> -		err = -1;
> +		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.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-06 21:43 ` [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem Vinicius Costa Gomes
@ 2010-12-07 17:27   ` Gustavo F. Padovan
  2010-12-07 17:51     ` Vinicius Costa Gomes
  2010-12-07 18:35   ` Brian Gix
  1 sibling, 1 reply; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 17:27 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:48 -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.
> 
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/hci_core.h |    2 ++
>  net/bluetooth/hci_core.c         |   10 ++++++++++
>  2 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 0687e2f..d0a9f5d 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -135,6 +135,8 @@ struct hci_dev {
>  	__u32			req_status;
>  	__u32			req_result;
>  
> +	struct crypto_blkcipher	*tfm;
> +
>  	struct inquiry_cache	inq_cache;
>  	struct hci_conn_hash	conn_hash;
>  	struct list_head	blacklist;
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 12c6735..b96c3dd 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -41,6 +41,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/notifier.h>
>  #include <linux/rfkill.h>
> +#include <linux/crypto.h>
>  #include <net/sock.h>
>  
>  #include <asm/system.h>
> @@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
>  	if (!hdev->workqueue)
>  		goto nomem;
>  
> +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hdev->tfm)) {
> +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> +							PTR_ERR(hdev->tfm));
> +		goto nomem;

You are leaking hdev->workqueue here.

Also you will need to add CRYPTO_BLKCIPHER dependence in the Kconfig.
Maybe we should add a CONFIG_BLUETOOTH_SMP, and just build with blkcipher
in the case SMP was selected to be built.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption
  2010-12-06 21:43 ` [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption Vinicius Costa Gomes
@ 2010-12-07 17:38   ` Gustavo F. Padovan
  2010-12-07 18:58   ` Brian Gix
  1 sibling, 0 replies; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 17:38 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:51 -0300]:

> 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 <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/hci.h      |   34 +++++++++++++++++++
>  include/net/bluetooth/hci_core.h |    5 +++
>  net/bluetooth/hci_conn.c         |   47 ++++++++++++++++++++++++++
>  net/bluetooth/hci_event.c        |   67 ++++++++++++++++++++++++++++++++++++++
>  net/bluetooth/smp.c              |    8 ++++-
>  5 files changed, 160 insertions(+), 1 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index dff6ded..e6bed3f 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -626,6 +626,33 @@ struct hci_cp_le_create_conn {
>  
>  #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
>  
> +#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
>  
> @@ -897,6 +924,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 d0a9f5d..c6c44eb 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -192,6 +192,7 @@ struct hci_conn {
>  	__u8             sec_level;
>  	__u8             power_save;
>  	__u16            disc_timeout;
> +	__u8		 ltk[16];
>  	unsigned long	 pend;
>  
>  	unsigned int	 sent;
> @@ -713,4 +714,8 @@ struct hci_sec_filter {
>  
>  void hci_req_complete(struct hci_dev *hdev, int result);
>  
> +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 edfb48b..f919ddb 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -183,6 +183,53 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
>  	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
>  }
>  
> +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, 16);
> +
> +	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);
> +}
> +EXPORT_SYMBOL(hci_le_ltk_neg_reply);
> +
>  /* 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 55cdd6a..c90696f 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -559,6 +559,30 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
>  	hci_req_complete(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, 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, rp->status);
> +}
> +
>  static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>  {
>  	BT_DBG("%s status 0x%x", hdev->name, status);
> @@ -920,6 +944,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);
> @@ -1440,6 +1469,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;
> @@ -1510,6 +1547,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;
> @@ -2013,6 +2054,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;
> @@ -2024,6 +2087,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 7d7e8ad..d19b8a2 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -289,7 +289,8 @@ 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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
>  
> @@ -297,6 +298,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
>  	skb_pull(skb, 16);
>  
>  	memset(k, 0, sizeof(k));
> +	memset(hcon->ltk, 0, sizeof(hcon->ltk));
>  
>  	if (conn->hcon->out)
>  		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> @@ -320,6 +322,9 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
>  
>  	if (conn->hcon->out) {
>  		smp_s1(tfm, k, random, conn->prnd, key);
> +		swap128(key, hcon->ltk);
> +
> +		hci_le_start_enc(conn->hcon, hcon->ltk);

You have hcon here, no need to use conn->hcon.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks
  2010-12-06 21:43 ` [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks Vinicius Costa Gomes
@ 2010-12-07 17:41   ` Gustavo F. Padovan
  2010-12-08  5:48   ` Koustuv Ghosh
  2010-12-08  6:19   ` Koustuv Ghosh
  2 siblings, 0 replies; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 17:41 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:50 -0300]:

> This adds supports for verifying the confirmation value that the
> remote side has sent. This includes support for generating and sending
> the random value used to produce the confirmation value.
> 
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>

Can this be split in more than one patch? I'm getting lost.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-07 17:27   ` Gustavo F. Padovan
@ 2010-12-07 17:51     ` Vinicius Costa Gomes
  2010-12-07 18:05       ` Gustavo F. Padovan
  0 siblings, 1 reply; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-07 17:51 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth

Hi Gustavo,

On 15:27 Tue 07 Dec, Gustavo F. Padovan wrote:
> Hi Vinicius,
> 
> * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:48 -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.
> > 
> > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> > ---
> >  include/net/bluetooth/hci_core.h |    2 ++
> >  net/bluetooth/hci_core.c         |   10 ++++++++++
> >  2 files changed, 12 insertions(+), 0 deletions(-)
> > 
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 0687e2f..d0a9f5d 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -135,6 +135,8 @@ struct hci_dev {
> >  	__u32			req_status;
> >  	__u32			req_result;
> >  
> > +	struct crypto_blkcipher	*tfm;
> > +
> >  	struct inquiry_cache	inq_cache;
> >  	struct hci_conn_hash	conn_hash;
> >  	struct list_head	blacklist;
> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > index 12c6735..b96c3dd 100644
> > --- a/net/bluetooth/hci_core.c
> > +++ b/net/bluetooth/hci_core.c
> > @@ -41,6 +41,7 @@
> >  #include <linux/interrupt.h>
> >  #include <linux/notifier.h>
> >  #include <linux/rfkill.h>
> > +#include <linux/crypto.h>
> >  #include <net/sock.h>
> >  
> >  #include <asm/system.h>
> > @@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
> >  	if (!hdev->workqueue)
> >  		goto nomem;
> >  
> > +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hdev->tfm)) {
> > +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> > +							PTR_ERR(hdev->tfm));
> > +		goto nomem;
> 
> You are leaking hdev->workqueue here.

Thanks, see below.

> 
> Also you will need to add CRYPTO_BLKCIPHER dependence in the Kconfig.
> Maybe we should add a CONFIG_BLUETOOTH_SMP, and just build with blkcipher
> in the case SMP was selected to be built.

Sounds fair. Another alternative is: instead of not being able to register the 
HCI device if the blockcypher allocation fails, we could reply "Pairing Not
Supported" at the SMP level. We would just need to document somewhere that the
crypto subsystem and support for AES are needed for SMP to work.

What do you think?

> 
> -- 
> Gustavo F. Padovan
> http://profusion.mobi


Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-07 17:51     ` Vinicius Costa Gomes
@ 2010-12-07 18:05       ` Gustavo F. Padovan
  0 siblings, 0 replies; 33+ messages in thread
From: Gustavo F. Padovan @ 2010-12-07 18:05 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

Hi Vinicius,

* Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-07 14:51:17 -0300]:

> Hi Gustavo,
> 
> On 15:27 Tue 07 Dec, Gustavo F. Padovan wrote:
> > Hi Vinicius,
> > 
> > * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:48 -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.
> > > 
> > > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> > > ---
> > >  include/net/bluetooth/hci_core.h |    2 ++
> > >  net/bluetooth/hci_core.c         |   10 ++++++++++
> > >  2 files changed, 12 insertions(+), 0 deletions(-)
> > > 
> > > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > > index 0687e2f..d0a9f5d 100644
> > > --- a/include/net/bluetooth/hci_core.h
> > > +++ b/include/net/bluetooth/hci_core.h
> > > @@ -135,6 +135,8 @@ struct hci_dev {
> > >  	__u32			req_status;
> > >  	__u32			req_result;
> > >  
> > > +	struct crypto_blkcipher	*tfm;
> > > +
> > >  	struct inquiry_cache	inq_cache;
> > >  	struct hci_conn_hash	conn_hash;
> > >  	struct list_head	blacklist;
> > > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > index 12c6735..b96c3dd 100644
> > > --- a/net/bluetooth/hci_core.c
> > > +++ b/net/bluetooth/hci_core.c
> > > @@ -41,6 +41,7 @@
> > >  #include <linux/interrupt.h>
> > >  #include <linux/notifier.h>
> > >  #include <linux/rfkill.h>
> > > +#include <linux/crypto.h>
> > >  #include <net/sock.h>
> > >  
> > >  #include <asm/system.h>
> > > @@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
> > >  	if (!hdev->workqueue)
> > >  		goto nomem;
> > >  
> > > +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
> > > +	if (IS_ERR(hdev->tfm)) {
> > > +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> > > +							PTR_ERR(hdev->tfm));
> > > +		goto nomem;
> > 
> > You are leaking hdev->workqueue here.
> 
> Thanks, see below.
> 
> > 
> > Also you will need to add CRYPTO_BLKCIPHER dependence in the Kconfig.
> > Maybe we should add a CONFIG_BLUETOOTH_SMP, and just build with blkcipher
> > in the case SMP was selected to be built.
> 
> Sounds fair. Another alternative is: instead of not being able to register the 
> HCI device if the blockcypher allocation fails, we could reply "Pairing Not
> Supported" at the SMP level. We would just need to document somewhere that the
> crypto subsystem and support for AES are needed for SMP to work.
> 
> What do you think?

No, because the build will fail if we don't select CRYPTO_BLKCIPHER and
CRYPTO_AES. It that case you can add a #ifdef CONFIG_CRYTO... to avoid the
build failure and comment that you need to enable such features. But I think
that would be better to add an Kconfig option for SMP in this case instead of
document somewhere that we need to enable some other options in the kernel to
have SMP working.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation
  2010-12-06 21:43 ` [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation Vinicius Costa Gomes
  2010-12-07 16:39   ` Gustavo F. Padovan
@ 2010-12-07 18:26   ` Brian Gix
  2010-12-07 22:27     ` Vinicius Costa Gomes
  1 sibling, 1 reply; 33+ messages in thread
From: Brian Gix @ 2010-12-07 18:26 UTC (permalink / raw)
  To: 'Vinicius Costa Gomes', linux-bluetooth
  Cc: 'Anderson Briglia'



Hi Vinicius,

> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
> owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> Sent: 06 December, 2010 1:44 PM
> To: linux-bluetooth@vger.kernel.org
> Cc: Anderson Briglia; Vinicius Costa Gomes
> Subject: [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation
> 
> From: Anderson Briglia <anderson.briglia@openbossa.org>
> 
> 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 <vinicius.gomes@openbossa.org>
> ---
>  net/bluetooth/l2cap_core.c |    3 +-
>  net/bluetooth/smp.c        |  114
> ++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 112 insertions(+), 5 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 674799c..da4f13d 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -4630,7 +4630,8 @@ static void l2cap_recv_frame(struct l2cap_conn
> *conn, struct sk_buff *skb)
>  		break;
> 
>  	case L2CAP_CID_SMP:
> -		smp_sig_channel(conn, skb);
> +		if (smp_sig_channel(conn, skb))
> +			l2cap_conn_del(conn->hcon, 0x05);
>  		break;
> 
>  	default:
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index e9dde5f..b25010f 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -64,6 +64,102 @@ 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("");
> +
> +	skb_pull(skb, sizeof(struct smp_cmd_pairing));
> +
> +	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 &= 0x05;
> +
> +	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
> +}

As a "placeholder" I understand that there is a fair amount of fleshing
out that these changes need.  However, as you have an conn->hcon->out
flag that indicates direction (which hopefully is based on Link Master),
I would like to see checking in this function and next, that the
correct role has received these SMP packets, with a rejection if they
were received by the incorrect role. Also, although the placeholder is
requesting no key distribution, in the fleshed out version, the responder
should be returning the subset (logical AND) of the requesters and the
responders key_dist masks, which in this case is still of course Zero.

I'm sorry if this is to many comments for this starting point.

> +
> +static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct
> sk_buff *skb)
> +{
> +	struct smp_cmd_pairing_confirm cp;
> +
> +	BT_DBG("");
> +
> +	memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
> +
> +	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("");
> +
> +	if (conn->hcon->out) {
> +		struct smp_cmd_pairing_random random;
> +
> +		BT_DBG("master");
> +
> +		memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
> +
> +		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
> +								&random);
> +	} else {
> +		struct smp_cmd_pairing_confirm confirm;
> +
> +		BT_DBG("slave");
> +
> +		memset(&confirm, 0, sizeof(struct
> smp_cmd_pairing_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("");
> +
> +	skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
> +
> +	/* FIXME: check if random matches */

The random numbers will not match. The correct check will be that
when the encryption with p1, p2, k, and the remote's random number,
is performed, that it matches the confirm previously received
via smp_cmd_pairing_confirm.

> +
> +	if (conn->hcon->out) {
> +		BT_DBG("master");
> +		/* FIXME: start encryption */
> +	} else {
> +		BT_DBG("slave");
> +
> +		memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
> +
> +		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("");
> +
> +	skb_pull(skb, sizeof(struct smp_cmd_security_req));
> +	memset(&cp, 0, sizeof(struct smp_cmd_pairing));
> +
> +	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 & 0x05;
> +
> +	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
> +}
> +

This function may need to be overloaded, such that if an existing
set of keys already exist (from an earlier pairing) that they are
used by simply encrypting the link, or signing the WRITE_CMD pkt
as needed.  Should the link encryption fail due to remote rejection,
we might then request security, subject to the same limitations
used by BR/EDR's SSP. 

But I do not know where the division lies between the key storage dB,
the kernel mode code and the user mode code.


>  int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
>  {
>  	__u8 authreq;
> @@ -114,23 +210,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, 1, &reason);
> -		err = -1;
> +		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.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-06 21:43 ` [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem Vinicius Costa Gomes
  2010-12-07 17:27   ` Gustavo F. Padovan
@ 2010-12-07 18:35   ` Brian Gix
  2010-12-07 19:06     ` Anderson Lizardo
  2010-12-07 19:23     ` Vinicius Costa Gomes
  1 sibling, 2 replies; 33+ messages in thread
From: Brian Gix @ 2010-12-07 18:35 UTC (permalink / raw)
  To: 'Vinicius Costa Gomes', linux-bluetooth


Hi Vinicius,

> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
> owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> Sent: 06 December, 2010 1:44 PM
> To: linux-bluetooth@vger.kernel.org
> Cc: Vinicius Costa Gomes
> Subject: [RFC v2 5/9] Bluetooth: Add support for using the crypto
> subsystem
> 
> 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.

I do understand the desire to reuse the crypto module, but I would like
to point out that every baseband that supports any level of LE-SM, is
required to have implemented the HCI commands for LE-SM centric encryption
and random number generation.

Also, since these are processor intensive calculations, which must take
place in real-time on the baseband for encrypted links, I would argue
that it makes more sense to use the likely optimized functionality
present in the basebands.

That is not to say that it cannot be done on the host, just that it
is likely less efficient, for no gain in portability or functionality.

 
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/hci_core.h |    2 ++
>  net/bluetooth/hci_core.c         |   10 ++++++++++
>  2 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h
> b/include/net/bluetooth/hci_core.h
> index 0687e2f..d0a9f5d 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -135,6 +135,8 @@ struct hci_dev {
>  	__u32			req_status;
>  	__u32			req_result;
> 
> +	struct crypto_blkcipher	*tfm;
> +
>  	struct inquiry_cache	inq_cache;
>  	struct hci_conn_hash	conn_hash;
>  	struct list_head	blacklist;
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 12c6735..b96c3dd 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -41,6 +41,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/notifier.h>
>  #include <linux/rfkill.h>
> +#include <linux/crypto.h>
>  #include <net/sock.h>
> 
>  #include <asm/system.h>
> @@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
>  	if (!hdev->workqueue)
>  		goto nomem;
> 
> +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0,
> CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hdev->tfm)) {
> +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> +							PTR_ERR(hdev->tfm));
> +		goto nomem;
> +	}
> +
>  	hci_register_sysfs(hdev);
> 
>  	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> @@ -1001,6 +1009,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
>  	for (i = 0; i < NUM_REASSEMBLY; i++)
>  		kfree_skb(hdev->reassembly[i]);
> 
> +	crypto_free_blkcipher(hdev->tfm);
> +
>  	hci_notify(hdev, HCI_DEV_UNREG);
> 
>  	if (hdev->rfkill) {
> --
> 1.7.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption
  2010-12-06 21:43 ` [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption Vinicius Costa Gomes
  2010-12-07 17:38   ` Gustavo F. Padovan
@ 2010-12-07 18:58   ` Brian Gix
  1 sibling, 0 replies; 33+ messages in thread
From: Brian Gix @ 2010-12-07 18:58 UTC (permalink / raw)
  To: 'Vinicius Costa Gomes', linux-bluetooth



Hi Vinicius,


> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
> owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> Sent: 06 December, 2010 1:44 PM
> To: linux-bluetooth@vger.kernel.org
> Cc: Vinicius Costa Gomes
> Subject: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption
> 
> 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 <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/hci.h      |   34 +++++++++++++++++++
>  include/net/bluetooth/hci_core.h |    5 +++
>  net/bluetooth/hci_conn.c         |   47 ++++++++++++++++++++++++++
>  net/bluetooth/hci_event.c        |   67
> ++++++++++++++++++++++++++++++++++++++
>  net/bluetooth/smp.c              |    8 ++++-
>  5 files changed, 160 insertions(+), 1 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index dff6ded..e6bed3f 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -626,6 +626,33 @@ struct hci_cp_le_create_conn {
> 
>  #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
> 
> +#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
> 
> @@ -897,6 +924,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 d0a9f5d..c6c44eb 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -192,6 +192,7 @@ struct hci_conn {
>  	__u8             sec_level;
>  	__u8             power_save;
>  	__u16            disc_timeout;
> +	__u8		 ltk[16];
>  	unsigned long	 pend;
> 
>  	unsigned int	 sent;
> @@ -713,4 +714,8 @@ struct hci_sec_filter {
> 
>  void hci_req_complete(struct hci_dev *hdev, int result);
> 
> +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 edfb48b..f919ddb 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -183,6 +183,53 @@ void hci_setup_sync(struct hci_conn *conn, __u16
> handle)
>  	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
>  }
> 
> +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, 16);
> +
> +	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
> +}
> +EXPORT_SYMBOL(hci_le_start_enc);


This appears only useful for link encryption with the STK, as both the ediv
random values are Zero.  If this is how it was intended, the OK, however
it may be more appropriate in smp.c

> +
> +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);
> +}
> +EXPORT_SYMBOL(hci_le_ltk_neg_reply);
> +
>  /* 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 55cdd6a..c90696f 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -559,6 +559,30 @@ static void hci_cc_le_read_buffer_size(struct
> hci_dev *hdev,
>  	hci_req_complete(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, 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, rp->status);
> +}
> +
>  static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>  {
>  	BT_DBG("%s status 0x%x", hdev->name, status);
> @@ -920,6 +944,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);
> @@ -1440,6 +1469,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;
> @@ -1510,6 +1547,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;
> @@ -2013,6 +2054,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);
> +}

Same basic problem here, except ediv and random should be checked
for all Zeros, in which case it should be considered an STK request
and rejected unless part of an intended SM Pairing procedure. If
they are not zero, then they are the values that should be used to
look up the LTK for the LTK_REPLY, because the BD ADDR of the remote
device may have changed since the last time it was connected.

> +
>  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;
> @@ -2024,6 +2087,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 7d7e8ad..d19b8a2 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -289,7 +289,8 @@ 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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
> 
> @@ -297,6 +298,7 @@ static void smp_cmd_pairing_random(struct
> l2cap_conn *conn, struct sk_buff *skb)
>  	skb_pull(skb, 16);
> 
>  	memset(k, 0, sizeof(k));
> +	memset(hcon->ltk, 0, sizeof(hcon->ltk));
> 
>  	if (conn->hcon->out)
>  		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> @@ -320,6 +322,9 @@ static void smp_cmd_pairing_random(struct
> l2cap_conn *conn, struct sk_buff *skb)
> 
>  	if (conn->hcon->out) {
>  		smp_s1(tfm, k, random, conn->prnd, key);
> +		swap128(key, hcon->ltk);
> +
> +		hci_le_start_enc(conn->hcon, hcon->ltk);
> 
>  		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
> sizeof(buf), 0);
>  		BT_DBG("key %s", buf);
> @@ -330,6 +335,7 @@ static void smp_cmd_pairing_random(struct
> l2cap_conn *conn, struct sk_buff *skb)
>  		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
> 
>  		smp_s1(tfm, k, 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.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-07 18:35   ` Brian Gix
@ 2010-12-07 19:06     ` Anderson Lizardo
  2010-12-07 19:21       ` Brian Gix
  2010-12-07 19:23     ` Vinicius Costa Gomes
  1 sibling, 1 reply; 33+ messages in thread
From: Anderson Lizardo @ 2010-12-07 19:06 UTC (permalink / raw)
  To: Brian Gix; +Cc: Vinicius Costa Gomes, linux-bluetooth

Hi,

On Tue, Dec 7, 2010 at 2:35 PM, Brian Gix <bgix@codeaurora.org> wrote:
>> 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.
>
> I do understand the desire to reuse the crypto module, but I would like
> to point out that every baseband that supports any level of LE-SM, is
> required to have implemented the HCI commands for LE-SM centric encryption
> and random number generation.

Correct.

> Also, since these are processor intensive calculations, which must take
> place in real-time on the baseband for encrypted links, I would argue
> that it makes more sense to use the likely optimized functionality
> present in the basebands.

Note that only the LTK negotiation is done on the host/kernel. The
payload PDU encryption itself still happens on the controller.

Is it expected that LTK generation happens so often? If so, I suspect
the request/response "overhead" would be bigger than the AES
implemented in kernel.

Also note that the Linux kernel API uses HW engine where
available/supported, and at least for x86 it has many optimizations.

Dunno which has better performance in the end though (we haven't measured it).

> That is not to say that it cannot be done on the host, just that it
> is likely less efficient, for no gain in portability or functionality.

For LTK calculation I *think* Linux kernel crypto API is fast enough
(the payloads are small, 16 bytes). Using the "built-in" AES engine on
LE controllers would be actually a lot more efficient for low-end
hosts though...

My two cents,
-- 
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-07 19:06     ` Anderson Lizardo
@ 2010-12-07 19:21       ` Brian Gix
  0 siblings, 0 replies; 33+ messages in thread
From: Brian Gix @ 2010-12-07 19:21 UTC (permalink / raw)
  To: 'Anderson Lizardo'
  Cc: 'Vinicius Costa Gomes', linux-bluetooth



Hi,

> -----Original Message-----
> From: Anderson Lizardo [mailto:anderson.lizardo@openbossa.org]
> Sent: 07 December, 2010 11:07 AM
> To: Brian Gix
> Cc: Vinicius Costa Gomes; linux-bluetooth@vger.kernel.org
> Subject: Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto
> subsystem
> 
> Hi,
> 
> On Tue, Dec 7, 2010 at 2:35 PM, Brian Gix <bgix@codeaurora.org> wrote:
> >> 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.
> >
> > I do understand the desire to reuse the crypto module, but I would
> like
> > to point out that every baseband that supports any level of LE-SM, is
> > required to have implemented the HCI commands for LE-SM centric
> encryption
> > and random number generation.
> 
> Correct.
> 
> > Also, since these are processor intensive calculations, which must
> take
> > place in real-time on the baseband for encrypted links, I would argue
> > that it makes more sense to use the likely optimized functionality
> > present in the basebands.
> 
> Note that only the LTK negotiation is done on the host/kernel. The
> payload PDU encryption itself still happens on the controller.
> 
> Is it expected that LTK generation happens so often? If so, I suspect
> the request/response "overhead" would be bigger than the AES
> implemented in kernel.
> 
> Also note that the Linux kernel API uses HW engine where
> available/supported, and at least for x86 it has many optimizations.
> 
> Dunno which has better performance in the end though (we haven't
> measured it).
> 
> > That is not to say that it cannot be done on the host, just that it
> > is likely less efficient, for no gain in portability or
> functionality.
> 
> For LTK calculation I *think* Linux kernel crypto API is fast enough
> (the payloads are small, 16 bytes). Using the "built-in" AES engine on
> LE controllers would be actually a lot more efficient for low-end
> hosts though...

Yeah, but if using crypto.c is what everyone wants, I have no hard
objections,
I guess. I do also see that Gustavo also notes a CRYPTO_BLKCIPHER dependence
that wasn't there before, suggesting that this will require pulling in code
that may not otherwise be needed. The HCI commands to do that work are
pretty straight forward.


> 
> My two cents,
> --
> Anderson Lizardo
> OpenBossa Labs - INdT
> Manaus - Brazil


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-07 18:35   ` Brian Gix
  2010-12-07 19:06     ` Anderson Lizardo
@ 2010-12-07 19:23     ` Vinicius Costa Gomes
  2010-12-07 19:34       ` Brian Gix
  1 sibling, 1 reply; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-07 19:23 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth

Hi Brian,

On 10:35 Tue 07 Dec, Brian Gix wrote:
> 
> Hi Vinicius,
> 
> > -----Original Message-----
> > From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
> > owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> > Sent: 06 December, 2010 1:44 PM
> > To: linux-bluetooth@vger.kernel.org
> > Cc: Vinicius Costa Gomes
> > Subject: [RFC v2 5/9] Bluetooth: Add support for using the crypto
> > subsystem
> > 
> > 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.
> 
> I do understand the desire to reuse the crypto module, but I would like
> to point out that every baseband that supports any level of LE-SM, is
> required to have implemented the HCI commands for LE-SM centric encryption
> and random number generation.

Yes, we are aware of that.

> 
> Also, since these are processor intensive calculations, which must take
> place in real-time on the baseband for encrypted links, I would argue
> that it makes more sense to use the likely optimized functionality
> present in the basebands.

I am sure that the baseband is optimized for those operations, but one 
thing that needs to be considered is the time that the information takes to get
to and from the baseband. For example, in the case of a USB controller, we need 
to build an HCI command, insert the command in the queue, and wait for it to be
delivered (and received) via the USB bus to the baseband. Using the crypto
subsystem we may even be able to use functionality built inside the processor.

> 
> That is not to say that it cannot be done on the host, just that it
> is likely less efficient, for no gain in portability or functionality.

There is a gain in simplicity ;-) 

> 
>  
> > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> > ---
> >  include/net/bluetooth/hci_core.h |    2 ++
> >  net/bluetooth/hci_core.c         |   10 ++++++++++
> >  2 files changed, 12 insertions(+), 0 deletions(-)
> > 
> > diff --git a/include/net/bluetooth/hci_core.h
> > b/include/net/bluetooth/hci_core.h
> > index 0687e2f..d0a9f5d 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -135,6 +135,8 @@ struct hci_dev {
> >  	__u32			req_status;
> >  	__u32			req_result;
> > 
> > +	struct crypto_blkcipher	*tfm;
> > +
> >  	struct inquiry_cache	inq_cache;
> >  	struct hci_conn_hash	conn_hash;
> >  	struct list_head	blacklist;
> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > index 12c6735..b96c3dd 100644
> > --- a/net/bluetooth/hci_core.c
> > +++ b/net/bluetooth/hci_core.c
> > @@ -41,6 +41,7 @@
> >  #include <linux/interrupt.h>
> >  #include <linux/notifier.h>
> >  #include <linux/rfkill.h>
> > +#include <linux/crypto.h>
> >  #include <net/sock.h>
> > 
> >  #include <asm/system.h>
> > @@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
> >  	if (!hdev->workqueue)
> >  		goto nomem;
> > 
> > +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0,
> > CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hdev->tfm)) {
> > +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> > +							PTR_ERR(hdev->tfm));
> > +		goto nomem;
> > +	}
> > +
> >  	hci_register_sysfs(hdev);
> > 
> >  	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> > @@ -1001,6 +1009,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
> >  	for (i = 0; i < NUM_REASSEMBLY; i++)
> >  		kfree_skb(hdev->reassembly[i]);
> > 
> > +	crypto_free_blkcipher(hdev->tfm);
> > +
> >  	hci_notify(hdev, HCI_DEV_UNREG);
> > 
> >  	if (hdev->rfkill) {
> > --
> > 1.7.3.2
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-
> > bluetooth" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem
  2010-12-07 19:23     ` Vinicius Costa Gomes
@ 2010-12-07 19:34       ` Brian Gix
  0 siblings, 0 replies; 33+ messages in thread
From: Brian Gix @ 2010-12-07 19:34 UTC (permalink / raw)
  To: 'Vinicius Costa Gomes'; +Cc: linux-bluetooth

Hi Vinicius,

> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
> owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> Sent: 07 December, 2010 11:23 AM
> To: Brian Gix
> Cc: linux-bluetooth@vger.kernel.org
> Subject: Re: [RFC v2 5/9] Bluetooth: Add support for using the crypto
> subsystem
> 
> Hi Brian,
> 
> On 10:35 Tue 07 Dec, Brian Gix wrote:
> >
> > Hi Vinicius,
> >
> > > -----Original Message-----
> > > From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-
> bluetooth-
> > > owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> > > Sent: 06 December, 2010 1:44 PM
> > > To: linux-bluetooth@vger.kernel.org
> > > Cc: Vinicius Costa Gomes
> > > Subject: [RFC v2 5/9] Bluetooth: Add support for using the crypto
> > > subsystem
> > >
> > > 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.
> >
> > I do understand the desire to reuse the crypto module, but I would
> like
> > to point out that every baseband that supports any level of LE-SM, is
> > required to have implemented the HCI commands for LE-SM centric
> encryption
> > and random number generation.
> 
> Yes, we are aware of that.
> 
> >
> > Also, since these are processor intensive calculations, which must
> take
> > place in real-time on the baseband for encrypted links, I would argue
> > that it makes more sense to use the likely optimized functionality
> > present in the basebands.
> 
> I am sure that the baseband is optimized for those operations, but one
> thing that needs to be considered is the time that the information
> takes to get
> to and from the baseband. For example, in the case of a USB controller,
> we need
> to build an HCI command, insert the command in the queue, and wait for
> it to be
> delivered (and received) via the USB bus to the baseband. Using the
> crypto
> subsystem we may even be able to use functionality built inside the
> processor.
> 
> >
> > That is not to say that it cannot be done on the host, just that it
> > is likely less efficient, for no gain in portability or
> functionality.
> 
> There is a gain in simplicity ;-)


Well that's fine.  Again, I have no objection.


> 
> >
> >
> > > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> > > ---
> > >  include/net/bluetooth/hci_core.h |    2 ++
> > >  net/bluetooth/hci_core.c         |   10 ++++++++++
> > >  2 files changed, 12 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/include/net/bluetooth/hci_core.h
> > > b/include/net/bluetooth/hci_core.h
> > > index 0687e2f..d0a9f5d 100644
> > > --- a/include/net/bluetooth/hci_core.h
> > > +++ b/include/net/bluetooth/hci_core.h
> > > @@ -135,6 +135,8 @@ struct hci_dev {
> > >  	__u32			req_status;
> > >  	__u32			req_result;
> > >
> > > +	struct crypto_blkcipher	*tfm;
> > > +
> > >  	struct inquiry_cache	inq_cache;
> > >  	struct hci_conn_hash	conn_hash;
> > >  	struct list_head	blacklist;
> > > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > index 12c6735..b96c3dd 100644
> > > --- a/net/bluetooth/hci_core.c
> > > +++ b/net/bluetooth/hci_core.c
> > > @@ -41,6 +41,7 @@
> > >  #include <linux/interrupt.h>
> > >  #include <linux/notifier.h>
> > >  #include <linux/rfkill.h>
> > > +#include <linux/crypto.h>
> > >  #include <net/sock.h>
> > >
> > >  #include <asm/system.h>
> > > @@ -961,6 +962,13 @@ int hci_register_dev(struct hci_dev *hdev)
> > >  	if (!hdev->workqueue)
> > >  		goto nomem;
> > >
> > > +	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0,
> > > CRYPTO_ALG_ASYNC);
> > > +	if (IS_ERR(hdev->tfm)) {
> > > +		BT_ERR("Failed to load transform for ecb(aes): %ld",
> > > +							PTR_ERR(hdev->tfm));
> > > +		goto nomem;
> > > +	}
> > > +
> > >  	hci_register_sysfs(hdev);
> > >
> > >  	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
> > > @@ -1001,6 +1009,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
> > >  	for (i = 0; i < NUM_REASSEMBLY; i++)
> > >  		kfree_skb(hdev->reassembly[i]);
> > >
> > > +	crypto_free_blkcipher(hdev->tfm);
> > > +
> > >  	hci_notify(hdev, HCI_DEV_UNREG);
> > >
> > >  	if (hdev->rfkill) {
> > > --
> > > 1.7.3.2
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-
> > > bluetooth" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> 
> Cheers,
> --
> Vinicius
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 2/9] Bluetooth: Implement the first SMP commands
  2010-12-07 16:03   ` Gustavo F. Padovan
@ 2010-12-07 22:05     ` Vinicius Costa Gomes
  0 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-07 22:05 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, Anderson Briglia

Hi Gustavo,

On 14:03 Tue 07 Dec, Gustavo F. Padovan wrote:
> Hi Vinicius,
> 
> * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:45 -0300]:
> 
> > 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 <vinicius.gomes@openbossa.org>
> > Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> > ---
> >  include/net/bluetooth/smp.h             |    4 +
> >  net/bluetooth/Makefile                  |    1 +
> >  net/bluetooth/{l2cap.c => l2cap_core.c} |    0
> 
> I want a separated patch for the l2cap.c rename.
>

Sure. Will do.

> >  net/bluetooth/smp.c                     |  144 +++++++++++++++++++++++++++++++
> >  4 files changed, 149 insertions(+), 0 deletions(-)
> >  rename net/bluetooth/{l2cap.c => l2cap_core.c} (100%)
> >  create mode 100644 net/bluetooth/smp.c
> > 
> > diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
> > index 8f2edbf..b9603cc 100644
> > --- a/include/net/bluetooth/smp.h
> > +++ b/include/net/bluetooth/smp.h
> > @@ -73,4 +73,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 d1e433f..d138b23 100644
> > --- a/net/bluetooth/Makefile
> > +++ b/net/bluetooth/Makefile
> > @@ -11,3 +11,4 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
> >  obj-$(CONFIG_BT_HIDP)	+= hidp/
> >  
> >  bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
> > +l2cap-objs := l2cap_core.o smp.o
> > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap_core.c
> > similarity index 100%
> > rename from net/bluetooth/l2cap.c
> > rename to net/bluetooth/l2cap_core.c
> > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> > new file mode 100644
> > index 0000000..e427d11
> > --- /dev/null
> > +++ b/net/bluetooth/smp.c
> > @@ -0,0 +1,144 @@
> > +/*
> > +   BlueZ - Bluetooth protocol stack for Linux
> > +   Copyright (C) 2010 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 + 1 + 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(1 + dlen);
> > +	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
> > +
> > +	memcpy(skb_put(skb, 1), &code, 1);
> > +
> > +	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 = 0x01;
> > +		break;
> > +
> > +	case BT_SECURITY_HIGH:
> > +		/* Bonding, MITM protection */
> > +		authreq = 0x05;
> > +		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, 1);
> > +
> > +	switch (code) {
> > +	case SMP_CMD_PAIRING_REQ:
> > +		reason = SMP_PAIRING_NOTSUPP;
> > +		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, 1, &reason);
> > +		err = -1;
> 
> Don't use -1, use a proper error macro here.

Sure.

> 
> > +		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, 1, &reason);
> > +		err = -1;
> 
> Same here.

Ok.

> 
> -- 
> Gustavo F. Padovan
> http://profusion.mobi


Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 2/9] Bluetooth: Implement the first SMP commands
  2010-12-07 16:10   ` Gustavo F. Padovan
@ 2010-12-07 22:06     ` Vinicius Costa Gomes
  0 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-07 22:06 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, Anderson Briglia

Hi Gustavo,

On 14:10 Tue 07 Dec, Gustavo F. Padovan wrote:
> Hi Vinicius,
> 
> * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:45 -0300]:
> 
> > 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 <vinicius.gomes@openbossa.org>
> > Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> > ---
> >  include/net/bluetooth/smp.h             |    4 +
> >  net/bluetooth/Makefile                  |    1 +
> >  net/bluetooth/{l2cap.c => l2cap_core.c} |    0
> >  net/bluetooth/smp.c                     |  144 +++++++++++++++++++++++++++++++
> >  4 files changed, 149 insertions(+), 0 deletions(-)
> >  rename net/bluetooth/{l2cap.c => l2cap_core.c} (100%)
> >  create mode 100644 net/bluetooth/smp.c
> > 
> > diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
> > index 8f2edbf..b9603cc 100644
> > --- a/include/net/bluetooth/smp.h
> > +++ b/include/net/bluetooth/smp.h
> > @@ -73,4 +73,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 d1e433f..d138b23 100644
> > --- a/net/bluetooth/Makefile
> > +++ b/net/bluetooth/Makefile
> > @@ -11,3 +11,4 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
> >  obj-$(CONFIG_BT_HIDP)	+= hidp/
> >  
> >  bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
> > +l2cap-objs := l2cap_core.o smp.o
> > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap_core.c
> > similarity index 100%
> > rename from net/bluetooth/l2cap.c
> > rename to net/bluetooth/l2cap_core.c
> > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> > new file mode 100644
> > index 0000000..e427d11
> > --- /dev/null
> > +++ b/net/bluetooth/smp.c
> > @@ -0,0 +1,144 @@
> > +/*
> > +   BlueZ - Bluetooth protocol stack for Linux
> > +   Copyright (C) 2010 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 + 1 + 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(1 + dlen);
> > +	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
> > +
> > +	memcpy(skb_put(skb, 1), &code, 1);
> > +
> > +	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 = 0x01;
> > +		break;
> > +
> > +	case BT_SECURITY_HIGH:
> > +		/* Bonding, MITM protection */
> > +		authreq = 0x05;
> 
> It would be good have some defines for the authreq values.

Makes sense.

> 
> -- 
> Gustavo F. Padovan
> http://profusion.mobi

Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 3/9] Bluetooth: Start SMP procedure
  2010-12-07 16:11   ` Gustavo F. Padovan
@ 2010-12-07 22:08     ` Vinicius Costa Gomes
  0 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-07 22:08 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, Anderson Briglia

Hi Gustavo,

On 14:11 Tue 07 Dec, Gustavo F. Padovan wrote:
> Hi Vinicius,
> 
> * Vinicius Costa Gomes <vinicius.gomes@openbossa.org> [2010-12-06 18:43:46 -0300]:
> 
> > From: Anderson Briglia <anderson.briglia@openbossa.org>
> > 
> > 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 <vinicius.gomes@openbossa.org>
> > Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> > ---
> >  net/bluetooth/l2cap_core.c |    7 +++++++
> >  net/bluetooth/smp.c        |    2 +-
> >  2 files changed, 8 insertions(+), 1 deletions(-)
> > 
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 69e5f80..674799c 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>
> >  
> >  #define VERSION "2.15"
> >  
> > @@ -642,6 +643,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 &&
> > @@ -4626,6 +4629,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
> >  		l2cap_conless_channel(conn, psm, skb);
> >  		break;
> >  
> > +	case L2CAP_CID_SMP:
> > +		smp_sig_channel(conn, skb);
> > +		break;
> > +
> >  	default:
> >  		l2cap_data_channel(conn, cid, skb);
> >  		break;
> > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> > index e427d11..e9dde5f 100644
> > --- a/net/bluetooth/smp.c
> > +++ b/net/bluetooth/smp.c
> > @@ -86,7 +86,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
> >  		return 1;
> >  	}
> >  
> > -	if (conn->hcon->link_mode & HCI_LM_MASTER) {
> > +	if (conn->hcon->out) {
> 
> This change should not belong to this patch.
> 

My bad. Will fix.

> -- 
> Gustavo F. Padovan
> http://profusion.mobi

Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation
  2010-12-07 18:26   ` Brian Gix
@ 2010-12-07 22:27     ` Vinicius Costa Gomes
  0 siblings, 0 replies; 33+ messages in thread
From: Vinicius Costa Gomes @ 2010-12-07 22:27 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth, 'Anderson Briglia'

Hi Brian,

On 10:26 Tue 07 Dec, Brian Gix wrote:
> 
> 
> Hi Vinicius,
> 
> > -----Original Message-----
> > From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
> > owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes
> > Sent: 06 December, 2010 1:44 PM
> > To: linux-bluetooth@vger.kernel.org
> > Cc: Anderson Briglia; Vinicius Costa Gomes
> > Subject: [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation
> > 
> > From: Anderson Briglia <anderson.briglia@openbossa.org>
> > 
> > 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 <vinicius.gomes@openbossa.org>
> > ---
> >  net/bluetooth/l2cap_core.c |    3 +-
> >  net/bluetooth/smp.c        |  114
> > ++++++++++++++++++++++++++++++++++++++++++--
> >  2 files changed, 112 insertions(+), 5 deletions(-)
> > 
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 674799c..da4f13d 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -4630,7 +4630,8 @@ static void l2cap_recv_frame(struct l2cap_conn
> > *conn, struct sk_buff *skb)
> >  		break;
> > 
> >  	case L2CAP_CID_SMP:
> > -		smp_sig_channel(conn, skb);
> > +		if (smp_sig_channel(conn, skb))
> > +			l2cap_conn_del(conn->hcon, 0x05);
> >  		break;
> > 
> >  	default:
> > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> > index e9dde5f..b25010f 100644
> > --- a/net/bluetooth/smp.c
> > +++ b/net/bluetooth/smp.c
> > @@ -64,6 +64,102 @@ 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("");
> > +
> > +	skb_pull(skb, sizeof(struct smp_cmd_pairing));
> > +
> > +	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 &= 0x05;
> > +
> > +	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
> > +}
> 
> As a "placeholder" I understand that there is a fair amount of fleshing
> out that these changes need.  However, as you have an conn->hcon->out
> flag that indicates direction (which hopefully is based on Link Master),
> I would like to see checking in this function and next, that the
> correct role has received these SMP packets, with a rejection if they
> were received by the incorrect role. Also, although the placeholder is
> requesting no key distribution, in the fleshed out version, the responder
> should be returning the subset (logical AND) of the requesters and the
> responders key_dist masks, which in this case is still of course Zero.
> 

Yeah, that kind of protocol checking is something that is really lacking.

This RFC is just the implementation of the Just Works pairing procedure,
without any support for key distribution. And as you noted, many things were
implemented using this assumption.

> I'm sorry if this is to many comments for this starting point.

Keep them coming :-) they are being very helpful.

> 
> > +
> > +static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct
> > sk_buff *skb)
> > +{
> > +	struct smp_cmd_pairing_confirm cp;
> > +
> > +	BT_DBG("");
> > +
> > +	memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
> > +
> > +	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("");
> > +
> > +	if (conn->hcon->out) {
> > +		struct smp_cmd_pairing_random random;
> > +
> > +		BT_DBG("master");
> > +
> > +		memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
> > +
> > +		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
> > +								&random);
> > +	} else {
> > +		struct smp_cmd_pairing_confirm confirm;
> > +
> > +		BT_DBG("slave");
> > +
> > +		memset(&confirm, 0, sizeof(struct
> > smp_cmd_pairing_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("");
> > +
> > +	skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
> > +
> > +	/* FIXME: check if random matches */
> 
> The random numbers will not match. The correct check will be that
> when the encryption with p1, p2, k, and the remote's random number,
> is performed, that it matches the confirm previously received
> via smp_cmd_pairing_confirm.

The comment is wrong. Will fix.

> 
> > +
> > +	if (conn->hcon->out) {
> > +		BT_DBG("master");
> > +		/* FIXME: start encryption */
> > +	} else {
> > +		BT_DBG("slave");
> > +
> > +		memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
> > +
> > +		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("");
> > +
> > +	skb_pull(skb, sizeof(struct smp_cmd_security_req));
> > +	memset(&cp, 0, sizeof(struct smp_cmd_pairing));
> > +
> > +	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 & 0x05;
> > +
> > +	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
> > +}
> > +
> 
> This function may need to be overloaded, such that if an existing
> set of keys already exist (from an earlier pairing) that they are
> used by simply encrypting the link, or signing the WRITE_CMD pkt
> as needed.  Should the link encryption fail due to remote rejection,
> we might then request security, subject to the same limitations
> used by BR/EDR's SSP. 

This particular function is just for the actual SMP Security Request Command.
But yeah, we need to have a single starting point for both when we have the
keys or not. How signing will be implemented is still an open point on my
mind.

> 
> But I do not know where the division lies between the key storage dB,
> the kernel mode code and the user mode code.
> 
> 
> >  int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
> >  {
> >  	__u8 authreq;
> > @@ -114,23 +210,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, 1, &reason);
> > -		err = -1;
> > +		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.3.2
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-
> > bluetooth" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Cheers,
-- 
Vinicius

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks
  2010-12-06 21:43 ` [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks Vinicius Costa Gomes
  2010-12-07 17:41   ` Gustavo F. Padovan
@ 2010-12-08  5:48   ` Koustuv Ghosh
  2010-12-08  6:33     ` Brian Gix
  2010-12-08  6:19   ` Koustuv Ghosh
  2 siblings, 1 reply; 33+ messages in thread
From: Koustuv Ghosh @ 2010-12-08  5:48 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

 Hello Vinicus,
 regarding the below routine,
 is it not good to check the IO capabilities and authentication
rquirement of the remote device from the skb inside this routine and
based on that we can trigger JustWorks or PassKey paring method.
Though I know you are implementing  only JustWorks
 but I feel it will be good approach to parse the response and then
trigger the paring method.


  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 k[16], res[16];

 -       BT_DBG("");
 +       /* Just Works */
 +       memset(k, 0, sizeof(k));
 +
 +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
 +       memcpy(&conn->pres[1], rp, sizeof(*rp));
 +       skb_pull(skb, sizeof(*rp));

 -       memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
 +       ret = smp_rand(conn->prnd);
 +       if (ret)
 +               return;
 +
 +       ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,
 +                       conn->src, 0, conn->dst, res);
 +       if (ret)
 +               return;

        smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
  }

On Tue, Dec 7, 2010 at 3:13 AM, Vinicius Costa Gomes
<vinicius.gomes@openbossa.org> wrote:
> This adds supports for verifying the confirmation value that the
> remote side has sent. This includes support for generating and sending
> the random value used to produce the confirmation value.
>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/l2cap.h |    5 ++
>  net/bluetooth/smp.c           |  121 ++++++++++++++++++++++++++++++++---------
>  2 files changed, 101 insertions(+), 25 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index a3cb1ab..bcda2aa 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -290,6 +290,11 @@ struct l2cap_conn {
>
>        __u8            disc_reason;
>
> +       __u8            preq[7];
> +       __u8            pres[7];
> +       __u8            prnd[16];
> +       __u8            pcnf[16];
> +
>        struct l2cap_chan_list chan_list;
>  };
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index b62160e..7d7e8ad 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -203,7 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>
>        BT_DBG("");
>
> -       skb_pull(skb, sizeof(struct smp_cmd_pairing));
> +       conn->preq[0] = SMP_CMD_PAIRING_REQ;
> +       memcpy(&conn->preq[1], rp, sizeof(*rp));
> +       skb_pull(skb, sizeof(*rp));
>
>        rp->io_capability = 0x00;
>        rp->oob_flag = 0x00;
> @@ -212,64 +214,125 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>        rp->resp_key_dist = 0x00;
>        rp->auth_req &= 0x05;
>
> +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
> +       memcpy(&conn->pres[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;
> +       struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
> +       int ret;
> +       u8 k[16], res[16];
>
> -       BT_DBG("");
> +       /* Just Works */
> +       memset(k, 0, sizeof(k));
> +
> +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
> +       memcpy(&conn->pres[1], rp, sizeof(*rp));
> +       skb_pull(skb, sizeof(*rp));
> +
> +       ret = smp_rand(conn->prnd);
> +       if (ret)
> +               return;
>
> -       memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
> +       ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 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("");
>
> -       if (conn->hcon->out) {
> -               struct smp_cmd_pairing_random random;
> +       memcpy(conn->pcnf, skb->data, 16);
> +       skb_pull(skb, 16);
>
> -               BT_DBG("master");
> +       if (conn->hcon->out) {
> +               u8 random[16];
>
> -               memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
> +               swap128(conn->prnd, random);
>
> -               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
> -                                                               &random);
> +               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, random);
>        } else {
> -               struct smp_cmd_pairing_confirm confirm;
> +               struct smp_cmd_pairing_confirm cp;
> +               int ret;
> +               u8 k[16], res[16];
> +
> +               /* Just Works */
> +               memset(k, 0, sizeof(k));
>
> -               BT_DBG("slave");
> +               ret = smp_rand(conn->prnd);
> +               if (ret)
> +                       return;
>
> -               memset(&confirm, 0, sizeof(struct smp_cmd_pairing_confirm));
> +               ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,
> +                               conn->dst, 0, conn->src, res);
> +               if (ret)
> +                       return;
>
> -               smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
> -                                                               &confirm);
> +               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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
> +
> +       swap128(skb->data, random);
> +       skb_pull(skb, 16);
> +
> +       memset(k, 0, sizeof(k));
> +
> +       if (conn->hcon->out)
> +               ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> +                               conn->src, 0, conn->dst, res);
> +       else
> +               ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> +                               conn->dst, 0, conn->src, res);
> +       if (ret)
> +               return;
>
> -       BT_DBG("");
> +       swap128(res, confirm);
>
> -       skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
> +       if (memcmp(conn->pcnf, confirm, 16) != 0) {
> +               struct smp_cmd_pairing_fail cp;
>
> -       /* FIXME: check if random matches */
> +               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) {
> -               BT_DBG("master");
> -               /* FIXME: start encryption */
> +               smp_s1(tfm, k, random, conn->prnd, key);
> +
> +               hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
> +               BT_DBG("key %s", buf);
>        } else {
> -               BT_DBG("slave");
> +               u8 r[16];
>
> -               memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
> +               swap128(conn->prnd, r);
> +               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
>
> -               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
> +               smp_s1(tfm, k, conn->prnd, random, key);
> +
> +               hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
> +               BT_DBG("key %s", buf);
>        }
>  }
>
> @@ -280,8 +343,9 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
>
>        BT_DBG("");
>
> -       skb_pull(skb, sizeof(struct smp_cmd_security_req));
> -       memset(&cp, 0, sizeof(struct smp_cmd_pairing));
> +       skb_pull(skb, sizeof(*rp));
> +
> +       memset(&cp, 0, sizeof(cp));
>
>        cp.io_capability = 0x00;
>        cp.oob_flag = 0x00;
> @@ -290,6 +354,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 & 0x05;
>
> +       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);
>  }
>
> @@ -323,6 +390,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.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks
  2010-12-06 21:43 ` [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks Vinicius Costa Gomes
  2010-12-07 17:41   ` Gustavo F. Padovan
  2010-12-08  5:48   ` Koustuv Ghosh
@ 2010-12-08  6:19   ` Koustuv Ghosh
  2 siblings, 0 replies; 33+ messages in thread
From: Koustuv Ghosh @ 2010-12-08  6:19 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

Hello ,
pls I apologise for top posting. So I request to ignore my first mail.

On Tue, Dec 7, 2010 at 3:13 AM, Vinicius Costa Gomes
<vinicius.gomes@openbossa.org> wrote:
> This adds supports for verifying the confirmation value that the
> remote side has sent. This includes support for generating and sending
> the random value used to produce the confirmation value.
>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
>  include/net/bluetooth/l2cap.h |    5 ++
>  net/bluetooth/smp.c           |  121 ++++++++++++++++++++++++++++++++---------
>  2 files changed, 101 insertions(+), 25 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index a3cb1ab..bcda2aa 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -290,6 +290,11 @@ struct l2cap_conn {
>
>        __u8            disc_reason;
>
> +       __u8            preq[7];
> +       __u8            pres[7];
> +       __u8            prnd[16];
> +       __u8            pcnf[16];
> +
>        struct l2cap_chan_list chan_list;
>  };
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index b62160e..7d7e8ad 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -203,7 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>
>        BT_DBG("");
>
> -       skb_pull(skb, sizeof(struct smp_cmd_pairing));
> +       conn->preq[0] = SMP_CMD_PAIRING_REQ;
> +       memcpy(&conn->preq[1], rp, sizeof(*rp));
> +       skb_pull(skb, sizeof(*rp));
>
>        rp->io_capability = 0x00;
>        rp->oob_flag = 0x00;
> @@ -212,64 +214,125 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>        rp->resp_key_dist = 0x00;
>        rp->auth_req &= 0x05;
>
> +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
> +       memcpy(&conn->pres[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;
> +       struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
> +       int ret;
> +       u8 k[16], res[16];
>
> -       BT_DBG("");
> +       /* Just Works */
> +       memset(k, 0, sizeof(k));
> +
> +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
> +       memcpy(&conn->pres[1], rp, sizeof(*rp));
> +       skb_pull(skb, sizeof(*rp));
> +
> +       ret = smp_rand(conn->prnd);
> +       if (ret)
> +               return;
>
> -       memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
> +       ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 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("");
>
> -       if (conn->hcon->out) {
> -               struct smp_cmd_pairing_random random;
> +       memcpy(conn->pcnf, skb->data, 16);
> +       skb_pull(skb, 16);
>
> -               BT_DBG("master");
> +       if (conn->hcon->out) {
> +               u8 random[16];
>
> -               memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
> +               swap128(conn->prnd, random);
>
> -               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
> -                                                               &random);
> +               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, random);
>        } else {
> -               struct smp_cmd_pairing_confirm confirm;
> +               struct smp_cmd_pairing_confirm cp;
> +               int ret;
> +               u8 k[16], res[16];
> +
> +               /* Just Works */
> +               memset(k, 0, sizeof(k));
>
> -               BT_DBG("slave");
> +               ret = smp_rand(conn->prnd);
> +               if (ret)
> +                       return;
>
> -               memset(&confirm, 0, sizeof(struct smp_cmd_pairing_confirm));
> +               ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,
> +                               conn->dst, 0, conn->src, res);
> +               if (ret)
> +                       return;
>
> -               smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
> -                                                               &confirm);
> +               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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
> +
> +       swap128(skb->data, random);
> +       skb_pull(skb, 16);
> +
> +       memset(k, 0, sizeof(k));
> +
> +       if (conn->hcon->out)
> +               ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> +                               conn->src, 0, conn->dst, res);
> +       else
> +               ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> +                               conn->dst, 0, conn->src, res);
> +       if (ret)
> +               return;
>
> -       BT_DBG("");
> +       swap128(res, confirm);
>
> -       skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
> +       if (memcmp(conn->pcnf, confirm, 16) != 0) {
> +               struct smp_cmd_pairing_fail cp;
>
> -       /* FIXME: check if random matches */
> +               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) {
> -               BT_DBG("master");
> -               /* FIXME: start encryption */
> +               smp_s1(tfm, k, random, conn->prnd, key);
> +
> +               hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
> +               BT_DBG("key %s", buf);
>        } else {
> -               BT_DBG("slave");
> +               u8 r[16];
>
> -               memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
> +               swap128(conn->prnd, r);
> +               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
>
> -               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
> +               smp_s1(tfm, k, conn->prnd, random, key);
> +
> +               hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
> +               BT_DBG("key %s", buf);
>        }
>  }
>
> @@ -280,8 +343,9 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
>
>        BT_DBG("");
>
> -       skb_pull(skb, sizeof(struct smp_cmd_security_req));
> -       memset(&cp, 0, sizeof(struct smp_cmd_pairing));
> +       skb_pull(skb, sizeof(*rp));
> +
> +       memset(&cp, 0, sizeof(cp));
>
>        cp.io_capability = 0x00;
>        cp.oob_flag = 0x00;
> @@ -290,6 +354,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 & 0x05;
>
> +       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);
>  }
>
> @@ -323,6 +390,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.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Hello Vinicus,
 regarding the below routine,
 is it not good to check the IO capabilities and authentication
rquirement of the remote device from the skb inside this routine and
based on that we can trigger JustWorks or PassKey paring method.
Though I know you are implementing  only JustWorks
 but I feel it will be good approach to parse the response and then
trigger the paring method.



 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 k[16], res[16];

 -       BT_DBG("");
 +       /* Just Works */
 +       memset(k, 0, sizeof(k));
 +
 +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
 +       memcpy(&conn->pres[1], rp, sizeof(*rp));
 +       skb_pull(skb, sizeof(*rp));


 -       memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
 +       ret = smp_rand(conn->prnd);
 +       if (ret)
 +               return;
 +
 +       ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,

 +                       conn->src, 0, conn->dst, res);
 +       if (ret)
 +               return;


       smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
 }

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks
  2010-12-08  5:48   ` Koustuv Ghosh
@ 2010-12-08  6:33     ` Brian Gix
  0 siblings, 0 replies; 33+ messages in thread
From: Brian Gix @ 2010-12-08  6:33 UTC (permalink / raw)
  To: Koustuv Ghosh; +Cc: Vinicius Costa Gomes, linux-bluetooth

Hi Koustuv,

On 12/07/2010 9:48 PM, Koustuv Ghosh wrote:
>   Hello Vinicus,
>   regarding the below routine,
>   is it not good to check the IO capabilities and authentication
> rquirement of the remote device from the skb inside this routine and
> based on that we can trigger JustWorks or PassKey paring method.
> Though I know you are implementing  only JustWorks
>   but I feel it will be good approach to parse the response and then
> trigger the paring method.

The way LE pairing is suppose to work is that each of the two devices
declares what it wants from the process ((Permanent)Pairing and/or 
Man-In-The-Middle (MITM) protection) and what kind of I/O it has to
perform the required steps.

If *either* side wants MITM, then it will be attempted, but if the
I/O capabilities are incompatible with MITM, then JUST_WORKS must be
done instead. The only special case here is if both side *Don't* want
MITM, and at least one side does not have OOB capabilities. In that
case, JUST_WORKS is always used, regardless of the I/O Capabilities.

This creates the situation that going into the process, neither side
knows for sure whether MITM protection is provided. So at "completion"
of the pairing process, the level of protection provided must be 
advertised to the upper layers.  This gives the individual profiles
the protection level provided, so that they may reject any transactions 
that do not conform to their required security level.

In other words, you can request MITM (highest) security, but you cannot 
require it during pairing. You will get MITM only if possible. It *will 
not* prevent pairing from happening. however you will always know at 
completion what level has been achieved.

>
>
>    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 k[16], res[16];
>
>   -       BT_DBG("");
>   +       /* Just Works */
>   +       memset(k, 0, sizeof(k));
>   +
>   +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
>   +       memcpy(&conn->pres[1], rp, sizeof(*rp));
>   +       skb_pull(skb, sizeof(*rp));
>
>   -       memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
>   +       ret = smp_rand(conn->prnd);
>   +       if (ret)
>   +               return;
>   +
>   +       ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,
>   +                       conn->src, 0, conn->dst, res);
>   +       if (ret)
>   +               return;
>
>          smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp),&cp);
>    }
>
> On Tue, Dec 7, 2010 at 3:13 AM, Vinicius Costa Gomes
> <vinicius.gomes@openbossa.org>  wrote:
>> This adds supports for verifying the confirmation value that the
>> remote side has sent. This includes support for generating and sending
>> the random value used to produce the confirmation value.
>>
>> Signed-off-by: Vinicius Costa Gomes<vinicius.gomes@openbossa.org>
>> ---
>>   include/net/bluetooth/l2cap.h |    5 ++
>>   net/bluetooth/smp.c           |  121 ++++++++++++++++++++++++++++++++---------
>>   2 files changed, 101 insertions(+), 25 deletions(-)
>>
>> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
>> index a3cb1ab..bcda2aa 100644
>> --- a/include/net/bluetooth/l2cap.h
>> +++ b/include/net/bluetooth/l2cap.h
>> @@ -290,6 +290,11 @@ struct l2cap_conn {
>>
>>         __u8            disc_reason;
>>
>> +       __u8            preq[7];
>> +       __u8            pres[7];
>> +       __u8            prnd[16];
>> +       __u8            pcnf[16];
>> +
>>         struct l2cap_chan_list chan_list;
>>   };
>>
>> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
>> index b62160e..7d7e8ad 100644
>> --- a/net/bluetooth/smp.c
>> +++ b/net/bluetooth/smp.c
>> @@ -203,7 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>>
>>         BT_DBG("");
>>
>> -       skb_pull(skb, sizeof(struct smp_cmd_pairing));
>> +       conn->preq[0] = SMP_CMD_PAIRING_REQ;
>> +       memcpy(&conn->preq[1], rp, sizeof(*rp));
>> +       skb_pull(skb, sizeof(*rp));
>>
>>         rp->io_capability = 0x00;
>>         rp->oob_flag = 0x00;
>> @@ -212,64 +214,125 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
>>         rp->resp_key_dist = 0x00;
>>         rp->auth_req&= 0x05;
>>
>> +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
>> +       memcpy(&conn->pres[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;
>> +       struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
>> +       int ret;
>> +       u8 k[16], res[16];
>>
>> -       BT_DBG("");
>> +       /* Just Works */
>> +       memset(k, 0, sizeof(k));
>> +
>> +       conn->pres[0] = SMP_CMD_PAIRING_RSP;
>> +       memcpy(&conn->pres[1], rp, sizeof(*rp));
>> +       skb_pull(skb, sizeof(*rp));
>> +
>> +       ret = smp_rand(conn->prnd);
>> +       if (ret)
>> +               return;
>>
>> -       memset(&cp, 0, sizeof(struct smp_cmd_pairing_confirm));
>> +       ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 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("");
>>
>> -       if (conn->hcon->out) {
>> -               struct smp_cmd_pairing_random random;
>> +       memcpy(conn->pcnf, skb->data, 16);
>> +       skb_pull(skb, 16);
>>
>> -               BT_DBG("master");
>> +       if (conn->hcon->out) {
>> +               u8 random[16];
>>
>> -               memset(&random, 0, sizeof(struct smp_cmd_pairing_random));
>> +               swap128(conn->prnd, random);
>>
>> -               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
>> -&random);
>> +               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, random);
>>         } else {
>> -               struct smp_cmd_pairing_confirm confirm;
>> +               struct smp_cmd_pairing_confirm cp;
>> +               int ret;
>> +               u8 k[16], res[16];
>> +
>> +               /* Just Works */
>> +               memset(k, 0, sizeof(k));
>>
>> -               BT_DBG("slave");
>> +               ret = smp_rand(conn->prnd);
>> +               if (ret)
>> +                       return;
>>
>> -               memset(&confirm, 0, sizeof(struct smp_cmd_pairing_confirm));
>> +               ret = smp_c1(tfm, k, conn->prnd, conn->preq, conn->pres, 0,
>> +                               conn->dst, 0, conn->src, res);
>> +               if (ret)
>> +                       return;
>>
>> -               smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
>> -&confirm);
>> +               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 k[16], key[16], res[16], random[16], confirm[16], buf[128];
>> +
>> +       swap128(skb->data, random);
>> +       skb_pull(skb, 16);
>> +
>> +       memset(k, 0, sizeof(k));
>> +
>> +       if (conn->hcon->out)
>> +               ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
>> +                               conn->src, 0, conn->dst, res);
>> +       else
>> +               ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
>> +                               conn->dst, 0, conn->src, res);
>> +       if (ret)
>> +               return;
>>
>> -       BT_DBG("");
>> +       swap128(res, confirm);
>>
>> -       skb_pull(skb, sizeof(struct smp_cmd_pairing_random));
>> +       if (memcmp(conn->pcnf, confirm, 16) != 0) {
>> +               struct smp_cmd_pairing_fail cp;
>>
>> -       /* FIXME: check if random matches */
>> +               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) {
>> -               BT_DBG("master");
>> -               /* FIXME: start encryption */
>> +               smp_s1(tfm, k, random, conn->prnd, key);
>> +
>> +               hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
>> +               BT_DBG("key %s", buf);
>>         } else {
>> -               BT_DBG("slave");
>> +               u8 r[16];
>>
>> -               memset(&cp, 0, sizeof(struct smp_cmd_pairing_random));
>> +               swap128(conn->prnd, r);
>> +               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
>>
>> -               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp),&cp);
>> +               smp_s1(tfm, k, conn->prnd, random, key);
>> +
>> +               hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
>> +               BT_DBG("key %s", buf);
>>         }
>>   }
>>
>> @@ -280,8 +343,9 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
>>
>>         BT_DBG("");
>>
>> -       skb_pull(skb, sizeof(struct smp_cmd_security_req));
>> -       memset(&cp, 0, sizeof(struct smp_cmd_pairing));
>> +       skb_pull(skb, sizeof(*rp));
>> +
>> +       memset(&cp, 0, sizeof(cp));
>>
>>         cp.io_capability = 0x00;
>>         cp.oob_flag = 0x00;
>> @@ -290,6 +354,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&  0x05;
>>
>> +       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);
>>   }
>>
>> @@ -323,6 +390,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.3.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2010-12-08  6:33 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-06 21:43 [RFC v2 0/9] SMP Implementation Vinicius Costa Gomes
2010-12-06 21:43 ` [RFC v2 1/9] Bluetooth: Add SMP command structures Vinicius Costa Gomes
2010-12-06 21:43 ` [RFC v2 2/9] Bluetooth: Implement the first SMP commands Vinicius Costa Gomes
2010-12-07 16:03   ` Gustavo F. Padovan
2010-12-07 22:05     ` Vinicius Costa Gomes
2010-12-07 16:10   ` Gustavo F. Padovan
2010-12-07 22:06     ` Vinicius Costa Gomes
2010-12-06 21:43 ` [RFC v2 3/9] Bluetooth: Start SMP procedure Vinicius Costa Gomes
2010-12-07 16:11   ` Gustavo F. Padovan
2010-12-07 22:08     ` Vinicius Costa Gomes
2010-12-06 21:43 ` [RFC v2 4/9] Bluetooth: simple SMP pairing negotiation Vinicius Costa Gomes
2010-12-07 16:39   ` Gustavo F. Padovan
2010-12-07 18:26   ` Brian Gix
2010-12-07 22:27     ` Vinicius Costa Gomes
2010-12-06 21:43 ` [RFC v2 5/9] Bluetooth: Add support for using the crypto subsystem Vinicius Costa Gomes
2010-12-07 17:27   ` Gustavo F. Padovan
2010-12-07 17:51     ` Vinicius Costa Gomes
2010-12-07 18:05       ` Gustavo F. Padovan
2010-12-07 18:35   ` Brian Gix
2010-12-07 19:06     ` Anderson Lizardo
2010-12-07 19:21       ` Brian Gix
2010-12-07 19:23     ` Vinicius Costa Gomes
2010-12-07 19:34       ` Brian Gix
2010-12-06 21:43 ` [RFC v2 6/9] Bluetooth: LE SMP Cryptoolbox functions Vinicius Costa Gomes
2010-12-06 21:43 ` [RFC v2 7/9] Bluetooth: Add support for SMP confirmation checks Vinicius Costa Gomes
2010-12-07 17:41   ` Gustavo F. Padovan
2010-12-08  5:48   ` Koustuv Ghosh
2010-12-08  6:33     ` Brian Gix
2010-12-08  6:19   ` Koustuv Ghosh
2010-12-06 21:43 ` [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption Vinicius Costa Gomes
2010-12-07 17:38   ` Gustavo F. Padovan
2010-12-07 18:58   ` Brian Gix
2010-12-06 21:43 ` [RFC v2 9/9] Bluetooth: Add support for resuming socket when SMP is finished Vinicius Costa Gomes

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.