From c2ee00f7374a587b81ce570cd92f4a84af619c34 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Wed, 24 Jul 2019 17:07:09 +0200 Subject: [PATCH] Bluetooth: SMP: Fix peripheral security request with authenticated keys The call to bt_conn_security will send a SMP security request for peripheral, and for central it will initiate LL encryption. A call to bt_conn_security with no IO capabilities but authenticated keys has been distributed, would succeed on central side, but fail on peripheral side with error code -22. The keys could have been either: - Preprogrammed - IO capabilities may have changed. - OOB bonding may been used. Fix so that Peripheral can send a security request if the bond information is already established. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/conn.c | 26 +------------------------- subsys/bluetooth/host/smp.c | 34 +++++++++++++++++++++++++++++++++- subsys/bluetooth/host/smp.h | 1 + 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 924d49da710..9deb2cfa850 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1005,33 +1005,9 @@ static int start_security(struct bt_conn *conn) #if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_SMP) case BT_HCI_ROLE_MASTER: { - if (!conn->le.keys) { - conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, - conn->id, &conn->le.dst); - if (!conn->le.keys) { - conn->le.keys = bt_keys_find(BT_KEYS_LTK, - conn->id, - &conn->le.dst); - } - } - - if (!conn->le.keys || - !(conn->le.keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) { + if (!bt_smp_keys_check(conn)) { return bt_smp_send_pairing_req(conn); } - - if (conn->required_sec_level > BT_SECURITY_MEDIUM && - !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) { - return bt_smp_send_pairing_req(conn); - } - - if (conn->required_sec_level > BT_SECURITY_HIGH && - !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED) && - !(conn->le.keys->keys & BT_KEYS_LTK_P256) && - !(conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE)) { - return bt_smp_send_pairing_req(conn); - } - /* LE SC LTK and legacy master LTK are stored in same place */ return bt_conn_le_start_encryption(conn, conn->le.keys->ltk.rand, diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 3d08bdd33df..f8795212f8c 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -2384,7 +2384,7 @@ int bt_smp_send_security_req(struct bt_conn *conn) } /* early verify if required sec level if reachable */ - if (!sec_level_reachable(conn)) { + if (!(sec_level_reachable(conn) || bt_smp_keys_check(conn))) { return -EINVAL; } @@ -4845,6 +4845,38 @@ bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk) return true; } +bool bt_smp_keys_check(struct bt_conn *conn) +{ + if (!conn->le.keys) { + conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, + conn->id, &conn->le.dst); + if (!conn->le.keys) { + conn->le.keys = bt_keys_find(BT_KEYS_LTK, + conn->id, + &conn->le.dst); + } + } + + if (!conn->le.keys || + !(conn->le.keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) { + return false; + } + + if (conn->required_sec_level > BT_SECURITY_MEDIUM && + !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) { + return false; + } + + if (conn->required_sec_level > BT_SECURITY_HIGH && + !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED) && + !(conn->le.keys->keys & BT_KEYS_LTK_P256) && + !(conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE)) { + return false; + } + + return true; +} + static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) { int i; diff --git a/subsys/bluetooth/host/smp.h b/subsys/bluetooth/host/smp.h index 72e4759a630..a6354419eeb 100644 --- a/subsys/bluetooth/host/smp.h +++ b/subsys/bluetooth/host/smp.h @@ -127,6 +127,7 @@ int bt_smp_send_pairing_req(struct bt_conn *conn); int bt_smp_send_security_req(struct bt_conn *conn); void bt_smp_update_keys(struct bt_conn *conn); bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk); +bool bt_smp_keys_check(struct bt_conn *conn); int bt_smp_br_send_pairing_req(struct bt_conn *conn);