Skip to content

Commit

Permalink
bluetooth: host: smp: Add bondable flag overlay per connection
Browse files Browse the repository at this point in the history
The current API for changing the bondable mode uses the global flag.
With Zephyr support for multiple Bluetooth identities, the API for
changing the bondable mode should be more fine-grained.
The bondable requirements of one identity should not have an impact on
another identity which can have a different set of requirements.
This change introduces function to overlay bondable flag per
connection.

Signed-off-by: Mateusz Kapala <mateusz.kapala@nordicsemi.no>
  • Loading branch information
mkapala-nordic committed Jul 5, 2023
1 parent acde5fe commit bc8b7d6
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
20 changes: 20 additions & 0 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,26 @@ void bt_conn_cb_register(struct bt_conn_cb *cb);
*/
void bt_set_bondable(bool enable);

/** @brief Set/clear the bonding flag for a given connection.
*
* Set/clear the Bonding flag in the Authentication Requirements of
* SMP Pairing Request/Response data for a given connection.
*
* The bonding flag for a given connection cannot be set/cleared if
* security procedures in the SMP module have already started.
* This function can be called only once per connection.
*
* If the bonding flag is not set/cleared for a given connection,
* the value will depend on global configuration which is set using
* bt_set_bondable.
* The default value of the global configuration is defined using
* CONFIG_BT_BONDABLE Kconfig option.
*
* @param conn Connection object.
* @param enable Value allowing/disallowing to be bondable.
*/
int bt_conn_set_bondable(struct bt_conn *conn, bool enable);

/** @brief Allow/disallow remote LE SC OOB data to be used for pairing.
*
* Set/clear the OOB data flag for LE SC SMP Pairing Request/Response data.
Expand Down
7 changes: 7 additions & 0 deletions subsys/bluetooth/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,13 @@ config BT_BONDING_REQUIRED
set the bondable flag in their pairing request. Any other kind of
requests will be rejected.

config BT_BONDABLE_PER_CONNECTION
bool "Set/clear the bonding flag per-connection [EXPERIMENTAL]"
select EXPERIMENTAL
help
Enable support for setting/clearing the bonding flag on a
per-connection basis.

config BT_STORE_DEBUG_KEYS
bool "Store Debug Mode bonds"
help
Expand Down
38 changes: 36 additions & 2 deletions subsys/bluetooth/host/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ struct bt_smp {

/* Used Bluetooth authentication callbacks. */
atomic_ptr_t auth_cb;

/* Bondable flag */
atomic_t bondable;
};

static unsigned int fixed_passkey = BT_PASSKEY_INVALID;
Expand Down Expand Up @@ -288,6 +291,11 @@ static K_SEM_DEFINE(sc_local_pkey_ready, 0, 1);
*/
#define BT_SMP_AUTH_CB_UNINITIALIZED ((atomic_ptr_val_t)bt_smp_pool)

/* Value used to mark that per-connection bondable flag is not initialized.
* Value false/true represent if flag is cleared or set and cannot be used for that purpose.
*/
#define BT_SMP_BONDABLE_UNINITIALIZED ((atomic_val_t)-1)

static bool le_sc_supported(void)
{
/*
Expand All @@ -310,6 +318,13 @@ static const struct bt_conn_auth_cb *latch_auth_cb(struct bt_smp *smp)
return atomic_ptr_get(&smp->auth_cb);
}

static bool latch_bondable(struct bt_smp *smp)
{
atomic_cas(&smp->bondable, BT_SMP_BONDABLE_UNINITIALIZED, (atomic_val_t)bondable);

return atomic_get(&smp->bondable);
}

static uint8_t get_io_capa(struct bt_smp *smp)
{
const struct bt_conn_auth_cb *smp_auth_cb = latch_auth_cb(smp);
Expand Down Expand Up @@ -2592,7 +2607,7 @@ static uint8_t get_auth(struct bt_smp *smp, uint8_t auth)
auth |= BT_SMP_AUTH_MITM;
}

if (bondable) {
if (latch_bondable(smp)) {
auth |= BT_SMP_AUTH_BONDING;
} else {
auth &= ~BT_SMP_AUTH_BONDING;
Expand Down Expand Up @@ -3977,7 +3992,7 @@ static uint8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
}

if (IS_ENABLED(CONFIG_BT_BONDING_REQUIRED) &&
!(bondable && (auth & BT_SMP_AUTH_BONDING))) {
!(latch_bondable(smp) && (auth & BT_SMP_AUTH_BONDING))) {
/* Reject security req if not both intend to bond */
LOG_DBG("Bonding required");
return BT_SMP_ERR_UNSPECIFIED;
Expand Down Expand Up @@ -4541,6 +4556,7 @@ static void bt_smp_connected(struct bt_l2cap_chan *chan)
smp_reset(smp);

atomic_ptr_set(&smp->auth_cb, BT_SMP_AUTH_CB_UNINITIALIZED);
atomic_set(&smp->bondable, BT_SMP_BONDABLE_UNINITIALIZED);
}

static void bt_smp_disconnected(struct bt_l2cap_chan *chan)
Expand Down Expand Up @@ -5291,6 +5307,24 @@ static inline int smp_self_test(void)
}
#endif

#if defined(CONFIG_BT_BONDABLE_PER_CONNECTION)
int bt_conn_set_bondable(struct bt_conn *conn, bool enable)
{
struct bt_smp *smp;

smp = smp_chan_get(conn);
if (!smp) {
return -EINVAL;
}

if (atomic_cas(&smp->bondable, BT_SMP_BONDABLE_UNINITIALIZED, (atomic_val_t)enable)) {
return 0;
} else {
return -EALREADY;
}
}
#endif

int bt_smp_auth_cb_overlay(struct bt_conn *conn, const struct bt_conn_auth_cb *cb)
{
struct bt_smp *smp;
Expand Down

0 comments on commit bc8b7d6

Please sign in to comment.