From a3e89e84a801d9bc048b0ee2177f0fb11d1a925a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Delawarde?= Date: Mon, 27 Jan 2020 13:25:39 +0100 Subject: [PATCH] bluetooth: host: Fix simultaneous pairings getting the same keys slot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an issue where a slot in the key pool was considered free when either the address was cleared or no keys were written in the entry (enc_size == 0). This caused a problem with simultaneous pairing attempts that would be assigned the same entry. This patch makes it so a a slot is considered free even when keys are not yet present in the entry, and makes sure the address is cleared in case of pairing failure or timeout so to mark the slot as free. Signed-off-by: François Delawarde --- subsys/bluetooth/host/keys.c | 3 +-- subsys/bluetooth/host/smp.c | 26 ++++++++------------------ 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index 38e5c031fc5..d3e4c9ce342 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -54,8 +54,7 @@ struct bt_keys *bt_keys_get_addr(u8_t id, const bt_addr_le_t *addr) } if (first_free_slot == ARRAY_SIZE(key_pool) && - (!bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY) || - !keys->enc_size)) { + !bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) { first_free_slot = i; } } diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 9ece69e384b..9fd82c879f9 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -1763,6 +1763,14 @@ static void smp_pairing_complete(struct bt_smp *smp, u8_t status) } else { u8_t auth_err = auth_err_get(status); + /* + * Clear the key pool entry in case of pairing failure. + */ + if (smp->chan.chan.conn->le.keys) { + bt_keys_clear(smp->chan.chan.conn->le.keys); + smp->chan.chan.conn->le.keys = NULL; + } + if (!atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR)) { bt_conn_security_changed(smp->chan.chan.conn, auth_err); } @@ -1781,15 +1789,6 @@ static void smp_timeout(struct k_work *work) BT_ERR("SMP Timeout"); - /* - * If SMP timeout occurred during key distribution we should assume - * pairing failed and don't store any keys from this pairing. - */ - if (atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR) && - smp->chan.chan.conn->le.keys) { - bt_keys_clear(smp->chan.chan.conn->le.keys); - } - atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT); smp_pairing_complete(smp, BT_SMP_ERR_UNSPECIFIED); @@ -3519,15 +3518,6 @@ static u8_t smp_pairing_failed(struct bt_smp *smp, struct net_buf *buf) } } - /* - * Pairing Failed command may be sent at any time during the pairing, - * so if there are any keys distributed, shall be cleared. - */ - if (atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR) && - smp->chan.chan.conn->le.keys) { - bt_keys_clear(smp->chan.chan.conn->le.keys); - } - smp_pairing_complete(smp, req->reason); /* return no error to avoid sending Pairing Failed in response */