Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/releases/migration-guide-4.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,15 @@ Bluetooth Mesh
been removed. The selection of the PSA Crypto provider is now automatically controlled
by Kconfig :kconfig:option:`CONFIG_PSA_CRYPTO`.

Bluetooth Host
==============

* :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` has been deprecated. Instead, the application can
provide passkeys for pairing using the :c:member:`bt_conn_auth_cb.app_passkey` callback, which is
available when :kconfig:option:`CONFIG_BT_APP_PASSKEY` is enabled. The application can return the
passkey for pairing, or :c:macro:`BT_PASSKEY_RAND` for the Host to generate a random passkey
instead.

Ethernet
========

Expand Down
40 changes: 37 additions & 3 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -2380,8 +2380,8 @@ int bt_le_oob_get_sc_data(struct bt_conn *conn,
const struct bt_le_oob_sc_data **oobd_remote);

/**
* Special passkey value that can be used to disable a previously
* set fixed passkey.
* DEPRECATED - use @ref BT_PASSKEY_RAND instead. Special passkey value that can be used to disable
* a previously set fixed passkey.
*/
#define BT_PASSKEY_INVALID 0xffffffff

Expand All @@ -2393,12 +2393,15 @@ int bt_le_oob_get_sc_data(struct bt_conn *conn,
* Sets a fixed passkey to be used for pairing. If set, the
* pairing_confirm() callback will be called for all incoming pairings.
*
* @deprecated Use @ref BT_PASSKEY_RAND and the app_passkey callback from @ref bt_conn_auth_cb
* instead.
*
* @param passkey A valid passkey (0 - 999999) or BT_PASSKEY_INVALID
* to disable a previously set fixed passkey.
*
* @return 0 on success or a negative error code on failure.
*/
int bt_passkey_set(unsigned int passkey);
__deprecated int bt_passkey_set(unsigned int passkey);

/** Info Structure for OOB pairing */
struct bt_conn_oob_info {
Expand Down Expand Up @@ -2464,6 +2467,13 @@ struct bt_conn_pairing_feat {
};
#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */

/**
* Special passkey value that can be used to generate a random passkey when using the
* app_passkey callback from @ref bt_conn_auth_cb.
*
*/
#define BT_PASSKEY_RAND 0xffffffff

/** Authenticated pairing callback structure */
struct bt_conn_auth_cb {
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
Expand Down Expand Up @@ -2663,6 +2673,30 @@ struct bt_conn_auth_cb {
*/
void (*pincode_entry)(struct bt_conn *conn, bool highsec);
#endif

#if defined(CONFIG_BT_APP_PASSKEY)
/** @brief Allow the application to provide a passkey for pairing.
*
* If implemented, this callback allows the application to provide passkeys for pairing.
* The valid range of passkeys is 0 - 999999. The application shall return the passkey for
* pairing, or BT_PASSKEY_RAND to generate a random passkey. This callback is invoked only
* for the Passkey Entry method as defined in Core Specification Vol. 3, Part H. Which
* device in the pairing is showing the passkey depends on the IO capabilities of the
* device; see Table 2.8 of the Bluetooth Core Specification V6.0, Vol. 3, Part H for more
* details. For the purposes of this table, the device gains the "display" capability when
* this callback is non-NULL. This is irrespective of whether the callback returns a
* specified key or BT_PASSKEY_RAND.
*
*
* @note When using this callback, it is the responsibility of the application to use
* random and unique keys.
*
* @param conn Connection where pairing is currently active.
* @return Passkey for pairing, or BT_PASSKEY_RAND for the Host to generate a random
* passkey.
*/
uint32_t (*app_passkey)(struct bt_conn *conn);
#endif /* CONFIG_BT_APP_PASSKEY */
};

/** Authenticated pairing information callback structure */
Expand Down
14 changes: 13 additions & 1 deletion subsys/bluetooth/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -725,12 +725,24 @@ config BT_SMP_USB_HCI_CTLR_WORKAROUND
if the keys are distributed over an encrypted link.

config BT_FIXED_PASSKEY
bool "Use a fixed passkey for pairing"
bool "Use a fixed passkey for pairing [DEPRECATED]"
select DEPRECATED
help
This option is deprecated, use BT_APP_PASSKEY instead.
With this option enabled, the application will be able to call the
bt_passkey_set() API to set a fixed passkey. If set, the
pairing_confirm() callback will be called for all incoming pairings.

config BT_APP_PASSKEY
bool "Allow the application to provide passkeys for pairing"
depends on !BT_FIXED_PASSKEY
help
With this option enabled, the application will be able to provide passkeys for pairing
using the app_passkey() callback. If the application does not provide a passkey, a
random passkey will be generated by the Host.

WARNING: It is the responsibility of the application to use random and unique keys.

config BT_USE_DEBUG_KEYS
bool "Security Manager Debug Mode"
help
Expand Down
53 changes: 37 additions & 16 deletions subsys/bluetooth/host/shell/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4421,6 +4421,15 @@ static void br_bond_deleted(const bt_addr_t *peer)
}
#endif /* CONFIG_BT_CLASSIC */

#if defined(CONFIG_BT_APP_PASSKEY)
static uint32_t app_passkey = BT_PASSKEY_RAND;

static uint32_t auth_app_passkey(struct bt_conn *conn)
{
return app_passkey;
}
#endif /* CONFIG_BT_APP_PASSKEY */

static struct bt_conn_auth_cb auth_cb_display = {
.passkey_display = auth_passkey_display,
#if defined(CONFIG_BT_PASSKEY_KEYPRESS)
Expand All @@ -4437,6 +4446,9 @@ static struct bt_conn_auth_cb auth_cb_display = {
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
.pairing_accept = pairing_accept,
#endif
#if defined(CONFIG_BT_APP_PASSKEY)
.app_passkey = auth_app_passkey,
#endif
};

static struct bt_conn_auth_cb auth_cb_display_yes_no = {
Expand All @@ -4445,6 +4457,9 @@ static struct bt_conn_auth_cb auth_cb_display_yes_no = {
.passkey_confirm = auth_passkey_confirm,
#if defined(CONFIG_BT_CLASSIC)
.pincode_entry = auth_pincode_entry,
#endif
#if defined(CONFIG_BT_APP_PASSKEY)
.app_passkey = auth_app_passkey,
#endif
.oob_data_request = NULL,
.cancel = auth_cancel,
Expand All @@ -4460,6 +4475,9 @@ static struct bt_conn_auth_cb auth_cb_input = {
.passkey_confirm = NULL,
#if defined(CONFIG_BT_CLASSIC)
.pincode_entry = auth_pincode_entry,
#endif
#if defined(CONFIG_BT_APP_PASSKEY)
.app_passkey = auth_app_passkey,
#endif
.oob_data_request = NULL,
.cancel = auth_cancel,
Expand All @@ -4472,6 +4490,9 @@ static struct bt_conn_auth_cb auth_cb_input = {
static struct bt_conn_auth_cb auth_cb_confirm = {
#if defined(CONFIG_BT_CLASSIC)
.pincode_entry = auth_pincode_entry,
#endif
#if defined(CONFIG_BT_APP_PASSKEY)
.app_passkey = auth_app_passkey,
#endif
.oob_data_request = NULL,
.cancel = auth_cancel,
Expand All @@ -4487,6 +4508,9 @@ static struct bt_conn_auth_cb auth_cb_all = {
.passkey_confirm = auth_passkey_confirm,
#if defined(CONFIG_BT_CLASSIC)
.pincode_entry = auth_pincode_entry,
#endif
#if defined(CONFIG_BT_APP_PASSKEY)
.app_passkey = auth_app_passkey,
#endif
.oob_data_request = auth_pairing_oob_data_request,
.cancel = auth_cancel,
Expand Down Expand Up @@ -4703,16 +4727,15 @@ static int cmd_fal_connect(const struct shell *sh, size_t argc, char *argv[])
#endif /* CONFIG_BT_CENTRAL */
#endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */

#if defined(CONFIG_BT_FIXED_PASSKEY)
static int cmd_fixed_passkey(const struct shell *sh,
size_t argc, char *argv[])
#if defined(CONFIG_BT_APP_PASSKEY)
static int cmd_app_passkey(const struct shell *sh,
size_t argc, char *argv[])
{
unsigned int passkey;
int err;
uint32_t passkey;

if (argc < 2) {
bt_passkey_set(BT_PASSKEY_INVALID);
shell_print(sh, "Fixed passkey cleared");
app_passkey = BT_PASSKEY_RAND;
shell_print(sh, "App passkey cleared");
return 0;
}

Expand All @@ -4722,14 +4745,12 @@ static int cmd_fixed_passkey(const struct shell *sh,
return -ENOEXEC;
}

err = bt_passkey_set(passkey);
if (err) {
shell_print(sh, "Setting fixed passkey failed (err %d)", err);
}
app_passkey = passkey;
shell_print(sh, "App passkey set to %06u", passkey);

return err;
return 0;
}
#endif
#endif /* CONFIG_BT_APP_PASSKEY */

static int cmd_auth_passkey(const struct shell *sh,
size_t argc, char *argv[])
Expand Down Expand Up @@ -5340,10 +5361,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
cmd_fal_connect, 2, 3),
#endif /* CONFIG_BT_CENTRAL */
#endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
#if defined(CONFIG_BT_FIXED_PASSKEY)
SHELL_CMD_ARG(fixed-passkey, NULL, "[passkey]", cmd_fixed_passkey,
#if defined(CONFIG_BT_APP_PASSKEY)
SHELL_CMD_ARG(app-passkey, NULL, "[passkey]", cmd_app_passkey,
1, 1),
#endif
#endif /* CONFIG_BT_APP_PASSKEY */
#endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC) */
#endif /* CONFIG_BT_CONN */

Expand Down
77 changes: 58 additions & 19 deletions subsys/bluetooth/host/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,10 @@ struct bt_smp {
atomic_t bondable;
};

static unsigned int fixed_passkey = BT_PASSKEY_INVALID;
static unsigned int fixed_passkey = BT_PASSKEY_RAND;

#define DISPLAY_FIXED(smp) (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && \
fixed_passkey != BT_PASSKEY_INVALID && \
fixed_passkey != BT_PASSKEY_RAND && \
(smp)->method == PASSKEY_DISPLAY)

#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
Expand Down Expand Up @@ -363,9 +363,21 @@ static uint8_t get_io_capa(struct bt_smp *smp)
return BT_SMP_IO_DISPLAY_YESNO;
}

#if defined(CONFIG_BT_APP_PASSKEY)
/* Implementation of the app_passkey cb implies that the application can "know" the passkey
* without actually having a display, thus earning the "display" capability.
*/
if (smp_auth_cb->app_passkey) {
if (smp_auth_cb->passkey_entry) {
return BT_SMP_IO_KEYBOARD_DISPLAY;
}

return BT_SMP_IO_DISPLAY_ONLY;
}
#endif /* CONFIG_BT_APP_PASSKEY */

if (smp_auth_cb->passkey_entry) {
if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
fixed_passkey != BT_PASSKEY_INVALID) {
if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) {
return BT_SMP_IO_KEYBOARD_DISPLAY;
} else {
return BT_SMP_IO_KEYBOARD_ONLY;
Expand All @@ -377,8 +389,7 @@ static uint8_t get_io_capa(struct bt_smp *smp)
}

no_callbacks:
if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
fixed_passkey != BT_PASSKEY_INVALID) {
if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) {
return BT_SMP_IO_DISPLAY_ONLY;
} else {
return BT_SMP_IO_NO_INPUT_OUTPUT;
Expand Down Expand Up @@ -2475,7 +2486,6 @@ static uint8_t legacy_request_tk(struct bt_smp *smp)
struct bt_conn *conn = smp->chan.chan.conn;
const struct bt_conn_auth_cb *smp_auth_cb = latch_auth_cb(smp);
struct bt_keys *keys;
uint32_t passkey;

/*
* Fail if we have keys that are stronger than keys that will be
Expand Down Expand Up @@ -2503,11 +2513,25 @@ static uint8_t legacy_request_tk(struct bt_smp *smp)
}

break;
case PASSKEY_DISPLAY:
if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
fixed_passkey != BT_PASSKEY_INVALID) {
case PASSKEY_DISPLAY: {
uint32_t passkey;

if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) {
passkey = fixed_passkey;
} else {
#if defined(CONFIG_BT_APP_PASSKEY)
} else if (smp_auth_cb && smp_auth_cb->app_passkey) {
passkey = smp_auth_cb->app_passkey(conn);

if (passkey != BT_PASSKEY_RAND && passkey > 999999) {
LOG_WRN("App-provided passkey is out of valid range: %u", passkey);
return BT_SMP_ERR_UNSPECIFIED;
}
#endif /* CONFIG_BT_APP_PASSKEY */
} else {
passkey = BT_PASSKEY_RAND;
}

if (passkey == BT_PASSKEY_RAND) {
if (bt_rand(&passkey, sizeof(passkey))) {
return BT_SMP_ERR_UNSPECIFIED;
}
Expand All @@ -2527,6 +2551,7 @@ static uint8_t legacy_request_tk(struct bt_smp *smp)
sys_put_le32(passkey, smp->tk);

break;
}
case PASSKEY_INPUT:
atomic_set_bit(smp->flags, SMP_FLAG_USER);
smp_auth_cb->passkey_entry(conn);
Expand Down Expand Up @@ -4429,18 +4454,32 @@ __maybe_unused static uint8_t display_passkey(struct bt_smp *smp)
{
struct bt_conn *conn = smp->chan.chan.conn;
const struct bt_conn_auth_cb *smp_auth_cb = latch_auth_cb(smp);
uint32_t passkey = BT_PASSKEY_RAND;

if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
fixed_passkey != BT_PASSKEY_INVALID) {
smp->passkey = fixed_passkey;
} else {
if (bt_rand(&smp->passkey, sizeof(smp->passkey))) {
if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) {
passkey = fixed_passkey;
}

#if defined(CONFIG_BT_APP_PASSKEY)
if (smp_auth_cb && smp_auth_cb->app_passkey) {
passkey = smp_auth_cb->app_passkey(conn);

if (passkey != BT_PASSKEY_RAND && passkey > 999999) {
LOG_WRN("App-provided passkey is out of valid range: %u", passkey);
return BT_SMP_ERR_UNSPECIFIED;
}
}
#endif /* CONFIG_BT_APP_PASSKEY */

if (passkey == BT_PASSKEY_RAND) {
if (bt_rand(&passkey, sizeof(passkey))) {
return BT_SMP_ERR_UNSPECIFIED;
}

smp->passkey %= 1000000;
passkey %= 1000000;
}

smp->passkey = passkey;
smp->passkey_round = 0U;

if (smp_auth_cb && smp_auth_cb->passkey_display) {
Expand Down Expand Up @@ -6172,8 +6211,8 @@ int bt_smp_auth_pairing_confirm(struct bt_conn *conn)
#if defined(CONFIG_BT_FIXED_PASSKEY)
int bt_passkey_set(unsigned int passkey)
{
if (passkey == BT_PASSKEY_INVALID) {
fixed_passkey = BT_PASSKEY_INVALID;
if (passkey == BT_PASSKEY_INVALID || passkey == BT_PASSKEY_RAND) {
fixed_passkey = BT_PASSKEY_RAND;
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/bluetooth/shell/audio.conf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y
CONFIG_BT_GATT_AUTO_UPDATE_MTU=y
CONFIG_BT_L2CAP_ECRED=y
CONFIG_BT_SIGNING=y
CONFIG_BT_FIXED_PASSKEY=y
CONFIG_BT_APP_PASSKEY=y
CONFIG_BT_ATT_PREPARE_COUNT=5
CONFIG_BT_SHELL=y
CONFIG_BT_DEVICE_NAME="audio test shell"
Expand Down
2 changes: 1 addition & 1 deletion tests/bluetooth/shell/log.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CONFIG_BT_PERIPHERAL=y
CONFIG_BT_PRIVACY=y
CONFIG_BT_SMP=y
CONFIG_BT_SIGNING=y
CONFIG_BT_FIXED_PASSKEY=y
CONFIG_BT_APP_PASSKEY=y
CONFIG_BT_ATT_PREPARE_COUNT=2
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
Expand Down
Loading