Linux bluetooth development
 help / color / mirror / Atom feed
* [bluetooth-next 10/15] Bluetooth: Add support for resuming socket when SMP is finished
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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 |   61 ++++++++++++++++++++++---------------------
 net/bluetooth/l2cap_sock.c |   17 ++++++++++++
 net/bluetooth/smp.c        |   40 ++++++++++++++++++++--------
 3 files changed, 76 insertions(+), 42 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 66988b8..991b349 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -666,6 +666,22 @@ clean:
 	bh_unlock_sock(parent);
 }
 
+static void l2cap_chan_ready(struct sock *sk)
+{
+	struct sock *parent = bt_sk(sk)->parent;
+
+	BT_DBG("sk %p, parent %p", sk, parent);
+
+	l2cap_pi(sk)->conf_state = 0;
+	l2cap_sock_clear_timer(sk);
+
+	sk->sk_state = BT_CONNECTED;
+	sk->sk_state_change(sk);
+
+	if (parent)
+		parent->sk_data_ready(parent, 0);
+}
+
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
 	struct l2cap_chan_list *l = &conn->chan_list;
@@ -681,15 +697,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
 		bh_lock_sock(sk);
 
-		if (conn->hcon->type == LE_LINK) {
-			l2cap_sock_clear_timer(sk);
-			sk->sk_state = BT_CONNECTED;
-			sk->sk_state_change(sk);
+		if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
 			if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
-				BT_DBG("Insufficient security");
-		}
+				l2cap_chan_ready(sk);
 
-		if (sk->sk_type != SOCK_SEQPACKET &&
+		} else if (sk->sk_type != SOCK_SEQPACKET &&
 				sk->sk_type != SOCK_STREAM) {
 			l2cap_sock_clear_timer(sk);
 			sk->sk_state = BT_CONNECTED;
@@ -1360,29 +1372,6 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
 	return size;
 }
 
-static void l2cap_chan_ready(struct sock *sk)
-{
-	struct sock *parent = bt_sk(sk)->parent;
-
-	BT_DBG("sk %p, parent %p", sk, parent);
-
-	l2cap_pi(sk)->conf_state = 0;
-	l2cap_sock_clear_timer(sk);
-
-	if (!parent) {
-		/* Outgoing channel.
-		 * Wake up socket sleeping on connect.
-		 */
-		sk->sk_state = BT_CONNECTED;
-		sk->sk_state_change(sk);
-	} else {
-		/* Incoming channel.
-		 * Wake up socket sleeping on accept.
-		 */
-		parent->sk_data_ready(parent, 0);
-	}
-}
-
 /* Copy frame to all raw sockets on that connection */
 static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
 {
@@ -3800,6 +3789,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
 		bh_lock_sock(sk);
 
+		BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
+
+		if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
+			if (!status && encrypt) {
+				l2cap_pi(sk)->sec_level = hcon->sec_level;
+				l2cap_chan_ready(sk);
+			}
+
+			bh_unlock_sock(sk);
+			continue;
+		}
+
 		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
 			bh_unlock_sock(sk);
 			continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index fc85e7a..3abf678 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -29,6 +29,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
 
 /* ---- L2CAP timers ---- */
 static void l2cap_sock_timeout(unsigned long arg)
@@ -614,6 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 {
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
+	struct l2cap_conn *conn;
 	int len, err = 0;
 	u32 opt;
 
@@ -650,6 +652,21 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 		}
 
 		l2cap_pi(sk)->sec_level = sec.level;
+
+		conn = l2cap_pi(sk)->conn;
+		if (conn && l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
+			if (!conn->hcon->out) {
+				err = -EINVAL;
+				break;
+			}
+
+			if (!smp_conn_security(conn, sec.level)) {
+				err = -EINVAL;
+				break;
+			}
+
+			sk->sk_state = BT_CONFIG;
+		}
 		break;
 
 	case BT_DEFER_SETUP:
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6d32bcc..1fd338b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -338,9 +338,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_security_req *rp = (void *) skb->data;
 	struct smp_cmd_pairing cp;
+	struct hci_conn *hcon = conn->hcon;
 
 	BT_DBG("conn %p", conn);
 
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+		return;
+
 	skb_pull(skb, sizeof(*rp));
 	memset(&cp, 0, sizeof(cp));
 
@@ -355,6 +359,20 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 	memcpy(&conn->preq[1], &cp, sizeof(cp));
 
 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+
+	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+}
+
+static __u8 seclevel_to_authreq(__u8 level)
+{
+	switch (level) {
+	case BT_SECURITY_HIGH:
+		/* For now we don't support bonding */
+		return SMP_AUTH_MITM;
+
+	default:
+		return SMP_AUTH_NONE;
+	}
 }
 
 int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
@@ -367,21 +385,16 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 	if (IS_ERR(hcon->hdev->tfm))
 		return PTR_ERR(hcon->hdev->tfm);
 
-	switch (sec_level) {
-	case BT_SECURITY_MEDIUM:
-		/* Encrypted, no MITM protection */
-		authreq = HCI_AT_NO_BONDING_MITM;
-		break;
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+		return -EINPROGRESS;
 
-	case BT_SECURITY_HIGH:
-		/* Bonding, MITM protection */
-		authreq = HCI_AT_GENERAL_BONDING_MITM;
-		break;
+	if (sec_level == BT_SECURITY_LOW)
+		return 1;
 
-	case BT_SECURITY_LOW:
-	default:
+	if (hcon->sec_level > sec_level)
 		return 1;
-	}
+
+	authreq = seclevel_to_authreq(sec_level);
 
 	if (hcon->link_mode & HCI_LM_MASTER) {
 		struct smp_cmd_pairing cp;
@@ -402,6 +415,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
 	}
 
+	hcon->pending_sec_level = sec_level;
+	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
 	return 0;
 }
 
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 09/15] Bluetooth: Add support for LE Start Encryption
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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         |   46 ++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |   67 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/smp.c              |    9 ++++-
 5 files changed, 160 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index a5f8c46..f95b1e6 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -688,6 +688,33 @@ struct hci_cp_le_conn_update {
 	__le16   max_ce_len;
 } __packed;
 
+#define HCI_OP_LE_START_ENC		0x2019
+struct hci_cp_le_start_enc {
+	__le16	handle;
+	__u8	rand[8];
+	__le16	ediv;
+	__u8	ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY		0x201a
+struct hci_cp_le_ltk_reply {
+	__le16	handle;
+	__u8	ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+	__u8	status;
+	__le16	handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY		0x201b
+struct hci_cp_le_ltk_neg_reply {
+	__le16	handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+	__u8	status;
+	__le16	handle;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
@@ -967,6 +994,13 @@ struct hci_ev_le_conn_complete {
 	__u8     clk_accurancy;
 } __packed;
 
+#define HCI_EV_LE_LTK_REQ		0x05
+struct hci_ev_le_ltk_req {
+	__le16	handle;
+	__u8	random[8];
+	__le16	ediv;
+} __packed;
+
 /* Internal events generated by Bluetooth stack */
 #define HCI_EV_STACK_INTERNAL	0xfd
 struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e8dbde8..aeae4b4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -226,6 +226,7 @@ struct hci_conn {
 	__u8		power_save;
 	__u16		disc_timeout;
 	unsigned long	pend;
+	__u8		ltk[16];
 
 	__u8		remote_cap;
 	__u8		remote_oob;
@@ -781,4 +782,8 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
 
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 					u16 latency, u16 to_multiplier);
+void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
 #endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index a050a69..e75b2a6 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -203,6 +203,52 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 }
 EXPORT_SYMBOL(hci_le_conn_update);
 
+void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16])
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_start_enc cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+
+	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_ltk_reply cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, ltk, sizeof(ltk));
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_ltk_neg_reply cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
 /* Device _must_ be locked */
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 98b5764..829ba49 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -796,6 +796,30 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
 }
 
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1163,6 +1187,11 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1728,6 +1757,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_le_read_buffer_size(hdev, skb);
 		break;
 
+	case HCI_OP_LE_LTK_REPLY:
+		hci_cc_le_ltk_reply(hdev, skb);
+		break;
+
+	case HCI_OP_LE_LTK_NEG_REPLY:
+		hci_cc_le_ltk_neg_reply(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -1806,6 +1843,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_le_create_conn(hdev, ev->status);
 		break;
 
+	case HCI_OP_LE_START_ENC:
+		hci_cs_le_start_enc(hdev, ev->status);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -2432,6 +2473,28 @@ unlock:
 	hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+						struct sk_buff *skb)
+{
+	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+	struct hci_cp_le_ltk_reply cp;
+	struct hci_conn *conn;
+
+	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+
+	memset(&cp, 0, sizeof(cp));
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+
+	hci_dev_unlock(hdev);
+}
+
 static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2443,6 +2506,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_le_conn_complete_evt(hdev, skb);
 		break;
 
+	case HCI_EV_LE_LTK_REQ:
+		hci_le_ltk_request_evt(hdev, skb);
+		break;
+
 	default:
 		break;
 	}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 52241fd..6d32bcc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -280,13 +280,16 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
 
 static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+	struct hci_conn *hcon = conn->hcon;
+	struct crypto_blkcipher *tfm = hcon->hdev->tfm;
 	int ret;
 	u8 key[16], res[16], random[16], confirm[16], buf[128];
 
 	swap128(skb->data, random);
 	skb_pull(skb, sizeof(random));
 
+	memset(hcon->ltk, 0, sizeof(hcon->ltk));
+
 	if (conn->hcon->out)
 		ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
 				conn->src, 0, conn->dst, res);
@@ -311,6 +314,9 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	if (conn->hcon->out) {
 		smp_s1(tfm, conn->tk, random, conn->prnd, key);
+		swap128(key, hcon->ltk);
+
+		hci_le_start_enc(hcon, hcon->ltk);
 
 		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
 		BT_DBG("key %s", buf);
@@ -321,6 +327,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
 
 		smp_s1(tfm, conn->tk, conn->prnd, random, key);
+		swap128(key, hcon->ltk);
 
 		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
 		BT_DBG("key %s", buf);
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 08/15] Bluetooth: Minor fix in SMP methods
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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

Minor fix in smp_conn_security function.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 net/bluetooth/smp.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 37224a7..52241fd 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -352,12 +352,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
 int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 {
+	struct hci_conn *hcon = conn->hcon;
 	__u8 authreq;
 
-	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
+	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
 
-	if (IS_ERR(conn->hcon->hdev->tfm))
-		return PTR_ERR(conn->hcon->hdev->tfm);
+	if (IS_ERR(hcon->hdev->tfm))
+		return PTR_ERR(hcon->hdev->tfm);
 
 	switch (sec_level) {
 	case BT_SECURITY_MEDIUM:
@@ -375,7 +376,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 		return 1;
 	}
 
-	if (conn->hcon->link_mode & HCI_LM_MASTER) {
+	if (hcon->link_mode & HCI_LM_MASTER) {
 		struct smp_cmd_pairing cp;
 		cp.io_capability = 0x00;
 		cp.oob_flag = 0x00;
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 07/15] Bluetooth: Add SMP confirmation checks methods
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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

This patch includes support for generating and sending the random value
used to produce the confirmation value.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/l2cap.h |    1 +
 net/bluetooth/smp.c           |   92 ++++++++++++++++++++++++++++++++++------
 2 files changed, 79 insertions(+), 14 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 82508ed..ed65d65 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -311,6 +311,7 @@ struct l2cap_conn {
 	__u8		prsp[7]; /* SMP Pairing Response */
 	__u8		prnd[16]; /* SMP Pairing Random */
 	__u8		pcnf[16]; /* SMP Pairing Confirm */
+	__u8		tk[16]; /* SMP Temporary Key */
 
 	struct l2cap_chan_list chan_list;
 };
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 31ee1c0..37224a7 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -203,6 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 	rp->resp_key_dist = 0x00;
 	rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
 
+	/* Just works */
+	memset(conn->tk, 0, sizeof(conn->tk));
+
 	conn->prsp[0] = SMP_CMD_PAIRING_RSP;
 	memcpy(&conn->prsp[1], rp, sizeof(*rp));
 
@@ -213,53 +216,114 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_pairing *rp = (void *) skb->data;
 	struct smp_cmd_pairing_confirm cp;
+	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+	int ret;
+	u8 res[16];
 
 	BT_DBG("conn %p", conn);
 
-	memset(&cp, 0, sizeof(cp));
+	/* Just works */
+	memset(conn->tk, 0, sizeof(conn->tk));
 
 	conn->prsp[0] = SMP_CMD_PAIRING_RSP;
 	memcpy(&conn->prsp[1], rp, sizeof(*rp));
 	skb_pull(skb, sizeof(*rp));
 
+	ret = smp_rand(conn->prnd);
+	if (ret)
+		return;
+
+	ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
+			conn->src, 0, conn->dst, res);
+	if (ret)
+		return;
+
+	swap128(res, cp.confirm_val);
+
 	smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
 }
 
 static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 {
+	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+
 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
 
-	if (conn->hcon->out) {
-		struct smp_cmd_pairing_random random;
+	memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
+	skb_pull(skb, sizeof(conn->pcnf));
 
-		memset(&random, 0, sizeof(random));
+	if (conn->hcon->out) {
+		u8 random[16];
 
+		swap128(conn->prnd, random);
 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
-								&random);
+								random);
 	} else {
-		struct smp_cmd_pairing_confirm confirm;
+		struct smp_cmd_pairing_confirm cp;
+		int ret;
+		u8 res[16];
 
-		memset(&confirm, 0, sizeof(confirm));
+		ret = smp_rand(conn->prnd);
+		if (ret)
+			return;
 
-		smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
-								&confirm);
+		ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
+					0, conn->dst, 0, conn->src, res);
+		if (ret)
+			return;
+
+		swap128(res, cp.confirm_val);
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
 	}
 }
 
 static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	struct smp_cmd_pairing_random cp;
+	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+	int ret;
+	u8 key[16], res[16], random[16], confirm[16], buf[128];
+
+	swap128(skb->data, random);
+	skb_pull(skb, sizeof(random));
+
+	if (conn->hcon->out)
+		ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+				conn->src, 0, conn->dst, res);
+	else
+		ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+				conn->dst, 0, conn->src, res);
+	if (ret)
+		return;
 
 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
 
-	skb_pull(skb, sizeof(cp));
+	swap128(res, confirm);
+
+	if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
+		struct smp_cmd_pairing_fail cp;
+
+		BT_ERR("Pairing failed (confirmation values mismatch)");
+		cp.reason = SMP_CONFIRM_FAILED;
+		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(cp), &cp);
+		return;
+	}
 
 	if (conn->hcon->out) {
-		/* FIXME: start encryption */
+		smp_s1(tfm, conn->tk, random, conn->prnd, key);
+
+		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
+		BT_DBG("key %s", buf);
 	} else {
-		memset(&cp, 0, sizeof(cp));
+		u8 r[16];
+
+		swap128(conn->prnd, r);
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
+
+		smp_s1(tfm, conn->tk, conn->prnd, random, key);
 
-		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
+		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
+		BT_DBG("key %s", buf);
 	}
 }
 
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 06/15] Bluetooth: Add SMP confirmation structs
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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

This patch adds initial support for verifying the confirmation value
that the remote side has sent.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
 include/net/bluetooth/l2cap.h |    5 +++++
 net/bluetooth/smp.c           |   17 +++++++++++++++++
 2 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 4f4bff1..82508ed 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -307,6 +307,11 @@ struct l2cap_conn {
 
 	__u8		disc_reason;
 
+	__u8		preq[7]; /* SMP Pairing Request */
+	__u8		prsp[7]; /* SMP Pairing Response */
+	__u8		prnd[16]; /* SMP Pairing Random */
+	__u8		pcnf[16]; /* SMP Pairing Confirm */
+
 	struct l2cap_chan_list chan_list;
 };
 
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 740f579..31ee1c0 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -192,6 +192,8 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	BT_DBG("conn %p", conn);
 
+	conn->preq[0] = SMP_CMD_PAIRING_REQ;
+	memcpy(&conn->preq[1], rp, sizeof(*rp));
 	skb_pull(skb, sizeof(*rp));
 
 	rp->io_capability = 0x00;
@@ -201,17 +203,25 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 	rp->resp_key_dist = 0x00;
 	rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
 
+	conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&conn->prsp[1], rp, sizeof(*rp));
+
 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
 }
 
 static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 {
+	struct smp_cmd_pairing *rp = (void *) skb->data;
 	struct smp_cmd_pairing_confirm cp;
 
 	BT_DBG("conn %p", conn);
 
 	memset(&cp, 0, sizeof(cp));
 
+	conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&conn->prsp[1], rp, sizeof(*rp));
+	skb_pull(skb, sizeof(*rp));
+
 	smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
 }
 
@@ -270,6 +280,9 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 	cp.resp_key_dist = 0x00;
 	cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
 
+	conn->preq[0] = SMP_CMD_PAIRING_REQ;
+	memcpy(&conn->preq[1], &cp, sizeof(cp));
+
 	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
 }
 
@@ -306,6 +319,10 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 		cp.init_key_dist = 0x00;
 		cp.resp_key_dist = 0x00;
 		cp.auth_req = authreq;
+
+		conn->preq[0] = SMP_CMD_PAIRING_REQ;
+		memcpy(&conn->preq[1], &cp, sizeof(cp));
+
 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
 	} else {
 		struct smp_cmd_security_req cp;
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 05/15] Bluetooth: LE SMP Cryptoolbox functions
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Anderson Briglia, Anderson Lizardo, Bruna Moreira,
	Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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 |  122 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 122 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 7f275bf..740f579 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -24,6 +24,128 @@
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/smp.h>
+#include <linux/crypto.h>
+#include <crypto/b128ops.h>
+
+static inline void swap128(u8 src[16], u8 dst[16])
+{
+	int i;
+	for (i = 0; i < 16; i++)
+		dst[15 - i] = src[i];
+}
+
+static inline void swap56(u8 src[7], u8 dst[7])
+{
+	int i;
+	for (i = 0; i < 7; i++)
+		dst[6 - i] = src[i];
+}
+
+static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
+{
+	struct blkcipher_desc desc;
+	struct scatterlist sg;
+	int err, iv_len;
+	unsigned char iv[128];
+
+	if (tfm == NULL) {
+		BT_ERR("tfm %p", tfm);
+		return -EINVAL;
+	}
+
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	err = crypto_blkcipher_setkey(tfm, k, 16);
+	if (err) {
+		BT_ERR("cipher setkey failed: %d", err);
+		return err;
+	}
+
+	sg_init_one(&sg, r, 16);
+
+	iv_len = crypto_blkcipher_ivsize(tfm);
+	if (iv_len) {
+		memset(&iv, 0xff, iv_len);
+		crypto_blkcipher_set_iv(tfm, iv, iv_len);
+	}
+
+	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
+	if (err)
+		BT_ERR("Encrypt data error %d", err);
+
+	return err;
+}
+
+static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
+		u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
+		u8 _rat, bdaddr_t *ra, u8 res[16])
+{
+	u8 p1[16], p2[16], pair[7];
+	bdaddr_t addr;
+	int err;
+
+	/* p1 = pres || preq || _rat || _iat */
+	memset(p1, 0, 16);
+	swap56(pres, pair);
+
+	memcpy(p1, pair, 7);
+	swap56(preq, pair);
+
+	memcpy(p1 + 7, pair, 7);
+	*(p1 + 14) = _rat;
+	*(p1 + 15) = _iat;
+
+	/* p2 = padding || ia || ra */
+	memset(p2, 0, 16);
+	baswap(&addr, ia);
+	memcpy(p2 + 4, &addr, 6);
+	baswap(&addr, ra);
+	memcpy(p2 + 10, &addr, 6);
+
+	/* res = r XOR p1 */
+	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+	/* res = e(k, res) */
+	err = smp_e(tfm, k, res);
+	if (err) {
+		BT_ERR("Encrypt data error");
+		return err;
+	}
+
+	/* res = res XOR p2 */
+	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+	/* res = e(k, res) */
+	err = smp_e(tfm, k, res);
+	if (err)
+		BT_ERR("Encrypt data error");
+
+	return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
+			u8 r1[16], u8 r2[16], u8 _r[16])
+{
+	int err;
+
+	/* Just least significant octets from r1 and r2 are considered */
+	memcpy(_r, r1 + 8, 8);
+	memcpy(_r + 8, r2 + 8, 8);
+
+	err = smp_e(tfm, k, _r);
+	if (err)
+		BT_ERR("Encrypt data error");
+
+	return err;
+}
+
+static int smp_rand(u8 *buf)
+{
+	get_random_bytes(buf, 16);
+
+	return 0;
+}
 
 static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
 		u16 dlen, void *data)
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 04/15] Bluetooth: Add support for using the crypto subsystem
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes, Anderson Briglia
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

This will allow using the crypto subsystem for encrypting data. As SMP
(Security Manager Protocol) is implemented almost entirely on the host
side and the crypto module already implements the needed methods
(AES-128), it makes sense to use it.

This patch also adds a new Kconfig option to toggle the SMP support.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/hci_core.h |    2 ++
 net/bluetooth/Kconfig            |    6 ++++++
 net/bluetooth/hci_core.c         |   22 ++++++++++++++++++++++
 net/bluetooth/smp.c              |   17 +++++++++++++++--
 4 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d5d8454..e8dbde8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -161,6 +161,8 @@ struct hci_dev {
 
 	__u16			init_last_cmd;
 
+	struct crypto_blkcipher	*tfm;
+
 	struct inquiry_cache	inq_cache;
 	struct hci_conn_hash	conn_hash;
 	struct list_head	blacklist;
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index c6f9c2f..e9f40af 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -22,6 +22,7 @@ menuconfig BT
 	     BNEP Module (Bluetooth Network Encapsulation Protocol)
 	     CMTP Module (CAPI Message Transport Protocol)
 	     HIDP Module (Human Interface Device Protocol)
+	     SMP Module (Security Manager Protocol)
 
 	  Say Y here to compile Bluetooth support into the kernel or say M to
 	  compile it as module (bluetooth).
@@ -35,11 +36,16 @@ config BT_L2CAP
 	bool "L2CAP protocol support"
 	depends on BT
 	select CRC16
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_AES
 	help
 	  L2CAP (Logical Link Control and Adaptation Protocol) provides
 	  connection oriented and connection-less data transport.  L2CAP
 	  support is required for most Bluetooth applications.
 
+	  Also included is support for SMP (Security Manager Protocol) which
+	  is the security layer on top of LE (Low Energy) links.
+
 config BT_SCO
 	bool "SCO links support"
 	depends on BT
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b372fb8..ff67843 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -42,6 +42,7 @@
 #include <linux/notifier.h>
 #include <linux/rfkill.h>
 #include <linux/timer.h>
+#include <linux/crypto.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -60,6 +61,8 @@ static void hci_notify(struct hci_dev *hdev, int event);
 
 static DEFINE_RWLOCK(hci_task_lock);
 
+static int enable_smp;
+
 /* HCI device list */
 LIST_HEAD(hci_dev_list);
 DEFINE_RWLOCK(hci_dev_list_lock);
@@ -1077,6 +1080,14 @@ static void hci_cmd_timer(unsigned long arg)
 	tasklet_schedule(&hdev->cmd_task);
 }
 
+static struct crypto_blkcipher *alloc_cypher(void)
+{
+	if (enable_smp)
+		return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+
+	return ERR_PTR(-ENOTSUPP);
+}
+
 /* Register HCI device */
 int hci_register_dev(struct hci_dev *hdev)
 {
@@ -1155,6 +1166,11 @@ int hci_register_dev(struct hci_dev *hdev)
 	if (!hdev->workqueue)
 		goto nomem;
 
+	hdev->tfm = alloc_cypher();
+	if (IS_ERR(hdev->tfm))
+		BT_INFO("Failed to load transform for ecb(aes): %ld",
+							PTR_ERR(hdev->tfm));
+
 	hci_register_sysfs(hdev);
 
 	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -1203,6 +1219,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
 					!test_bit(HCI_SETUP, &hdev->flags))
 		mgmt_index_removed(hdev->id);
 
+	if (!IS_ERR(hdev->tfm))
+		crypto_free_blkcipher(hdev->tfm);
+
 	hci_notify(hdev, HCI_DEV_UNREG);
 
 	if (hdev->rfkill) {
@@ -2037,3 +2056,6 @@ static void hci_cmd_task(unsigned long arg)
 		}
 	}
 }
+
+module_param(enable_smp, bool, 0644);
+MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 0d04c7a..7f275bf 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -157,6 +157,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 
 	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
 
+	if (IS_ERR(conn->hcon->hdev->tfm))
+		return PTR_ERR(conn->hcon->hdev->tfm);
+
 	switch (sec_level) {
 	case BT_SECURITY_MEDIUM:
 		/* Encrypted, no MITM protection */
@@ -197,6 +200,12 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 	__u8 reason;
 	int err = 0;
 
+	if (IS_ERR(conn->hcon->hdev->tfm)) {
+		err = PTR_ERR(conn->hcon->hdev->tfm);
+		reason = SMP_PAIRING_NOTSUPP;
+		goto done;
+	}
+
 	skb_pull(skb, sizeof(code));
 
 	switch (code) {
@@ -232,11 +241,15 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 		BT_DBG("Unknown command code 0x%2.2x", code);
 
 		reason = SMP_CMD_NOTSUPP;
-		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
-								&reason);
 		err = -EOPNOTSUPP;
+		goto done;
 	}
 
+done:
+	if (reason)
+		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+								&reason);
+
 	kfree_skb(skb);
 	return err;
 }
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 03/15] Bluetooth: simple SMP pairing negotiation
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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>
---
 include/net/bluetooth/smp.h |   17 +++++++
 net/bluetooth/smp.c         |  106 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 118 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 36bdd6e..111853a 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -38,6 +38,23 @@ struct smp_cmd_pairing {
 	__u8	resp_key_dist;
 } __packed;
 
+#define SMP_IO_DISPLAY_ONLY	0x00
+#define SMP_IO_DISPLAY_YESNO	0x01
+#define SMP_IO_KEYBOARD_ONLY	0x02
+#define SMP_IO_NO_INPUT_OUTPUT	0x03
+#define SMP_IO_KEYBOARD_DISPLAY	0x04
+
+#define SMP_OOB_NOT_PRESENT	0x00
+#define SMP_OOB_PRESENT		0x01
+
+#define SMP_DIST_ENC_KEY	0x01
+#define SMP_DIST_ID_KEY		0x02
+#define SMP_DIST_SIGN		0x04
+
+#define SMP_AUTH_NONE		0x00
+#define SMP_AUTH_BONDING	0x01
+#define SMP_AUTH_MITM		0x04
+
 #define SMP_CMD_PAIRING_CONFIRM	0x03
 struct smp_cmd_pairing_confirm {
 	__u8	confirm_val[16];
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 8b67a56..0d04c7a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -64,6 +64,93 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 	hci_send_acl(conn->hcon, skb, 0);
 }
 
+static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_pairing *rp = (void *) skb->data;
+
+	BT_DBG("conn %p", conn);
+
+	skb_pull(skb, sizeof(*rp));
+
+	rp->io_capability = 0x00;
+	rp->oob_flag = 0x00;
+	rp->max_key_size = 16;
+	rp->init_key_dist = 0x00;
+	rp->resp_key_dist = 0x00;
+	rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+
+	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
+}
+
+static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_pairing_confirm cp;
+
+	BT_DBG("conn %p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+}
+
+static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+	if (conn->hcon->out) {
+		struct smp_cmd_pairing_random random;
+
+		memset(&random, 0, sizeof(random));
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
+								&random);
+	} else {
+		struct smp_cmd_pairing_confirm confirm;
+
+		memset(&confirm, 0, sizeof(confirm));
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
+								&confirm);
+	}
+}
+
+static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_pairing_random cp;
+
+	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+	skb_pull(skb, sizeof(cp));
+
+	if (conn->hcon->out) {
+		/* FIXME: start encryption */
+	} else {
+		memset(&cp, 0, sizeof(cp));
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
+	}
+}
+
+static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_security_req *rp = (void *) skb->data;
+	struct smp_cmd_pairing cp;
+
+	BT_DBG("conn %p", conn);
+
+	skb_pull(skb, sizeof(*rp));
+	memset(&cp, 0, sizeof(cp));
+
+	cp.io_capability = 0x00;
+	cp.oob_flag = 0x00;
+	cp.max_key_size = 16;
+	cp.init_key_dist = 0x00;
+	cp.resp_key_dist = 0x00;
+	cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
+
+	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+}
+
 int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 {
 	__u8 authreq;
@@ -114,24 +201,33 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	switch (code) {
 	case SMP_CMD_PAIRING_REQ:
-		reason = SMP_PAIRING_NOTSUPP;
-		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
-								&reason);
-		err = -EOPNOTSUPP;
+		smp_cmd_pairing_req(conn, skb);
 		break;
 
 	case SMP_CMD_PAIRING_FAIL:
 		break;
 
 	case SMP_CMD_PAIRING_RSP:
+		smp_cmd_pairing_rsp(conn, skb);
+		break;
+
+	case SMP_CMD_SECURITY_REQ:
+		smp_cmd_security_req(conn, skb);
+		break;
+
 	case SMP_CMD_PAIRING_CONFIRM:
+		smp_cmd_pairing_confirm(conn, skb);
+		break;
+
 	case SMP_CMD_PAIRING_RANDOM:
+		smp_cmd_pairing_random(conn, skb);
+		break;
+
 	case SMP_CMD_ENCRYPT_INFO:
 	case SMP_CMD_MASTER_IDENT:
 	case SMP_CMD_IDENT_INFO:
 	case SMP_CMD_IDENT_ADDR_INFO:
 	case SMP_CMD_SIGN_INFO:
-	case SMP_CMD_SECURITY_REQ:
 	default:
 		BT_DBG("Unknown command code 0x%2.2x", code);
 
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 02/15] Bluetooth: Start SMP procedure
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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 |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index efcef0d..66988b8 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -54,6 +54,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
 
 int disable_ertm;
 
@@ -684,6 +685,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 			l2cap_sock_clear_timer(sk);
 			sk->sk_state = BT_CONNECTED;
 			sk->sk_state_change(sk);
+			if (smp_conn_security(conn, l2cap_pi(sk)->sec_level))
+				BT_DBG("Insufficient security");
 		}
 
 		if (sk->sk_type != SOCK_SEQPACKET &&
@@ -3673,6 +3676,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 		l2cap_conless_channel(conn, psm, skb);
 		break;
 
+	case L2CAP_CID_SMP:
+		if (smp_sig_channel(conn, skb))
+			l2cap_conn_del(conn->hcon, EACCES);
+		break;
+
 	default:
 		l2cap_data_channel(conn, cid, skb);
 		break;
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 01/15] Bluetooth: Implement the first SMP commands
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <cover.1298307667.git.vinicius.gomes@openbossa.org>

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

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 |   26 ++++++++
 net/bluetooth/Makefile      |    2 +-
 net/bluetooth/smp.c         |  146 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 173 insertions(+), 1 deletions(-)
 create mode 100644 net/bluetooth/smp.c

diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 8f2edbf..36bdd6e 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -1,3 +1,25 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
 #ifndef __SMP_H
 #define __SMP_H
 
@@ -73,4 +95,8 @@ struct smp_cmd_security_req {
 #define SMP_UNSPECIFIED		0x08
 #define SMP_REPEATED_ATTEMPTS		0x09
 
+/* SMP Commands */
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+
 #endif /* __SMP_H */
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index f04fe9a..9b67f3d 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -9,5 +9,5 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
 obj-$(CONFIG_BT_HIDP)	+= hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-bluetooth-$(CONFIG_BT_L2CAP)	+= l2cap_core.o l2cap_sock.o
+bluetooth-$(CONFIG_BT_L2CAP)	+= l2cap_core.o l2cap_sock.o smp.o
 bluetooth-$(CONFIG_BT_SCO)	+= sco.o
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644
index 0000000..8b67a56
--- /dev/null
+++ b/net/bluetooth/smp.c
@@ -0,0 +1,146 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
+
+static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
+		u16 dlen, void *data)
+{
+	struct sk_buff *skb;
+	struct l2cap_hdr *lh;
+	int len;
+
+	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
+
+	if (len > conn->mtu)
+		return NULL;
+
+	skb = bt_skb_alloc(len, GFP_ATOMIC);
+	if (!skb)
+		return NULL;
+
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->len = cpu_to_le16(sizeof(code) + dlen);
+	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+
+	memcpy(skb_put(skb, dlen), data, dlen);
+
+	return skb;
+}
+
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
+{
+	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+
+	BT_DBG("code 0x%2.2x", code);
+
+	if (!skb)
+		return;
+
+	hci_send_acl(conn->hcon, skb, 0);
+}
+
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+{
+	__u8 authreq;
+
+	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
+
+	switch (sec_level) {
+	case BT_SECURITY_MEDIUM:
+		/* Encrypted, no MITM protection */
+		authreq = HCI_AT_NO_BONDING_MITM;
+		break;
+
+	case BT_SECURITY_HIGH:
+		/* Bonding, MITM protection */
+		authreq = HCI_AT_GENERAL_BONDING_MITM;
+		break;
+
+	case BT_SECURITY_LOW:
+	default:
+		return 1;
+	}
+
+	if (conn->hcon->link_mode & HCI_LM_MASTER) {
+		struct smp_cmd_pairing cp;
+		cp.io_capability = 0x00;
+		cp.oob_flag = 0x00;
+		cp.max_key_size = 16;
+		cp.init_key_dist = 0x00;
+		cp.resp_key_dist = 0x00;
+		cp.auth_req = authreq;
+		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+	} else {
+		struct smp_cmd_security_req cp;
+		cp.auth_req = authreq;
+		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
+	}
+
+	return 0;
+}
+
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	__u8 code = skb->data[0];
+	__u8 reason;
+	int err = 0;
+
+	skb_pull(skb, sizeof(code));
+
+	switch (code) {
+	case SMP_CMD_PAIRING_REQ:
+		reason = SMP_PAIRING_NOTSUPP;
+		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+								&reason);
+		err = -EOPNOTSUPP;
+		break;
+
+	case SMP_CMD_PAIRING_FAIL:
+		break;
+
+	case SMP_CMD_PAIRING_RSP:
+	case SMP_CMD_PAIRING_CONFIRM:
+	case SMP_CMD_PAIRING_RANDOM:
+	case SMP_CMD_ENCRYPT_INFO:
+	case SMP_CMD_MASTER_IDENT:
+	case SMP_CMD_IDENT_INFO:
+	case SMP_CMD_IDENT_ADDR_INFO:
+	case SMP_CMD_SIGN_INFO:
+	case SMP_CMD_SECURITY_REQ:
+	default:
+		BT_DBG("Unknown command code 0x%2.2x", code);
+
+		reason = SMP_CMD_NOTSUPP;
+		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+								&reason);
+		err = -EOPNOTSUPP;
+	}
+
+	kfree_skb(skb);
+	return err;
+}
-- 
1.7.4.1


^ permalink raw reply related

* [bluetooth-next 00/15] SMP Just Works Implementation
From: Vinicius Costa Gomes @ 2011-02-21 17:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

Hi,

This patch series implement the Just Works SMP procedures for LE links.

These patches can also be reached from here[1].


Cheers,
--
Vinicius

[1] http://git.infradead.org/users/vcgomes/linux-2.6.git (for-next branch)

Anderson Briglia (7):
  Bluetooth: Implement the first SMP commands
  Bluetooth: Start SMP procedure
  Bluetooth: simple SMP pairing negotiation
  Bluetooth: LE SMP Cryptoolbox functions
  Bluetooth: Add SMP confirmation structs
  Bluetooth: Add SMP confirmation checks methods
  Bluetooth: Minor fix in SMP methods

Vinicius Costa Gomes (8):
  Bluetooth: Add support for using the crypto subsystem
  Bluetooth: Add support for LE Start Encryption
  Bluetooth: Add support for resuming socket when SMP is finished
  Bluetooth: Fix initial security level of LE links
  Bluetooth: Update the security level when link is encrypted
  Bluetooth: Add support for Pairing features exchange
  Bluetooth: Add support for SMP timeout
  Bluetooth: Add key size checks for SMP

 include/net/bluetooth/hci.h      |   34 +++
 include/net/bluetooth/hci_core.h |   10 +
 include/net/bluetooth/l2cap.h    |    9 +
 include/net/bluetooth/smp.h      |   46 ++++
 net/bluetooth/Kconfig            |    6 +
 net/bluetooth/Makefile           |    2 +-
 net/bluetooth/hci_conn.c         |   47 ++++
 net/bluetooth/hci_core.c         |   22 ++
 net/bluetooth/hci_event.c        |   69 +++++
 net/bluetooth/l2cap_core.c       |  137 ++++++----
 net/bluetooth/l2cap_sock.c       |   17 ++
 net/bluetooth/smp.c              |  535 ++++++++++++++++++++++++++++++++++++++
 12 files changed, 876 insertions(+), 58 deletions(-)
 create mode 100644 net/bluetooth/smp.c

--
1.7.4.1


^ permalink raw reply

* Re: [PATCH 1/2] Fix Find by Type Response with start == end grp handle
From: Johan Hedberg @ 2011-02-21 16:57 UTC (permalink / raw)
  To: Bruna Moreira; +Cc: linux-bluetooth
In-Reply-To: <1298299014-31175-1-git-send-email-bruna.moreira@openbossa.org>

Hi Bruna,

On Mon, Feb 21, 2011, Bruna Moreira wrote:
> Find by type value response in attribute server was in loop when the
> start/end grp handles from a primary service had same values.
> 
> Initializing end grp handle with start handle makes the special check
> when end grp handle was zero unnecessary so it was removed.
> ---
>  src/attrib-server.c |    9 +++------
>  1 files changed, 3 insertions(+), 6 deletions(-)

Both patches have been pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [RFC v2 00/14] Store UUID-128 on host order
From: Johan Hedberg @ 2011-02-21 16:54 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: Anderson Lizardo, Claudio Takahasi, linux-bluetooth,
	Marcel Holtmann
In-Reply-To: <AANLkTimR3cpHEVBUOrPH9LRnmszNdmfg37hN__PWkYUQ@mail.gmail.com>

Hi Luiz,

On Mon, Feb 21, 2011, Luiz Augusto von Dentz wrote:
> > Just throwing my own bits on this: I think making the internal
> > representation for uuid_t consistent is important to avoid bugs when
> > handling the different UUID types.
> >
> > currently uuid_t stores 16/32-bit uuids and 128-bit uuid differently.
> 
> The problem is not the internal representation, but things like this:
> 
> -       sdp_uuid128_create(&svclass_uuid, SYNCMLC_UUID);
> +       ntoh128(SYNCMLC_UUID, &h128);
> +       sdp_uuid128_create(&svclass_uuid, &h128);
> 
> This means the API has changed, it now takes host order where it used
> to be network order. We could have a new function e.g.
> sdp_uuid128h_create to handle such cases and not break existing
> applications using this API.

In this particular case the prefix sdp_ already implies that this is for
SDP and shouldn't be used in other code. I think what makes sense (and
Marcel supported it in IRC) is to a new bt_uuid_t struct and bt_uuid_*
helper functions which internally store everything in host byte order.
Then in the first phase we can make the ATT code use the new API and
later in a second phase start converting existing SDP code to use it.

Johan

^ permalink raw reply

* [PATCH 2/2] Fix end grp handle on Find By Type response
From: Bruna Moreira @ 2011-02-21 14:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1298299014-31175-1-git-send-email-bruna.moreira@openbossa.org>

The attribute server was incorrectly setting the end group handle of the
last attribute to 0xFFFF on Find By Type response (used by Discover
Primary Service by UUID).
---
 src/attrib-server.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 2eb800f..7ec0f56 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -486,13 +486,6 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 		}
 	}
 
-	if (range) {
-		if (l == NULL) {
-			/* Avoids another iteration */
-			range->end = 0xFFFF;
-		}
-	}
-
 	if (matches == NULL)
 		return enc_error_resp(ATT_OP_FIND_BY_TYPE_REQ, start,
 				ATT_ECODE_ATTR_NOT_FOUND, opdu, mtu);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/2] Fix Find by Type Response with start == end grp handle
From: Bruna Moreira @ 2011-02-21 14:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira

Find by type value response in attribute server was in loop when the
start/end grp handles from a primary service had same values.

Initializing end grp handle with start handle makes the special check
when end grp handle was zero unnecessary so it was removed.
---
 src/attrib-server.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 4285f6e..2eb800f 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -469,6 +469,9 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 
 			range = g_new0(struct att_range, 1);
 			range->start = a->handle;
+			/* It is allowed to have end group handle the same as
+			 * start handle, for groups with only one attribute. */
+			range->end = a->handle;
 
 			matches = g_slist_append(matches, range);
 		} else if (range) {
@@ -487,12 +490,6 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 		if (l == NULL) {
 			/* Avoids another iteration */
 			range->end = 0xFFFF;
-		} else if (range->end == 0) {
-			/* Broken requests: requested End Handle is not
-			 * 0xFFFF. Given handle is in the middle of a
-			 * service definition. */
-			matches = g_slist_remove(matches, range);
-			g_free(range);
 		}
 	}
 
-- 
1.7.0.4


^ permalink raw reply related

* Problem with an Apple bluetooth keyboard
From: Daniel O'Connor @ 2011-02-21 13:58 UTC (permalink / raw)
  To: linux-bluetooth

Hi,
I have an Apple BT keyboard talking to Ubuntu 10.04 and it only works if I unplug and replug the dongle.

dmesg shows the following :-

[22723.580234] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[22723.697163] apple 0005:05AC:0239.0002: parse failed
[22723.697172] apple: probe of 0005:05AC:0239.0002 failed with error -14

<unplug/replug USB BT dongle.

[22727.040345] usb 3-1: USB disconnect, address 2
[22727.041256] btusb_intr_complete: hci0 urb ffff880037286840 failed to resubmit (19)
[22727.041272] btusb_bulk_complete: hci0 urb ffff8800372860c0 failed to resubmit (19)
[22727.042257] btusb_bulk_complete: hci0 urb ffff880037286900 failed to resubmit (19)
[22727.042574] btusb_send_frame: hci0 urb ffff88002bf97a80 submission failed
[22728.784680] usb 3-1: new full speed USB device using uhci_hcd and address 3
[22729.170802] usb 3-1: configuration #1 chosen from 1 choice
[22733.044904] input: darius’s keyboard as /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:40/input8
[22733.045006] apple 0005:05AC:0239.0003: input,hidraw1: BLUETOOTH HID v0.50 Keyboard [darius’s keyboard] on 00:10:DC:57:76:BE

Is there some command I can run to re-probe it as a work around? Or perhaps some debugging I can enable to find out exactly what is going wrong.

Thanks.

--
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
 -- Andrew Tanenbaum
GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C


^ permalink raw reply

* Re: [RFC v2 00/14] Store UUID-128 on host order
From: Luiz Augusto von Dentz @ 2011-02-21 13:52 UTC (permalink / raw)
  To: Anderson Lizardo
  Cc: Claudio Takahasi, linux-bluetooth, Johan Hedberg, Marcel Holtmann
In-Reply-To: <AANLkTi=ghX3SS0CUZDKM4pwOt9bPJBnRZGA3cRojwOgs@mail.gmail.com>

Hi,

On Mon, Feb 21, 2011 at 3:43 PM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi,
>
> On Mon, Feb 21, 2011 at 10:14 AM, Claudio Takahasi
> <claudio.takahasi@openbossa.org> wrote:
>> On Sat, Feb 19, 2011 at 6:07 PM, Luiz Augusto von Dentz
>>> IMO it would be easier to have specific functions for uuid128 that can
>>> take data in host order, so that we don't break existing API. Note
>>> that the internal representation could be changed to host order, that
>>> is fine, but then you convert the existing function to do the
>>> conversion internally without breaking compatibility.
>>
>> Yes, it is easier. It will be necessary to add a function to convert
>> from little endian to big endian for ATT when the data is received.
>> I am not changing the API, it changes only the internal
>> representation(to host order) of the UUID128 values.
>
> Just throwing my own bits on this: I think making the internal
> representation for uuid_t consistent is important to avoid bugs when
> handling the different UUID types.
>
> currently uuid_t stores 16/32-bit uuids and 128-bit uuid differently.

The problem is not the internal representation, but things like this:

-       sdp_uuid128_create(&svclass_uuid, SYNCMLC_UUID);
+       ntoh128(SYNCMLC_UUID, &h128);
+       sdp_uuid128_create(&svclass_uuid, &h128);

This means the API has changed, it now takes host order where it used
to be network order. We could have a new function e.g.
sdp_uuid128h_create to handle such cases and not break existing
applications using this API.

-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Problem with an Apple bluetooth keyboard
From: Daniel O'Connor @ 2011-02-21 13:45 UTC (permalink / raw)
  To: linux-bluetooth

Hi,
I have an Apple BT keyboard talking to Ubuntu 10.04 and it only works if I unplug and replug the dongle.

dmesg shows the following :-

[22723.580234] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[22723.697163] apple 0005:05AC:0239.0002: parse failed
[22723.697172] apple: probe of 0005:05AC:0239.0002 failed with error -14

<unplug/replug USB BT dongle.

[22727.040345] usb 3-1: USB disconnect, address 2
[22727.041256] btusb_intr_complete: hci0 urb ffff880037286840 failed to resubmit (19)
[22727.041272] btusb_bulk_complete: hci0 urb ffff8800372860c0 failed to resubmit (19)
[22727.042257] btusb_bulk_complete: hci0 urb ffff880037286900 failed to resubmit (19)
[22727.042574] btusb_send_frame: hci0 urb ffff88002bf97a80 submission failed
[22728.784680] usb 3-1: new full speed USB device using uhci_hcd and address 3
[22729.170802] usb 3-1: configuration #1 chosen from 1 choice
[22733.044904] input: darius’s keyboard as /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:40/input8
[22733.045006] apple 0005:05AC:0239.0003: input,hidraw1: BLUETOOTH HID v0.50 Keyboard [darius’s keyboard] on 00:10:DC:57:76:BE

Is there some command I can run to re-probe it as a work around? Or perhaps some debugging I can enable to find out exactly what is going wrong.

Thanks.

--
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
  -- Andrew Tanenbaum
GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C







^ permalink raw reply

* Re: [RFC v2 00/14] Store UUID-128 on host order
From: Anderson Lizardo @ 2011-02-21 13:43 UTC (permalink / raw)
  To: Claudio Takahasi
  Cc: Luiz Augusto von Dentz, linux-bluetooth, Johan Hedberg,
	Marcel Holtmann
In-Reply-To: <AANLkTimjYJTVq5dgmisV8c74rZAvpmpHL=g78feOG-_T@mail.gmail.com>

Hi,

On Mon, Feb 21, 2011 at 10:14 AM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> On Sat, Feb 19, 2011 at 6:07 PM, Luiz Augusto von Dentz
>> IMO it would be easier to have specific functions for uuid128 that can
>> take data in host order, so that we don't break existing API. Note
>> that the internal representation could be changed to host order, that
>> is fine, but then you convert the existing function to do the
>> conversion internally without breaking compatibility.
>
> Yes, it is easier. It will be necessary to add a function to convert
> from little endian to big endian for ATT when the data is received.
> I am not changing the API, it changes only the internal
> representation(to host order) of the UUID128 values.

Just throwing my own bits on this: I think making the internal
representation for uuid_t consistent is important to avoid bugs when
handling the different UUID types.

currently uuid_t stores 16/32-bit uuids and 128-bit uuid differently.

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

^ permalink raw reply

* Re: [PATCH 2/4] HCI command to remove device from LE White List
From: Claudio Takahasi @ 2011-02-21 13:29 UTC (permalink / raw)
  To: Sumit Kumar BAJPAI, linux-bluetooth@vger.kernel.org
In-Reply-To: <20110131082853.GA10011@jh-x301>

Hi Sumit,

On Mon, Jan 31, 2011 at 8:28 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi,
>
> On Tue, Jan 25, 2011, Sumit Kumar BAJPAI wrote:
>> Thanks Anderson for review comments.
>> Posting patch again.
>
> The latest versions of these patches seem to be scattered around and not
> formated properly as something that could be applied with git am (at
> least the commit messages aren't right). Could you resend the latest
> versions of all of the patches in a new thread using git send-email?
>
> Johan
> --
> 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
>

Could you please resend the patches? We need the white list patches for testing.

BR,
Claudio

^ permalink raw reply

* Re: [RFC v2 00/14] Store UUID-128 on host order
From: Claudio Takahasi @ 2011-02-21 13:14 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Johan Hedberg, Marcel Holtmann
In-Reply-To: <AANLkTinzZ+nNSx6qq0xMXO8ZVLt5r-r0pgcjRBa7MaxY@mail.gmail.com>

Hi Luiz,

On Sat, Feb 19, 2011 at 6:07 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Claudio,
>
> On Sat, Feb 19, 2011 at 12:29 AM, Claudio Takahasi
> <claudio.takahasi@openbossa.org> wrote:
>> It must NOT be included in the next release until proper testing.
>>
>> Any good soul wants to test it if I am not breaking SDP?
>>
>> The following patches convert the internal UUID128 values representation
>> to host order. Currently, SDP functions use host order to store UUID-16
>> /UUID32 and network order to store UUID-128 values. The reason is to
>> keep the consistency and re-use the UUID functions for ATT protocol
>> which uses little endian.
>>
>> Changes from the first RFC:
>> =C2=A0- Changes sdptool
>> =C2=A0- Changes SDP XML parsing function
>> =C2=A0- Changes attribute example
>>
>> Claudio Takahasi (14):
>> =C2=A0Move 64 and 128 bits byte order functions to bluetooth.h
>> =C2=A0Use host byte order when converting UUID16/32 to UUID128
>> =C2=A0Add att_get_u128
>> =C2=A0Convert UUID128 value to host order when extracting SDP data
>> =C2=A0Convert to network order before use it on sdp_uuid128_to_uuid
>> =C2=A0Convert from host to network order before to print UUID128 values
>> =C2=A0Convert from network to host order on bt_string2uuid function
>> =C2=A0Change UUID128 host order on SDP PDU generation function
>> =C2=A0Replace UUID128 values from char array to uint128_t on sdptool
>> =C2=A0Create UUID128 on host order on sdptool
>> =C2=A0Change SDP XML parser to create UUID128 values on host order
>> =C2=A0Convert from little endian to host order when parsing EIR data
>> =C2=A0Add att_put_u128
>> =C2=A0Change Attribute example to create UUID128 on host order
>>
>> =C2=A0attrib/att.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 16 ++++--
>> =C2=A0attrib/att.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 17 ++++++
>> =C2=A0attrib/example.c =C2=A0 =C2=A0 | =C2=A0 24 +++++---
>> =C2=A0attrib/gatt.c =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 14 +++--
>> =C2=A0attrib/gatttool.c =C2=A0 =C2=A0| =C2=A0 =C2=A06 ++-
>> =C2=A0attrib/interactive.c | =C2=A0 =C2=A01 +
>> =C2=A0health/hdp_manager.c | =C2=A0 =C2=A01 +
>> =C2=A0health/mcap_sync.c =C2=A0 | =C2=A0 17 ------
>> =C2=A0lib/bluetooth.h =C2=A0 =C2=A0 =C2=A0| =C2=A0 41 ++++++++++++++
>> =C2=A0lib/sdp.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0108 +++=
+++++++++++-----------------------
>> =C2=A0lib/sdp.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 =C2=A0=
4 --
>> =C2=A0src/event.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 =C2=A06 +--
>> =C2=A0src/glib-helper.c =C2=A0 =C2=A0| =C2=A0 31 ++++++-----
>> =C2=A0src/sdp-xml.c =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 74 +++++++++++--=
------------
>> =C2=A0test/hciemu.c =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 16 ------
>> =C2=A0tools/sdptool.c =C2=A0 =C2=A0 =C2=A0| =C2=A0145 ++++++++++++++++++=
++++++++++++-------------------
>> =C2=A016 files changed, 280 insertions(+), 241 deletions(-)
>>
>> --
>> 1.7.4.1
>
> IMO it would be easier to have specific functions for uuid128 that can
> take data in host order, so that we don't break existing API. Note
> that the internal representation could be changed to host order, that
> is fine, but then you convert the existing function to do the
> conversion internally without breaking compatibility.
>
> --
> Luiz Augusto von Dentz
> Computer Engineer
>

Yes, it is easier. It will be necessary to add a function to convert
from little endian to big endian for ATT when the data is received.
I am not changing the API, it changes only the internal
representation(to host order) of the UUID128 values.


We got "blessing" from Marcel to proceed with this change, but I can
implement the easier solution ;-)

Marcel/Johan: comments?

BR,
Claudio

^ permalink raw reply

* Re: [PATCH 2/2] bt hidp: send Output reports using SET_REPORT on the Control channel
From: Jiri Kosina @ 2011-02-21 12:50 UTC (permalink / raw)
  To: Alan Ott
  Cc: Antonio Ospite, linux-input, linux-bluetooth, Marcel Holtmann,
	Gustavo F. Padovan, Bastien Nocera, Jim Paris, pascal@pabr.org
In-Reply-To: <4D61DFE0.5020400@signal11.us>

On Sun, 20 Feb 2011, Alan Ott wrote:

> On 02/20/2011 12:26 PM, Antonio Ospite wrote:
> > The current implementation of hidp_output_raw_report() relies only on
> > the Control channel even for Output reports, and the BT HID
> > specification [1] does not mention using the DATA message for Output
> > reports on the Control channel (see section 7.9.1 and also Figure 11:
> > SET_ Flow Chart), so let us just use SET_REPORT.
> > 
> > This also fixes sending Output reports to some devices (like Sony
> > Sixaxis) which are not able to handle DATA messages on the Control
> > channel.
> > 
> > Ideally hidp_output_raw_report() could be improved to use this scheme:
> >    Feature Report -- SET_REPORT on the Control channel
> >    Output Report  -- DATA on the Interrupt channel
> > for more efficiency, but as said above, right now only the Control
> > channel is used.
> > 
> > [1] http://www.bluetooth.com/Specification%20Documents/HID_SPEC_V10.pdf
> > 
> >   	case HID_OUTPUT_REPORT:
> > -		report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
> > +		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
> >    
> 
> I think this is right. Section 7.4[.0] says that SET_ and GET_ requests return
> with HANDSHAKE. Section 7.4.9 says that DATA does _not_ return a HANDSHAKE. My
> patch to hidp_output_raw_report() relies on getting a HANDSHAKE back, so it
> wouldn't have worked with BT devices that take output reports. Since I don't
> have any that do, I couldn't test it. (And it was like that when I got here :)
> )
> 
> For the whole set:
> Acked-by: Alan Ott <alan@signal11.us>

Agreed.

As an author of the original code, I agree with the change. But as it is 
in net/bluetooth, I'd at least have Acked-by from some of the Bluetooth 
folks before I take it through my tree.

Marcel? Gustavo?

Thanks,

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply

* Re: [PATCH 1/2] hid-sony.c: Fix sending Output reports to the Sixaxis
From: Jiri Kosina @ 2011-02-21 12:49 UTC (permalink / raw)
  To: Antonio Ospite
  Cc: linux-input, linux-bluetooth, Marcel Holtmann, Gustavo F. Padovan,
	Bastien Nocera, Alan Ott, Jim Paris, pascal@pabr.org
In-Reply-To: <1298222806-19433-2-git-send-email-ospite@studenti.unina.it>

On Sun, 20 Feb 2011, Antonio Ospite wrote:

> The Sixaxis does not want the report_id as part of the data packet in
> Output reports, so we have to discard buf[0] when sending the actual
> control message.
> 
> Add also some documentation about that and about why
> hdev->hid_output_raw_report needs to be overridden.
> 
> Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>

Applied, thanks Antonio.

> ---
>  drivers/hid/hid-sony.c |   20 ++++++++++++++++++++
>  1 files changed, 20 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
> index 68d7b36..93819a0 100644
> --- a/drivers/hid/hid-sony.c
> +++ b/drivers/hid/hid-sony.c
> @@ -46,6 +46,16 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
>  	return rdesc;
>  }
>  
> +/*
> + * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
> + * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
> + * so we need to override that forcing HID Output Reports on the Control EP.
> + *
> + * There is also another issue about HID Output Reports via USB, the Sixaxis
> + * does not want the report_id as part of the data packet, so we have to
> + * discard buf[0] when sending the actual control message, even for numbered
> + * reports, humpf!
> + */
>  static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
>  		size_t count, unsigned char report_type)
>  {
> @@ -55,6 +65,12 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
>  	int report_id = buf[0];
>  	int ret;
>  
> +	if (report_type == HID_OUTPUT_REPORT) {
> +		/* Don't send the Report ID */
> +		buf++;
> +		count--;
> +	}
> +
>  	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
>  		HID_REQ_SET_REPORT,
>  		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
> @@ -62,6 +78,10 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
>  		interface->desc.bInterfaceNumber, buf, count,
>  		USB_CTRL_SET_TIMEOUT);
>  
> +	/* Count also the Report ID, in case of an Output report. */
> +	if (ret > 0 && report_type == HID_OUTPUT_REPORT)
> +		ret++;
> +
>  	return ret;
>  }
>  
> -- 
> 1.7.4.1
> 

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply

* RE: BUG in Mobile initiated pairing
From: sachin.athanikar @ 2011-02-21  8:13 UTC (permalink / raw)
  To: padovan; +Cc: linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 1771 bytes --]

Hi Gustavo,

Thanks for your precious time and response.

I had modified the agent.c provided in the test folder of BlueZ to support mobile initiated pairing.

I have attached the

1. modified code (agent.c)
2. DBUS monitor logs

The pairing is successful, but the property changed event "Paired" is not seen in DBUS monitor.

Please let me know your comments on this program.

Yes, in Ubuntu 10.10 with the support of Bluetooth-Gnome remote device initiated pairing works with all the events.

Thanks
Sachin


-----Original Message-----
From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Gustavo F. Padovan
Sent: Thursday, February 17, 2011 9:57 PM
To: Athanikar, Sachin
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: BUG in Mobile initiated pairing

Hi Sachin,

* sachin.athanikar@accenture.com <sachin.athanikar@accenture.com> [2011-02-17 20:10:38 +0530]:

> Hi Gustavo,
> Many thanks for the response.
>
> The property changed event "Paired" is not generated when the mobile initiated pairing is successful. So I am not able get an acknowledgement for successful completion of pairing process.

Yes, it is. I just tested it before reply to you.

--
Gustavo F. Padovan
http://profusion.mobi
--
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


This message is for the designated recipient only and may contain privileged, proprietary, or otherwise private information.  If you have received it in error, please notify the sender immediately and delete the original.  Any other use of the email by you is prohibited.

[-- Attachment #2: dbus-monitor-log.txt --]
[-- Type: text/plain, Size: 1037 bytes --]

signal sender=org.freedesktop.DBus -> dest=(null destination) serial=50 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.82"
   string ""
   string ":1.82"
signal sender=:1.63 -> dest=(null destination) serial=286 path=/org/bluez/3346/hci0/dev_A0_4E_04_BC_A3_79; interface=org.bluez.Device; member=PropertyChanged
   string "Connected"
   variant       boolean true
signal sender=org.freedesktop.DBus -> dest=(null destination) serial=51 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.83"
   string ""
   string ":1.83"
signal sender=org.freedesktop.DBus -> dest=(null destination) serial=52 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.83"
   string ":1.83"
   string ""
signal sender=:1.63 -> dest=(null destination) serial=288 path=/org/bluez/3346/hci0/dev_A0_4E_04_BC_A3_79; interface=org.bluez.Device; member=PropertyChanged
   string "Connected"
   variant       boolean false


[-- Attachment #3: agent.c --]
[-- Type: text/plain, Size: 15368 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>

#include <dbus/dbus.h>

static char *passkey_value = NULL;
static int passkey_delay = 0;
static int do_reject = 0;

static volatile sig_atomic_t __io_canceled = 0;
static volatile sig_atomic_t __io_terminated = 0;

static void sig_term(int sig)
{
	__io_canceled = 1;
}

static DBusHandlerResult agent_filter(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	const char *name, *old, *new;

	if (!dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS,
						"NameOwnerChanged"))
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

	if (!dbus_message_get_args(msg, NULL,
					DBUS_TYPE_STRING, &name,
					DBUS_TYPE_STRING, &old,
					DBUS_TYPE_STRING, &new,
					DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for NameOwnerChanged signal");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (!strcmp(name, "org.bluez") && *new == '\0') {
		fprintf(stderr, "Agent has been terminated\n");
		__io_terminated = 1;
	}

	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

static DBusHandlerResult request_pincode_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	DBusMessage *reply;
	const char *path;

	if (!passkey_value)
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
							DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for RequestPinCode method");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (do_reject) {
		reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "");
		goto send;
	}

	reply = dbus_message_new_method_return(msg);
	if (!reply) {
		fprintf(stderr, "Can't create reply message\n");
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}

	printf("Pincode request for device %s\n", path);

	if (passkey_delay) {
		printf("Waiting for %d seconds\n", passkey_delay);
		sleep(passkey_delay);
	}

	dbus_message_append_args(reply, DBUS_TYPE_STRING, &passkey_value,
							DBUS_TYPE_INVALID);

send:
	dbus_connection_send(conn, reply, NULL);

	dbus_connection_flush(conn);

	dbus_message_unref(reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult request_passkey_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	DBusMessage *reply;
	const char *path;
	unsigned int passkey;

	if (!passkey_value)
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
							DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for RequestPasskey method");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (do_reject) {
		reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "");
		goto send;
	}

	reply = dbus_message_new_method_return(msg);
	if (!reply) {
		fprintf(stderr, "Can't create reply message\n");
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}

	printf("Passkey request for device %s\n", path);

	if (passkey_delay) {
		printf("Waiting for %d seconds\n", passkey_delay);
		sleep(passkey_delay);
	}

	passkey = strtoul(passkey_value, NULL, 10);

	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &passkey,
							DBUS_TYPE_INVALID);

send:
	dbus_connection_send(conn, reply, NULL);

	dbus_connection_flush(conn);

	dbus_message_unref(reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult request_confirmation_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	DBusMessage *reply;
	const char *path;
	unsigned int passkey;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
						DBUS_TYPE_UINT32, &passkey,
							DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for RequestPasskey method");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (do_reject) {
		reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "");
		goto send;
	}

	reply = dbus_message_new_method_return(msg);
	if (!reply) {
		fprintf(stderr, "Can't create reply message\n");
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}

	printf("Confirmation request of %u for device %s\n", passkey, path);

	if (passkey_delay) {
		printf("Waiting for %d seconds\n", passkey_delay);
		sleep(passkey_delay);
	}

send:
	dbus_connection_send(conn, reply, NULL);

	dbus_connection_flush(conn);

	dbus_message_unref(reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult authorize_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	DBusMessage *reply;
	const char *path, *uuid;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
						DBUS_TYPE_STRING, &uuid,
							DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for Authorize method");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (do_reject) {
		reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "");
		goto send;
	}

	reply = dbus_message_new_method_return(msg);
	if (!reply) {
		fprintf(stderr, "Can't create reply message\n");
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}

	printf("Authorizing request for %s\n", path);

send:
	dbus_connection_send(conn, reply, NULL);

	dbus_connection_flush(conn);

	dbus_message_unref(reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult cancel_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	DBusMessage *reply;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for passkey Confirm method");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	printf("Request canceled\n");

	reply = dbus_message_new_method_return(msg);
	if (!reply) {
		fprintf(stderr, "Can't create reply message\n");
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}

	dbus_connection_send(conn, reply, NULL);

	dbus_connection_flush(conn);

	dbus_message_unref(reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult release_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	DBusMessage *reply;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID)) {
		fprintf(stderr, "Invalid arguments for Release method");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (!__io_canceled)
		fprintf(stderr, "Agent has been released\n");

	__io_terminated = 1;

	reply = dbus_message_new_method_return(msg);
	if (!reply) {
		fprintf(stderr, "Can't create reply message\n");
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}

	dbus_connection_send(conn, reply, NULL);

	dbus_connection_flush(conn);

	dbus_message_unref(reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult agent_message(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	if (dbus_message_is_method_call(msg, "org.bluez.Agent",
							"RequestPinCode"))
		return request_pincode_message(conn, msg, data);

	if (dbus_message_is_method_call(msg, "org.bluez.Agent",
							"RequestPasskey"))
		return request_passkey_message(conn, msg, data);

	if (dbus_message_is_method_call(msg, "org.bluez.Agent",
							"RequestConfirmation"))
		return request_confirmation_message(conn, msg, data);

	if (dbus_message_is_method_call(msg, "org.bluez.Agent", "Authorize"))
		return authorize_message(conn, msg, data);

	if (dbus_message_is_method_call(msg, "org.bluez.Agent", "Cancel"))
		return cancel_message(conn, msg, data);

	if (dbus_message_is_method_call(msg, "org.bluez.Agent", "Release"))
		return release_message(conn, msg, data);

	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

static const DBusObjectPathVTable agent_table = {
	.message_function = agent_message,
};

static int register_agent(DBusConnection *conn, const char *adapter_path,
						const char *agent_path,
						const char *capabilities)
{
	DBusMessage *msg, *reply;
	DBusError err;

	msg = dbus_message_new_method_call("org.bluez", adapter_path,
					"org.bluez.Adapter", "RegisterAgent");
	if (!msg) {
		fprintf(stderr, "Can't allocate new method call\n");
		return -1;
	}

	dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
					DBUS_TYPE_STRING, &capabilities,
					DBUS_TYPE_INVALID);

	dbus_error_init(&err);

	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);

	dbus_message_unref(msg);

	if (!reply) {
		fprintf(stderr, "Can't register agent\n");
		if (dbus_error_is_set(&err)) {
			fprintf(stderr, "%s\n", err.message);
			dbus_error_free(&err);
		}
		return -1;
	}

	dbus_message_unref(reply);

	dbus_connection_flush(conn);

	return 0;
}

static int unregister_agent(DBusConnection *conn, const char *adapter_path,
							const char *agent_path)
{
	DBusMessage *msg, *reply;
	DBusError err;

	msg = dbus_message_new_method_call("org.bluez", adapter_path,
					"org.bluez.Adapter", "UnregisterAgent");
	if (!msg) {
		fprintf(stderr, "Can't allocate new method call\n");
		return -1;
	}

	dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
							DBUS_TYPE_INVALID);

	dbus_error_init(&err);

	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);

	dbus_message_unref(msg);

	if (!reply) {
		fprintf(stderr, "Can't unregister agent\n");
		if (dbus_error_is_set(&err)) {
			fprintf(stderr, "%s\n", err.message);
			dbus_error_free(&err);
		}
		return -1;
	}

	dbus_message_unref(reply);

	dbus_connection_flush(conn);

	dbus_connection_unregister_object_path(conn, agent_path);

	return 0;
}

static int create_paired_device(DBusConnection *conn, const char *adapter_path,
						const char *agent_path,
						const char *capabilities,
						const char *device)
{
	dbus_bool_t success;
	DBusMessage *msg;

	msg = dbus_message_new_method_call("org.bluez", adapter_path,
						"org.bluez.Adapter",
						"CreatePairedDevice");
	if (!msg) {
		fprintf(stderr, "Can't allocate new method call\n");
		return -1;
	}

	dbus_message_append_args(msg, DBUS_TYPE_STRING, &device,
					DBUS_TYPE_OBJECT_PATH, &agent_path,
					DBUS_TYPE_STRING, &capabilities,
					DBUS_TYPE_INVALID);

	success = dbus_connection_send(conn, msg, NULL);

	dbus_message_unref(msg);

	if (!success) {
		fprintf(stderr, "Not enough memory for message send\n");
		return -1;
	}

	dbus_connection_flush(conn);

	return 0;
}

static char *get_default_adapter_path(DBusConnection *conn)
{
	DBusMessage *msg, *reply;
	DBusError err;
	const char *reply_path;
	char *path;

	msg = dbus_message_new_method_call("org.bluez", "/",
					"org.bluez.Manager", "DefaultAdapter");

	if (!msg) {
		fprintf(stderr, "Can't allocate new method call\n");
		return NULL;
	}

	dbus_error_init(&err);

	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);

	dbus_message_unref(msg);

	if (!reply) {
		fprintf(stderr,
			"Can't get default adapter\n");
		if (dbus_error_is_set(&err)) {
			fprintf(stderr, "%s\n", err.message);
			dbus_error_free(&err);
		}
		return NULL;
	}

	if (!dbus_message_get_args(reply, &err,
					DBUS_TYPE_OBJECT_PATH, &reply_path,
					DBUS_TYPE_INVALID)) {
		fprintf(stderr,
			"Can't get reply arguments\n");
		if (dbus_error_is_set(&err)) {
			fprintf(stderr, "%s\n", err.message);
			dbus_error_free(&err);
		}
		return NULL;
	}

	path = strdup(reply_path);

	dbus_message_unref(reply);

	dbus_connection_flush(conn);

	return path;
}

static char *get_adapter_path(DBusConnection *conn, const char *adapter)
{
	DBusMessage *msg, *reply;
	DBusError err;
	const char *reply_path;
	char *path;

	if (!adapter)
		return get_default_adapter_path(conn);

	msg = dbus_message_new_method_call("org.bluez", "/",
					"org.bluez.Manager", "FindAdapter");

	if (!msg) {
		fprintf(stderr, "Can't allocate new method call\n");
		return NULL;
	}

	dbus_message_append_args(msg, DBUS_TYPE_STRING, &adapter,
					DBUS_TYPE_INVALID);

	dbus_error_init(&err);

	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);

	dbus_message_unref(msg);

	if (!reply) {
		fprintf(stderr,
			"Can't find adapter %s\n", adapter);
		if (dbus_error_is_set(&err)) {
			fprintf(stderr, "%s\n", err.message);
			dbus_error_free(&err);
		}
		return NULL;
	}

	if (!dbus_message_get_args(reply, &err,
					DBUS_TYPE_OBJECT_PATH, &reply_path,
					DBUS_TYPE_INVALID)) {
		fprintf(stderr,
			"Can't get reply arguments\n");
		if (dbus_error_is_set(&err)) {
			fprintf(stderr, "%s\n", err.message);
			dbus_error_free(&err);
		}
		return NULL;
	}

	path = strdup(reply_path);

	dbus_message_unref(reply);

	dbus_connection_flush(conn);

	return path;
}

static void usage(void)
{
//	printf("Bluetooth agent ver %s\n\n", VERSION);

	printf("Usage:\n"
		"\tagent [--adapter adapter-path] [--path agent-path] <passkey> [<device>]\n"
		"\n");
}

static struct option main_options[] = {
	{ "adapter",	1, 0, 'a' },
	{ "path",	1, 0, 'p' },
	{ "capabilites",1, 0, 'c' },
	{ "delay",	1, 0, 'd' },
	{ "reject",	0, 0, 'r' },
	{ "help",	0, 0, 'h' },
	{ 0, 0, 0, 0 }
};

int main(int argc, char *argv[])
{
	const char *capabilities = "DisplayYesNo";
	struct sigaction sa;
	DBusConnection *conn;
	char match_string[128], default_path[128], *adapter_id = NULL;
	char *adapter_path = NULL, *agent_path = NULL, *device = NULL;

	snprintf(default_path, sizeof(default_path),
					"/org/bluez/agent_%d", getpid());

	adapter_id = "hci0"; 
	
	passkey_value = "123";

	if (!agent_path)
		agent_path = strdup(default_path);

	conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
	if (!conn) {
		fprintf(stderr, "Can't get on system bus");
		exit(1);
	}

	adapter_path = get_adapter_path(conn, adapter_id);
	if (!adapter_path)
		exit(1);

	if (!dbus_connection_register_object_path(conn, agent_path,
							&agent_table, NULL)) {
		fprintf(stderr, "Can't register object path for agent\n");
		exit(1);
	}

	if (register_agent(conn, adapter_path, agent_path,
						capabilities) < 0) {
		dbus_connection_unref(conn);
		exit(1);
	}

	if (!dbus_connection_add_filter(conn, agent_filter, NULL, NULL))
		fprintf(stderr, "Can't add signal filter");

	snprintf(match_string, sizeof(match_string),
			"interface=%s,member=NameOwnerChanged,arg0=%s",
			DBUS_INTERFACE_DBUS, "org.bluez");

	dbus_bus_add_match(conn, match_string, NULL);

	memset(&sa, 0, sizeof(sa));
	sa.sa_flags   = SA_NOCLDSTOP;
	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	while (!__io_canceled && !__io_terminated) {
		if (dbus_connection_read_write_dispatch(conn, 500) != TRUE)
			break;
	}

	if (!__io_terminated && !device)
		unregister_agent(conn, adapter_path, agent_path);

	free(adapter_path);
	free(agent_path);

	free(passkey_value);

	dbus_connection_unref(conn);

	return 0;
}

^ permalink raw reply

* Re: bluetooth kernel to bluez userspace relationship
From: Arun K. Singh @ 2011-02-21  8:04 UTC (permalink / raw)
  To: Viswanathan Sankararam; +Cc: linux-bluetooth
In-Reply-To: <AANLkTimbj=p1ecddQsTiun6LUeP8+wPnT0VLCsvsWNRb@mail.gmail.com>

Hi Vish,

> All,
> I'm new to bluetooth so please forgive me for asking this question if
> its already been answered. I understand that the linux kernel has part
> of the bluetooth stack and there is also the rest of it called Bluez
> in userspace which consists of a daemon and library. How would one
> correlate linux kernel version with the bluez userspace version?
> Meaning, how would l know say, linux-2.6.35 would work with
> Bluez-4.68.
>
> Any response would be appreciated.

unless you are looking for a specific feature in bluez-userspace you
must use latest kernel and bluez version. If you are cherry-picking an
old bluez version you need to check recent feature enhancements into
same, which may require a matching kernel version. for example for AMP
manager or Bt 3.0 stuff, you may need an ERTM enabled kernel which
comes only 2.6.35 onwards ...

Even if you intend to use an old Bluez userspace, its always advisable
to pick latest kernel ...else you need to dig ..


> Thanks
> Vish
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



--
Best Regards,
Arun K. Singh
www.crazydaks.com

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox