Commit a3e89e84 authored by François Delawarde's avatar François Delawarde Committed by Johan Hedberg
Browse files

bluetooth: host: Fix simultaneous pairings getting the same keys slot

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: default avatarFrançois Delawarde <fnde@oticon.com>
parent 171a9fa1
Loading
Loading
Loading
Loading
+1 −2
Changes for subsys/bluetooth/host/keys.c: 1 added line, 2 removed lines.
Original line number Diff line number Diff line
@@ -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;
		}
	}
+8 −18
Changes for subsys/bluetooth/host/smp.c: 8 added lines, 18 removed lines.
Original line number Diff line number Diff line
@@ -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 */