From 97ec4a775e12aea773a459ae031b9b8472a0eb66 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Thu, 30 Jul 2020 12:56:11 +0200 Subject: [PATCH] Bluetooth: Host: Notify L2CAP that security change failed Notify L2CAP when pairing procedure fails during SMP pairing process. L2CAP needs to be notified so that it can cancel ongoing connection-oriented channel requests. Rename bt_l2cap_encrypt_change to bt_l2cap_security_changed and call it from bt_conn_security_changed always, so that L2CAP is informed when changing security fails. This also fixes security_changed conn callback not called when auth_complete returns an error. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/conn.c | 5 ++++- subsys/bluetooth/host/conn_internal.h | 3 ++- subsys/bluetooth/host/hci_core.c | 17 ++++++++--------- subsys/bluetooth/host/l2cap.c | 2 +- subsys/bluetooth/host/l2cap_internal.h | 2 +- subsys/bluetooth/host/smp.c | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 97185a87f17..38858289d74 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1071,10 +1071,13 @@ uint8_t bt_conn_enc_key_size(struct bt_conn *conn) return 0; } -void bt_conn_security_changed(struct bt_conn *conn, enum bt_security_err err) +void bt_conn_security_changed(struct bt_conn *conn, uint8_t hci_err, + enum bt_security_err err) { struct bt_conn_cb *cb; + bt_l2cap_security_changed(conn, hci_err); + for (cb = callback_list; cb; cb = cb->_next) { if (cb->security_changed) { cb->security_changed(conn, conn->sec_level, err); diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 249027320ae..0a413f49cb3 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -264,7 +264,8 @@ void bt_conn_identity_resolved(struct bt_conn *conn); #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) /* Notify higher layers that connection security changed */ -void bt_conn_security_changed(struct bt_conn *conn, enum bt_security_err err); +void bt_conn_security_changed(struct bt_conn *conn, uint8_t hci_err, + enum bt_security_err err); #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ /* Prepare a PDU to be sent over a connection */ diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 2cfd703132f..4a40415d3e0 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -3685,7 +3685,8 @@ static void auth_complete(struct net_buf *buf) * Inform layers above HCI about non-zero authentication * status to make them able cleanup pending jobs. */ - bt_l2cap_encrypt_change(conn, evt->status); + bt_conn_security_changed(conn, evt->status, + security_err_get(evt->status)); } reset_pairing(conn); } else { @@ -4134,8 +4135,8 @@ static void hci_encrypt_change(struct net_buf *buf) if (evt->status) { reset_pairing(conn); - bt_l2cap_encrypt_change(conn, evt->status); - bt_conn_security_changed(conn, security_err_get(evt->status)); + bt_conn_security_changed(conn, evt->status, + security_err_get(evt->status)); bt_conn_unref(conn); return; } @@ -4179,8 +4180,7 @@ static void hci_encrypt_change(struct net_buf *buf) #endif /* CONFIG_BT_BREDR */ reset_pairing(conn); - bt_l2cap_encrypt_change(conn, evt->status); - bt_conn_security_changed(conn, BT_SECURITY_ERR_SUCCESS); + bt_conn_security_changed(conn, evt->status, BT_SECURITY_ERR_SUCCESS); bt_conn_unref(conn); } @@ -4203,8 +4203,8 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf) if (evt->status) { reset_pairing(conn); - bt_l2cap_encrypt_change(conn, evt->status); - bt_conn_security_changed(conn, security_err_get(evt->status)); + bt_conn_security_changed(conn, evt->status, + security_err_get(evt->status)); bt_conn_unref(conn); return; } @@ -4231,8 +4231,7 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf) #endif /* CONFIG_BT_BREDR */ reset_pairing(conn); - bt_l2cap_encrypt_change(conn, evt->status); - bt_conn_security_changed(conn, BT_SECURITY_ERR_SUCCESS); + bt_conn_security_changed(conn, evt->status, BT_SECURITY_ERR_SUCCESS); bt_conn_unref(conn); } #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 7af577c7402..eb71ca374b9 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -548,7 +548,7 @@ fail: } #endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */ -void bt_l2cap_encrypt_change(struct bt_conn *conn, uint8_t hci_status) +void bt_l2cap_security_changed(struct bt_conn *conn, uint8_t hci_status) { struct bt_l2cap_chan *chan, *next; diff --git a/subsys/bluetooth/host/l2cap_internal.h b/subsys/bluetooth/host/l2cap_internal.h index fc9959b3625..d36496c3cf0 100644 --- a/subsys/bluetooth/host/l2cap_internal.h +++ b/subsys/bluetooth/host/l2cap_internal.h @@ -285,7 +285,7 @@ void bt_l2cap_chan_set_state(struct bt_l2cap_chan *chan, * 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); +void bt_l2cap_security_changed(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_timeout(struct net_buf_pool *pool, diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 9dd4c4694ca..9b07eba32c7 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -1835,7 +1835,8 @@ static void smp_pairing_complete(struct bt_smp *smp, uint8_t status) } if (!atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR)) { - bt_conn_security_changed(smp->chan.chan.conn, auth_err); + bt_conn_security_changed(smp->chan.chan.conn, status, + auth_err); } if (bt_auth && bt_auth->pairing_failed) { @@ -2778,9 +2779,8 @@ bool bt_smp_request_ltk(struct bt_conn *conn, uint64_t rand, uint16_t ediv, uint /* Notify higher level that security failed if security was * initiated by slave. */ - bt_conn_security_changed(smp->chan.chan.conn, + bt_conn_security_changed(conn, BT_HCI_ERR_PIN_OR_KEY_MISSING, BT_SECURITY_ERR_PIN_OR_KEY_MISSING); - } smp_reset(smp);