summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorArkadiusz Lichwa <arkadiusz.lichwa@tieto.com>2016-09-13 09:38:10 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2016-10-04 15:15:40 +0000
commitf30b3debc6350748720298812a246a175e2d332e (patch)
treee07b79110e9edcd6ad5db013f7993335ec8d552e /net
parenta8de2de1f235ba31e15540400372928f6f2c4437 (diff)
Bluetooth: Refactor distribution of security procedure status
Layers (modules) above HCI like L2CAP need to know status of applied security procedure when it's triggered on existing connection. It gives them possibility to make action in layer specific context on post-security-procedure conditions. Change-Id: Ia10078469847b29bb7eb3b1fb376ac305dd0b0fc Signed-off-by: Arkadiusz Lichwa <arkadiusz.lichwa@tieto.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/att.c16
-rw-r--r--net/bluetooth/avdtp.c2
-rw-r--r--net/bluetooth/hci_core.c21
-rw-r--r--net/bluetooth/l2cap.c6
-rw-r--r--net/bluetooth/l2cap_br.c11
-rw-r--r--net/bluetooth/l2cap_internal.h14
-rw-r--r--net/bluetooth/smp.c11
7 files changed, 57 insertions, 24 deletions
diff --git a/net/bluetooth/att.c b/net/bluetooth/att.c
index be3b45d0b..d605425cf 100644
--- a/net/bluetooth/att.c
+++ b/net/bluetooth/att.c
@@ -1872,14 +1872,24 @@ static void bt_att_disconnected(struct bt_l2cap_chan *chan)
}
#if defined(CONFIG_BLUETOOTH_SMP)
-static void bt_att_encrypt_change(struct bt_l2cap_chan *chan)
+static void bt_att_encrypt_change(struct bt_l2cap_chan *chan,
+ uint8_t hci_status)
{
struct bt_att *att = ATT_CHAN(chan);
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
struct bt_conn *conn = ch->chan.conn;
- BT_DBG("chan %p conn %p handle %u sec_level 0x%02x", ch, conn,
- conn->handle, conn->sec_level);
+ BT_DBG("chan %p conn %p handle %u sec_level 0x%02x status 0x%02x", ch,
+ conn, conn->handle, conn->sec_level, hci_status);
+
+ /*
+ * If status (HCI status of security procedure) is non-zero, notify
+ * outstanding request about security failure.
+ */
+ if (hci_status) {
+ att_handle_rsp(att, NULL, 0, BT_ATT_ERR_AUTHENTICATION);
+ return;
+ }
if (conn->sec_level == BT_SECURITY_LOW) {
return;
diff --git a/net/bluetooth/avdtp.c b/net/bluetooth/avdtp.c
index 7dcdfb7c3..f220655a7 100644
--- a/net/bluetooth/avdtp.c
+++ b/net/bluetooth/avdtp.c
@@ -74,7 +74,7 @@ void bt_avdtp_l2cap_disconnected(struct bt_l2cap_chan *chan)
BT_DBG("chan %p session %p", chan, AVDTP_CHAN(chan));
}
-void bt_avdtp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan)
+void bt_avdtp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan, uint8_t status)
{
BT_DBG("");
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 4b294b96c..ecb4d136f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1839,6 +1839,13 @@ static void auth_complete(struct net_buf *buf)
}
if (evt->status) {
+ if (conn->state == BT_CONN_CONNECTED) {
+ /*
+ * Inform layers above HCI about non-zero authentication
+ * status to make them able cleanup pending jobs.
+ */
+ bt_l2cap_encrypt_change(conn, evt->status);
+ }
reset_pairing(conn);
} else {
link_encr(handle);
@@ -1962,6 +1969,7 @@ static void hci_encrypt_change(struct net_buf *buf)
conn->required_sec_level = conn->sec_level;
#if defined(CONFIG_BLUETOOTH_BREDR)
} else {
+ bt_l2cap_encrypt_change(conn, evt->status);
reset_pairing(conn);
#endif /* CONFIG_BLUETOOTH_BREDR */
}
@@ -1994,7 +2002,7 @@ static void hci_encrypt_change(struct net_buf *buf)
}
#endif /* CONFIG_BLUETOOTH_BREDR */
- bt_l2cap_encrypt_change(conn);
+ bt_l2cap_encrypt_change(conn, evt->status);
bt_conn_security_changed(conn);
bt_conn_unref(conn);
@@ -2010,16 +2018,17 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
BT_DBG("status %u handle %u", evt->status, handle);
- if (evt->status) {
- return;
- }
-
conn = bt_conn_lookup_handle(handle);
if (!conn) {
BT_ERR("Unable to look up conn with handle %u", handle);
return;
}
+ if (evt->status) {
+ bt_l2cap_encrypt_change(conn, evt->status);
+ return;
+ }
+
/*
* Update keys with last pairing info for proper sec level update.
* This is done only for LE transport. For BR/EDR transport keys are
@@ -2038,7 +2047,7 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
}
#endif /* CONFIG_BLUETOOTH_BREDR */
- bt_l2cap_encrypt_change(conn);
+ bt_l2cap_encrypt_change(conn, evt->status);
bt_conn_security_changed(conn);
bt_conn_unref(conn);
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index cf782e7c0..28645ceb3 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -321,20 +321,20 @@ void bt_l2cap_disconnected(struct bt_conn *conn)
conn->channels = NULL;
}
-void bt_l2cap_encrypt_change(struct bt_conn *conn)
+void bt_l2cap_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
{
struct bt_l2cap_chan *chan;
#if defined(CONFIG_BLUETOOTH_BREDR)
if (conn->type == BT_CONN_TYPE_BR) {
- l2cap_br_encrypt_change(conn);
+ l2cap_br_encrypt_change(conn, hci_status);
return;
}
#endif /* CONFIG_BLUETOOTH_BREDR */
for (chan = conn->channels; chan; chan = chan->_next) {
if (chan->ops->encrypt_change) {
- chan->ops->encrypt_change(chan);
+ chan->ops->encrypt_change(chan, hci_status);
}
}
}
diff --git a/net/bluetooth/l2cap_br.c b/net/bluetooth/l2cap_br.c
index 52aa4053c..a0c8913c2 100644
--- a/net/bluetooth/l2cap_br.c
+++ b/net/bluetooth/l2cap_br.c
@@ -1489,7 +1489,7 @@ static void l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
}
}
-static void l2cap_br_conn_pend(struct bt_l2cap_chan *chan)
+static void l2cap_br_conn_pend(struct bt_l2cap_chan *chan, uint8_t status)
{
struct net_buf *buf;
struct bt_l2cap_conn_rsp *rsp;
@@ -1500,6 +1500,9 @@ static void l2cap_br_conn_pend(struct bt_l2cap_chan *chan)
return;
}
+ BT_DBG("chan %p status 0x%02x encr 0x%02x", chan, status,
+ chan->conn->encrypt);
+
if (!chan->conn->encrypt) {
return;
}
@@ -1558,15 +1561,15 @@ static void l2cap_br_conn_pend(struct bt_l2cap_chan *chan)
}
}
-void l2cap_br_encrypt_change(struct bt_conn *conn)
+void l2cap_br_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
{
struct bt_l2cap_chan *chan;
for (chan = conn->channels; chan; chan = chan->_next) {
- l2cap_br_conn_pend(chan);
+ l2cap_br_conn_pend(chan, hci_status);
if (chan->ops && chan->ops->encrypt_change) {
- chan->ops->encrypt_change(chan);
+ chan->ops->encrypt_change(chan, hci_status);
}
}
}
diff --git a/net/bluetooth/l2cap_internal.h b/net/bluetooth/l2cap_internal.h
index 68896d1b2..cc704f298 100644
--- a/net/bluetooth/l2cap_internal.h
+++ b/net/bluetooth/l2cap_internal.h
@@ -221,8 +221,11 @@ void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
/* Delete channel */
void bt_l2cap_chan_del(struct bt_l2cap_chan *chan);
-/* Notify L2CAP channels of a change in encryption state */
-void bt_l2cap_encrypt_change(struct bt_conn *conn);
+/*
+ * Notify L2CAP channels of a change in encryption state passing additionally
+ * HCI status of performed security procedure.
+ */
+void bt_l2cap_encrypt_change(struct bt_conn *conn, uint8_t hci_status);
/* Prepare an L2CAP PDU to be sent over a connection */
struct net_buf *bt_l2cap_create_pdu(struct nano_fifo *fifo, size_t reserve);
@@ -272,6 +275,9 @@ int bt_l2cap_br_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
/* Send packet data to connected peer */
int bt_l2cap_br_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf);
-/* Handle security level changed on link */
-void l2cap_br_encrypt_change(struct bt_conn *conn);
+/*
+ * Handle security level changed on link passing HCI status of performed
+ * security procedure.
+ */
+void l2cap_br_encrypt_change(struct bt_conn *conn, uint8_t hci_status);
#endif /* CONFIG_BLUETOOTH_BREDR */
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a4b8fa32f..ad3459bd1 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -3434,13 +3434,18 @@ static void bt_smp_disconnected(struct bt_l2cap_chan *chan)
memset(smp, 0, sizeof(*smp));
}
-static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan)
+static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
+ uint8_t hci_status)
{
struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
struct bt_conn *conn = chan->conn;
- BT_DBG("chan %p conn %p handle %u encrypt 0x%02x", chan, conn,
- conn->handle, conn->encrypt);
+ BT_DBG("chan %p conn %p handle %u encrypt 0x%02x hci status 0x%02x",
+ chan, conn, conn->handle, conn->encrypt, hci_status);
+
+ if (hci_status) {
+ return;
+ }
if (!smp || !conn->encrypt) {
return;