All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan
@ 2014-08-08  6:37 johan.hedberg
  2014-08-08  6:37 ` [PATCH 1/4] Bluetooth: Add more L2CAP convenience callbacks johan.hedberg
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: johan.hedberg @ 2014-08-08  6:37 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

With this patches we do the initial conversion of SMP to use l2cap_chan
and its related callbacks. There are many more simplifications possible
after this, but to keep the conversion minimal I haven't done those yet.
To keep the code compiling and functional between each patch the code
that introduces the initial callbacks uses a custom 0x1f CID not to
intefere with the legacy SMP CID handling. Only in the last patch which
adds fully functional SMP handling through l2cap_chan is this custom CID
converted back to the proper L2CAP_CID_SMP.

Johan

----------------------------------------------------------------
Johan Hedberg (4):
      Bluetooth: Add more L2CAP convenience callbacks
      Bluetooth: Add SMP L2CAP channel skeleton
      Bluetooth: Make AES crypto context private to SMP
      Bluetooth: Convert SMP to use l2cap_chan infrastructure

 include/net/bluetooth/hci_core.h |   2 +-
 include/net/bluetooth/l2cap.h    |  27 +++-
 net/bluetooth/hci_core.c         |  13 +-
 net/bluetooth/l2cap_core.c       |  10 --
 net/bluetooth/smp.c              | 280 +++++++++++++++++++++++++++--------
 net/bluetooth/smp.h              |   6 +-
 6 files changed, 248 insertions(+), 90 deletions(-)


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

* [PATCH 1/4] Bluetooth: Add more L2CAP convenience callbacks
  2014-08-08  6:37 [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan johan.hedberg
@ 2014-08-08  6:37 ` johan.hedberg
  2014-08-08  6:37 ` [PATCH 2/4] Bluetooth: Add SMP L2CAP channel skeleton johan.hedberg
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: johan.hedberg @ 2014-08-08  6:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

In preparation for converting SMP to use l2cap_chan it's useful to add a
few more callback helpers so that smp.c won't need to define all of its
own.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/l2cap.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 4a51e7596608..a72965f6bc2f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -838,18 +838,43 @@ static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan
 	return NULL;
 }
 
+static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
+{
+	return -ENOSYS;
+}
+
+static inline struct sk_buff *l2cap_chan_no_alloc_skb(struct l2cap_chan *chan,
+						      unsigned long hdr_len,
+						      unsigned long len, int nb)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
 static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err)
 {
 }
 
+static inline void l2cap_chan_no_close(struct l2cap_chan *chan)
+{
+}
+
 static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_state_change(struct l2cap_chan *chan,
+					      int state, int err)
+{
+}
+
 static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_suspend(struct l2cap_chan *chan)
+{
+}
+
 static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
 {
 }
-- 
1.9.3


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

* [PATCH 2/4] Bluetooth: Add SMP L2CAP channel skeleton
  2014-08-08  6:37 [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan johan.hedberg
  2014-08-08  6:37 ` [PATCH 1/4] Bluetooth: Add more L2CAP convenience callbacks johan.hedberg
@ 2014-08-08  6:37 ` johan.hedberg
  2014-08-08  6:37 ` [PATCH 3/4] Bluetooth: Make AES crypto context private to SMP johan.hedberg
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: johan.hedberg @ 2014-08-08  6:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

This patch creates the initial SMP L2CAP channels and a skeleton for
their callbacks. There is one per-adapter channel created upon adapter
registration, and then one channel per-connection created through the
new_connection callback. The channels are registered with the reserved
CID 0x1f for now in order to not conflict with existing SMP
functionality. Once everything is in place the value can be changed to
what it should be, i.e. L2CAP_CID_SMP.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci_core.h |   1 +
 include/net/bluetooth/l2cap.h    |   1 +
 net/bluetooth/smp.c              | 131 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cc2eb7730fbc..2571fc1cb1c5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -303,6 +303,7 @@ struct hci_dev {
 	__u32			req_result;
 
 	struct crypto_blkcipher	*tfm_aes;
+	void			*smp_data;
 
 	struct discovery_state	discovery;
 	struct hci_conn_hash	conn_hash;
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index a72965f6bc2f..1a037ba4b6f4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -637,6 +637,7 @@ struct l2cap_conn {
 
 	struct delayed_work	security_timer;
 	struct smp_chan		*smp_chan;
+	struct l2cap_chan	*smp;
 
 	struct list_head	chan_l;
 	struct mutex		chan_lock;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index ab07649ecc77..2362ae35a4d5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1456,8 +1456,106 @@ int smp_distribute_keys(struct l2cap_conn *conn)
 	return 0;
 }
 
+static void smp_teardown_cb(struct l2cap_chan *chan, int err)
+{
+	struct l2cap_conn *conn = chan->conn;
+
+	BT_DBG("chan %p", chan);
+
+	conn->smp = NULL;
+	l2cap_chan_put(chan);
+}
+
+static void smp_ready_cb(struct l2cap_chan *chan)
+{
+	struct l2cap_conn *conn = chan->conn;
+
+	BT_DBG("chan %p", chan);
+
+	conn->smp = chan;
+	l2cap_chan_hold(chan);
+}
+
+static struct sk_buff *smp_alloc_skb_cb(struct l2cap_chan *chan,
+					unsigned long hdr_len,
+					unsigned long len, int nb)
+{
+	struct sk_buff *skb;
+
+	skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
+	if (!skb)
+		return ERR_PTR(-ENOMEM);
+
+	skb->priority = HCI_PRIO_MAX;
+	bt_cb(skb)->chan = chan;
+
+	return skb;
+}
+
+static const struct l2cap_ops smp_chan_ops = {
+	.name			= "Security Manager",
+	.ready			= smp_ready_cb,
+	.alloc_skb		= smp_alloc_skb_cb,
+	.teardown		= smp_teardown_cb,
+
+	.new_connection		= l2cap_chan_no_new_connection,
+	.recv			= l2cap_chan_no_recv,
+	.state_change		= l2cap_chan_no_state_change,
+	.close			= l2cap_chan_no_close,
+	.defer			= l2cap_chan_no_defer,
+	.suspend		= l2cap_chan_no_suspend,
+	.resume			= l2cap_chan_no_resume,
+	.set_shutdown		= l2cap_chan_no_set_shutdown,
+	.get_sndtimeo		= l2cap_chan_no_get_sndtimeo,
+	.memcpy_fromiovec	= l2cap_chan_no_memcpy_fromiovec,
+};
+
+static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
+{
+	struct l2cap_chan *chan;
+
+	BT_DBG("pchan %p", pchan);
+
+	chan = l2cap_chan_create();
+	if (!chan)
+		return NULL;
+
+	chan->chan_type	= pchan->chan_type;
+	chan->ops	= &smp_chan_ops;
+	chan->scid	= pchan->scid;
+	chan->dcid	= chan->scid;
+	chan->imtu	= pchan->imtu;
+	chan->omtu	= pchan->omtu;
+	chan->mode	= pchan->mode;
+
+	BT_DBG("created chan %p", chan);
+
+	return chan;
+}
+
+static const struct l2cap_ops smp_root_chan_ops = {
+	.name			= "Security Manager Root",
+	.new_connection		= smp_new_conn_cb,
+
+	/* None of these are implemented for the root channel */
+	.close			= l2cap_chan_no_close,
+	.alloc_skb		= l2cap_chan_no_alloc_skb,
+	.recv			= l2cap_chan_no_recv,
+	.state_change		= l2cap_chan_no_state_change,
+	.teardown		= l2cap_chan_no_teardown,
+	.ready			= l2cap_chan_no_ready,
+	.defer			= l2cap_chan_no_defer,
+	.suspend		= l2cap_chan_no_suspend,
+	.resume			= l2cap_chan_no_resume,
+	.set_shutdown		= l2cap_chan_no_set_shutdown,
+	.get_sndtimeo		= l2cap_chan_no_get_sndtimeo,
+	.memcpy_fromiovec	= l2cap_chan_no_memcpy_fromiovec,
+};
+
 int smp_register(struct hci_dev *hdev)
 {
+	struct l2cap_chan *chan;
+
 	BT_DBG("%s", hdev->name);
 
 	hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0,
@@ -1469,15 +1567,46 @@ int smp_register(struct hci_dev *hdev)
 		return err;
 	}
 
+	chan = l2cap_chan_create();
+	if (!chan) {
+		crypto_free_blkcipher(hdev->tfm_aes);
+		hdev->tfm_aes = NULL;
+		return -ENOMEM;
+	}
+
+	/* FIXME: Using reserved 0x1f value for now - to be changed to
+	 * L2CAP_CID_SMP once all functionality is in place.
+	 */
+	l2cap_add_scid(chan, 0x1f);
+
+	l2cap_chan_set_defaults(chan);
+
+	bacpy(&chan->src, &hdev->bdaddr);
+	chan->src_type = BDADDR_LE_PUBLIC;
+	chan->state = BT_LISTEN;
+	chan->mode = L2CAP_MODE_BASIC;
+	chan->imtu = L2CAP_DEFAULT_MTU;
+	chan->ops = &smp_root_chan_ops;
+
+	hdev->smp_data = chan;
+
 	return 0;
 }
 
 void smp_unregister(struct hci_dev *hdev)
 {
-	BT_DBG("%s", hdev->name);
+	struct l2cap_chan *chan = hdev->smp_data;
+
+	if (!chan)
+		return;
+
+	BT_DBG("%s chan %p", hdev->name, chan);
 
 	if (hdev->tfm_aes) {
 		crypto_free_blkcipher(hdev->tfm_aes);
 		hdev->tfm_aes = NULL;
 	}
+
+	hdev->smp_data = NULL;
+	l2cap_chan_put(chan);
 }
-- 
1.9.3


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

* [PATCH 3/4] Bluetooth: Make AES crypto context private to SMP
  2014-08-08  6:37 [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan johan.hedberg
  2014-08-08  6:37 ` [PATCH 1/4] Bluetooth: Add more L2CAP convenience callbacks johan.hedberg
  2014-08-08  6:37 ` [PATCH 2/4] Bluetooth: Add SMP L2CAP channel skeleton johan.hedberg
@ 2014-08-08  6:37 ` johan.hedberg
  2014-08-08  6:37 ` [PATCH 4/4] Bluetooth: Convert SMP to use l2cap_chan infrastructure johan.hedberg
  2014-08-08 17:47 ` [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan Marcel Holtmann
  4 siblings, 0 replies; 6+ messages in thread
From: johan.hedberg @ 2014-08-08  6:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

Now that we have per-adapter SMP data thanks to the root SMP L2CAP
channel we can take advantage of it and attach the AES crypto context
(only used for SMP) to it. This means that the smp_irk_matches() and
smp_generate_rpa() function can be converted to internally handle the
AES context.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci_core.h |  1 -
 net/bluetooth/hci_core.c         | 13 ++-----------
 net/bluetooth/smp.c              | 41 +++++++++++++++++++++++++++-------------
 net/bluetooth/smp.h              |  5 ++---
 4 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2571fc1cb1c5..5f0b77b71b45 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -302,7 +302,6 @@ struct hci_dev {
 	__u32			req_status;
 	__u32			req_result;
 
-	struct crypto_blkcipher	*tfm_aes;
 	void			*smp_data;
 
 	struct discovery_state	discovery;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 88575a633601..abeb5e47311e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3234,11 +3234,8 @@ struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
 			return irk;
 	}
 
-	if (!hdev->tfm_aes)
-		return NULL;
-
 	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
-		if (smp_irk_matches(hdev->tfm_aes, irk->val, rpa)) {
+		if (smp_irk_matches(hdev, irk->val, rpa)) {
 			bacpy(&irk->rpa, rpa);
 			return irk;
 		}
@@ -3887,13 +3884,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
 		    !bacmp(&hdev->random_addr, &hdev->rpa))
 			return 0;
 
-		if (!hdev->tfm_aes) {
-			BT_ERR("%s crypto not available to generate RPA",
-			       hdev->name);
-			return -EOPNOTSUPP;
-		}
-
-		err = smp_generate_rpa(hdev->tfm_aes, hdev->irk, &hdev->rpa);
+		err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
 		if (err < 0) {
 			BT_ERR("%s failed to generate new RPA", hdev->name);
 			return err;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 2362ae35a4d5..6925fc4caaee 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -139,12 +139,18 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
 	return 0;
 }
 
-bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
-		     bdaddr_t *bdaddr)
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
 {
+	struct l2cap_chan *chan = hdev->smp_data;
+	struct crypto_blkcipher *tfm;
 	u8 hash[3];
 	int err;
 
+	if (!chan || !chan->data)
+		return false;
+
+	tfm = chan->data;
+
 	BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
 
 	err = smp_ah(tfm, irk, &bdaddr->b[3], hash);
@@ -154,10 +160,17 @@ bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
 	return !memcmp(bdaddr->b, hash, 3);
 }
 
-int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa)
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
 {
+	struct l2cap_chan *chan = hdev->smp_data;
+	struct crypto_blkcipher *tfm;
 	int err;
 
+	if (!chan || !chan->data)
+		return -EOPNOTSUPP;
+
+	tfm = chan->data;
+
 	get_random_bytes(&rpa->b[3], 3);
 
 	rpa->b[5] &= 0x3f;	/* Clear two most significant bits */
@@ -1555,25 +1568,25 @@ static const struct l2cap_ops smp_root_chan_ops = {
 int smp_register(struct hci_dev *hdev)
 {
 	struct l2cap_chan *chan;
+	struct crypto_blkcipher	*tfm_aes;
 
 	BT_DBG("%s", hdev->name);
 
-	hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0,
-					       CRYPTO_ALG_ASYNC);
-	if (IS_ERR(hdev->tfm_aes)) {
-		int err = PTR_ERR(hdev->tfm_aes);
+	tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm_aes)) {
+		int err = PTR_ERR(tfm_aes);
 		BT_ERR("Unable to create crypto context");
-		hdev->tfm_aes = NULL;
 		return err;
 	}
 
 	chan = l2cap_chan_create();
 	if (!chan) {
-		crypto_free_blkcipher(hdev->tfm_aes);
-		hdev->tfm_aes = NULL;
+		crypto_free_blkcipher(tfm_aes);
 		return -ENOMEM;
 	}
 
+	chan->data = tfm_aes;
+
 	/* FIXME: Using reserved 0x1f value for now - to be changed to
 	 * L2CAP_CID_SMP once all functionality is in place.
 	 */
@@ -1596,15 +1609,17 @@ int smp_register(struct hci_dev *hdev)
 void smp_unregister(struct hci_dev *hdev)
 {
 	struct l2cap_chan *chan = hdev->smp_data;
+	struct crypto_blkcipher *tfm_aes;
 
 	if (!chan)
 		return;
 
 	BT_DBG("%s chan %p", hdev->name, chan);
 
-	if (hdev->tfm_aes) {
-		crypto_free_blkcipher(hdev->tfm_aes);
-		hdev->tfm_aes = NULL;
+	tfm_aes = chan->data;
+	if (tfm_aes) {
+		chan->data = NULL;
+		crypto_free_blkcipher(tfm_aes);
 	}
 
 	hdev->smp_data = NULL;
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 6e29359f60a3..d3f6bd617940 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -132,9 +132,8 @@ int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
 
 void smp_chan_destroy(struct l2cap_conn *conn);
 
-bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
-		     bdaddr_t *bdaddr);
-int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa);
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
 
 int smp_register(struct hci_dev *hdev);
 void smp_unregister(struct hci_dev *hdev);
-- 
1.9.3


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

* [PATCH 4/4] Bluetooth: Convert SMP to use l2cap_chan infrastructure
  2014-08-08  6:37 [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan johan.hedberg
                   ` (2 preceding siblings ...)
  2014-08-08  6:37 ` [PATCH 3/4] Bluetooth: Make AES crypto context private to SMP johan.hedberg
@ 2014-08-08  6:37 ` johan.hedberg
  2014-08-08 17:47 ` [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan Marcel Holtmann
  4 siblings, 0 replies; 6+ messages in thread
From: johan.hedberg @ 2014-08-08  6:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

Now that we have all the necessary pieces in place we can fully convert
SMP to use the L2CAP channel infrastructure. This patch adds the
necessary callbacks and removes the now unneeded conn->smp_chan pointer.

One notable behavioral change in this patch comes from the following
code snippet:

-       case L2CAP_CID_SMP:
-               if (smp_sig_channel(conn, skb))
-                       l2cap_conn_del(conn->hcon, EACCES);

This piece of code was essentially forcing a disconnection if garbage
SMP data was received. The l2cap_conn_del() function is private to
l2cap_conn.c so we don't have access to it anymore when using the L2CAP
channel callbacks. Therefore, the behavior of the new code is simply to
return errors in the recv() callback (which is simply the old
smp_sig_channel()), but no disconnection will occur.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/l2cap.h |   1 -
 net/bluetooth/l2cap_core.c    |  10 ----
 net/bluetooth/smp.c           | 122 +++++++++++++++++++++++-------------------
 net/bluetooth/smp.h           |   1 -
 4 files changed, 66 insertions(+), 68 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 1a037ba4b6f4..bda6252e3722 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -636,7 +636,6 @@ struct l2cap_conn {
 	__u8			disc_reason;
 
 	struct delayed_work	security_timer;
-	struct smp_chan		*smp_chan;
 	struct l2cap_chan	*smp;
 
 	struct list_head	chan_l;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8acfe6f57b5e..40b6c06ab2c0 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1651,11 +1651,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
 		cancel_delayed_work_sync(&conn->info_timer);
 
-	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
-		cancel_delayed_work_sync(&conn->security_timer);
-		smp_chan_destroy(conn);
-	}
-
 	hcon->l2cap_data = NULL;
 	conn->hchan = NULL;
 	l2cap_conn_put(conn);
@@ -6862,11 +6857,6 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 		l2cap_le_sig_channel(conn, 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;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6925fc4caaee..744f678ac3e8 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -248,44 +248,29 @@ static int smp_s1(struct smp_chan *smp, u8 k[16], u8 r1[16], u8 r2[16],
 	return err;
 }
 
-static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
-				     u16 dlen, void *data)
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, 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;
+	struct l2cap_chan *chan = conn->smp;
+	struct kvec iv[2];
+	struct msghdr msg;
 
-	skb = bt_skb_alloc(len, GFP_ATOMIC);
-	if (!skb)
-		return NULL;
+	if (!chan)
+		return;
 
-	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);
+	BT_DBG("code 0x%2.2x", code);
 
-	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+	iv[0].iov_base = &code;
+	iv[0].iov_len = 1;
 
-	memcpy(skb_put(skb, dlen), data, dlen);
+	iv[1].iov_base = data;
+	iv[1].iov_len = len;
 
-	return skb;
-}
+	memset(&msg, 0, sizeof(msg));
 
-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);
+	msg.msg_iov = (struct iovec *) &iv;
+	msg.msg_iovlen = 2;
 
-	BT_DBG("code 0x%2.2x", code);
-
-	if (!skb)
-		return;
-
-	skb->priority = HCI_PRIO_MAX;
-	hci_send_acl(conn->hchan, skb, 0);
+	l2cap_chan_send(chan, &msg, 1 + len);
 
 	cancel_delayed_work_sync(&conn->security_timer);
 	schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
@@ -315,7 +300,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
 			      struct smp_cmd_pairing *req,
 			      struct smp_cmd_pairing *rsp, __u8 authreq)
 {
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	struct hci_conn *hcon = conn->hcon;
 	struct hci_dev *hdev = hcon->hdev;
 	u8 local_dist = 0, remote_dist = 0;
@@ -358,7 +344,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
 
 static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
 {
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 
 	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
 	    (max_key_size < SMP_MIN_ENC_KEY_SIZE))
@@ -418,7 +405,8 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
 						u8 local_io, u8 remote_io)
 {
 	struct hci_conn *hcon = conn->hcon;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	u8 method;
 	u32 passkey = 0;
 	int ret = 0;
@@ -589,6 +577,7 @@ static u8 smp_random(struct smp_chan *smp)
 
 static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
 {
+	struct l2cap_chan *chan = conn->smp;
 	struct smp_chan *smp;
 
 	smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
@@ -606,7 +595,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
 	}
 
 	smp->conn = conn;
-	conn->smp_chan = smp;
+	chan->data = smp;
 
 	hci_conn_hold(conn->hcon);
 
@@ -615,7 +604,8 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
 
 void smp_chan_destroy(struct l2cap_conn *conn)
 {
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	bool complete;
 
 	BUG_ON(!smp);
@@ -646,14 +636,15 @@ void smp_chan_destroy(struct l2cap_conn *conn)
 		}
 	}
 
+	chan->data = NULL;
 	kfree(smp);
-	conn->smp_chan = NULL;
 	hci_conn_drop(conn->hcon);
 }
 
 int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct l2cap_chan *chan;
 	struct smp_chan *smp;
 	u32 value;
 
@@ -662,7 +653,11 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
 	if (!conn || !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
 		return -ENOTCONN;
 
-	smp = conn->smp_chan;
+	chan = conn->smp;
+	if (!chan)
+		return -ENOTCONN;
+
+	smp = chan->data;
 
 	switch (mgmt_op) {
 	case MGMT_OP_USER_PASSKEY_REPLY:
@@ -709,10 +704,12 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 	if (conn->hcon->role != HCI_ROLE_SLAVE)
 		return SMP_CMD_NOTSUPP;
 
-	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
+	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
 		smp = smp_chan_create(conn);
-	else
-		smp = conn->smp_chan;
+	} else {
+		struct l2cap_chan *chan = conn->smp;
+		smp = chan->data;
+	}
 
 	if (!smp)
 		return SMP_UNSPECIFIED;
@@ -766,7 +763,8 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	u8 key_size, auth = SMP_AUTH_NONE;
 	int ret;
 
@@ -827,7 +825,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 
 static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 
 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
 
@@ -850,7 +849,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 
 static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 
 	BT_DBG("conn %p", conn);
 
@@ -1023,7 +1023,8 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 
 	BT_DBG("conn %p", conn);
 
@@ -1044,7 +1045,8 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
 static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_master_ident *rp = (void *) skb->data;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	struct hci_dev *hdev = conn->hcon->hdev;
 	struct hci_conn *hcon = conn->hcon;
 	struct smp_ltk *ltk;
@@ -1080,7 +1082,8 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
 static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_ident_info *info = (void *) skb->data;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 
 	BT_DBG("");
 
@@ -1102,7 +1105,8 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
 				   struct sk_buff *skb)
 {
 	struct smp_cmd_ident_addr_info *info = (void *) skb->data;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	struct hci_conn *hcon = conn->hcon;
 	bdaddr_t rpa;
 
@@ -1156,7 +1160,8 @@ distribute:
 static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_sign_info *rp = (void *) skb->data;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	struct hci_dev *hdev = conn->hcon->hdev;
 	struct smp_csrk *csrk;
 
@@ -1187,8 +1192,9 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
 	return 0;
 }
 
-int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
 {
+	struct l2cap_conn *conn = chan->conn;
 	struct hci_conn *hcon = conn->hcon;
 	__u8 code, reason;
 	int err = 0;
@@ -1290,7 +1296,8 @@ done:
 
 static void smp_notify_keys(struct l2cap_conn *conn)
 {
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	struct hci_conn *hcon = conn->hcon;
 	struct hci_dev *hdev = hcon->hdev;
 	struct smp_cmd_pairing *req = (void *) &smp->preq[1];
@@ -1357,7 +1364,8 @@ static void smp_notify_keys(struct l2cap_conn *conn)
 int smp_distribute_keys(struct l2cap_conn *conn)
 {
 	struct smp_cmd_pairing *req, *rsp;
-	struct smp_chan *smp = conn->smp_chan;
+	struct l2cap_chan *chan = conn->smp;
+	struct smp_chan *smp = chan->data;
 	struct hci_conn *hcon = conn->hcon;
 	struct hci_dev *hdev = hcon->hdev;
 	__u8 *keydist;
@@ -1475,6 +1483,11 @@ static void smp_teardown_cb(struct l2cap_chan *chan, int err)
 
 	BT_DBG("chan %p", chan);
 
+	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
+		cancel_delayed_work_sync(&conn->security_timer);
+		smp_chan_destroy(conn);
+	}
+
 	conn->smp = NULL;
 	l2cap_chan_put(chan);
 }
@@ -1508,11 +1521,11 @@ static struct sk_buff *smp_alloc_skb_cb(struct l2cap_chan *chan,
 static const struct l2cap_ops smp_chan_ops = {
 	.name			= "Security Manager",
 	.ready			= smp_ready_cb,
+	.recv			= smp_recv_cb,
 	.alloc_skb		= smp_alloc_skb_cb,
 	.teardown		= smp_teardown_cb,
 
 	.new_connection		= l2cap_chan_no_new_connection,
-	.recv			= l2cap_chan_no_recv,
 	.state_change		= l2cap_chan_no_state_change,
 	.close			= l2cap_chan_no_close,
 	.defer			= l2cap_chan_no_defer,
@@ -1587,10 +1600,7 @@ int smp_register(struct hci_dev *hdev)
 
 	chan->data = tfm_aes;
 
-	/* FIXME: Using reserved 0x1f value for now - to be changed to
-	 * L2CAP_CID_SMP once all functionality is in place.
-	 */
-	l2cap_add_scid(chan, 0x1f);
+	l2cap_add_scid(chan, L2CAP_CID_SMP);
 
 	l2cap_chan_set_defaults(chan);
 
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index d3f6bd617940..161ace3c3234 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -126,7 +126,6 @@ enum {
 /* SMP Commands */
 bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
-int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
 int smp_distribute_keys(struct l2cap_conn *conn);
 int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
 
-- 
1.9.3


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

* Re: [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan
  2014-08-08  6:37 [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan johan.hedberg
                   ` (3 preceding siblings ...)
  2014-08-08  6:37 ` [PATCH 4/4] Bluetooth: Convert SMP to use l2cap_chan infrastructure johan.hedberg
@ 2014-08-08 17:47 ` Marcel Holtmann
  4 siblings, 0 replies; 6+ messages in thread
From: Marcel Holtmann @ 2014-08-08 17:47 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> With this patches we do the initial conversion of SMP to use l2cap_chan
> and its related callbacks. There are many more simplifications possible
> after this, but to keep the conversion minimal I haven't done those yet.
> To keep the code compiling and functional between each patch the code
> that introduces the initial callbacks uses a custom 0x1f CID not to
> intefere with the legacy SMP CID handling. Only in the last patch which
> adds fully functional SMP handling through l2cap_chan is this custom CID
> converted back to the proper L2CAP_CID_SMP.
> 
> Johan
> 
> ----------------------------------------------------------------
> Johan Hedberg (4):
>      Bluetooth: Add more L2CAP convenience callbacks
>      Bluetooth: Add SMP L2CAP channel skeleton
>      Bluetooth: Make AES crypto context private to SMP
>      Bluetooth: Convert SMP to use l2cap_chan infrastructure
> 
> include/net/bluetooth/hci_core.h |   2 +-
> include/net/bluetooth/l2cap.h    |  27 +++-
> net/bluetooth/hci_core.c         |  13 +-
> net/bluetooth/l2cap_core.c       |  10 --
> net/bluetooth/smp.c              | 280 +++++++++++++++++++++++++++--------
> net/bluetooth/smp.h              |   6 +-
> 6 files changed, 248 insertions(+), 90 deletions(-)

all 4 patches have been applied to bluetooth-next tree.

Regards

Marcel


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

end of thread, other threads:[~2014-08-08 17:47 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-08  6:37 [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan johan.hedberg
2014-08-08  6:37 ` [PATCH 1/4] Bluetooth: Add more L2CAP convenience callbacks johan.hedberg
2014-08-08  6:37 ` [PATCH 2/4] Bluetooth: Add SMP L2CAP channel skeleton johan.hedberg
2014-08-08  6:37 ` [PATCH 3/4] Bluetooth: Make AES crypto context private to SMP johan.hedberg
2014-08-08  6:37 ` [PATCH 4/4] Bluetooth: Convert SMP to use l2cap_chan infrastructure johan.hedberg
2014-08-08 17:47 ` [PATCH 0/4] Bluetooth: Convert SMP to use l2cap_chan Marcel Holtmann

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.