From 763dc19bbf339e6150b812730758dc400c370284 Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Mon, 3 Jul 2023 13:45:30 +0200 Subject: [PATCH 1/2] bluetooth: host: smp: Add bondable flag overlay per connection 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 --- include/zephyr/bluetooth/conn.h | 20 +++++++++++++++++ subsys/bluetooth/host/Kconfig | 7 ++++++ subsys/bluetooth/host/smp.c | 38 +++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index a6c6d3b0366c09..0403a5a69001c1 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -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. diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index ae91baf884a00b..00ed7718a32105 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -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 the bt_conn_set_bondable API function that is + used to set/clear the bonding flag on a per-connection basis. + config BT_STORE_DEBUG_KEYS bool "Store Debug Mode bonds" help diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 9b40910cb304d3..86fbd723cd5790 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -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; @@ -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) { /* @@ -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); @@ -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; @@ -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; @@ -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) @@ -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; From f9d86b5549ec80ce625620dd5bd4816e6bf57d36 Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Wed, 5 Jul 2023 14:09:58 +0200 Subject: [PATCH 2/2] bluetooth: tests: Add bsim test for setting bondable flag per-conn Added test for the bt_conn_set_bondable API function. Check if we can pair without setting the bonding flag on the per-connection basis if the device was already bonded on the other identity. Signed-off-by: Mateusz Kapala --- tests/bsim/bluetooth/host/compile.sh | 1 + .../bond_per_connection/CMakeLists.txt | 18 ++ .../security/bond_per_connection/prj.conf | 17 ++ .../bond_per_connection/src/bs_bt_utils.c | 209 ++++++++++++++++++ .../bond_per_connection/src/bs_bt_utils.h | 85 +++++++ .../bond_per_connection/src/central.c | 55 +++++ .../security/bond_per_connection/src/main.c | 40 ++++ .../bond_per_connection/src/peripheral.c | 56 +++++ .../test_scripts/_compile.sh | 20 ++ .../bond_per_connection/test_scripts/_env.sh | 30 +++ .../test_scripts/run_test.sh | 25 +++ 11 files changed, 556 insertions(+) create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/CMakeLists.txt create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/prj.conf create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/src/main.c create mode 100644 tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c create mode 100755 tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_compile.sh create mode 100755 tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_env.sh create mode 100755 tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/run_test.sh diff --git a/tests/bsim/bluetooth/host/compile.sh b/tests/bsim/bluetooth/host/compile.sh index aa12780f2d8307..dd5ef23471887d 100755 --- a/tests/bsim/bluetooth/host/compile.sh +++ b/tests/bsim/bluetooth/host/compile.sh @@ -65,6 +65,7 @@ app=tests/bsim/bluetooth/host/privacy/legacy compile app=tests/bsim/bluetooth/host/security/bond_overwrite_allowed compile app=tests/bsim/bluetooth/host/security/bond_overwrite_denied compile +app=tests/bsim/bluetooth/host/security/bond_per_connection compile app=tests/bsim/bluetooth/host/security/ccc_update compile app=tests/bsim/bluetooth/host/security/ccc_update conf_file=prj_2.conf compile diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/CMakeLists.txt b/tests/bsim/bluetooth/host/security/bond_per_connection/CMakeLists.txt new file mode 100644 index 00000000000000..2fa69bf185fffe --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_multi_id_bond_per_connection) + +target_sources(app PRIVATE + src/bs_bt_utils.c + src/central.c + src/main.c + src/peripheral.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/prj.conf b/tests/bsim/bluetooth/host/security/bond_per_connection/prj.conf new file mode 100644 index 00000000000000..afa7d44903925b --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/prj.conf @@ -0,0 +1,17 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y + +CONFIG_BT_SMP=y + +CONFIG_ASSERT=y +CONFIG_BT_TESTING=y +CONFIG_LOG=y + +CONFIG_BT_ID_MAX=3 +CONFIG_BT_MAX_PAIRED=2 +CONFIG_BT_MAX_CONN=1 + +CONFIG_BT_PRIVACY=y + +CONFIG_BT_BONDABLE_PER_CONNECTION=y diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c new file mode 100644 index 00000000000000..1523e10d8a5a18 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" + +BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 2, "CONFIG_BT_MAX_PAIRED is too small."); +BUILD_ASSERT(CONFIG_BT_ID_MAX >= 3, "CONFIG_BT_ID_MAX is too small."); + +#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * 1000000) +#define TEST_TIMEOUT_SIMULATED BS_SECONDS(60) + +void test_tick(bs_time_t HW_device_time) +{ + bs_trace_debug_time(0, "Simulation ends now.\n"); + if (bst_result != Passed) { + bst_result = Failed; + bs_trace_error("Test did not pass before simulation ended.\n"); + } +} + +void test_init(void) +{ + bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED); + bst_result = In_progress; +} + +DEFINE_FLAG(flag_is_connected); +struct bt_conn *g_conn; +DEFINE_FLAG(bondable); +DEFINE_FLAG(call_bt_conn_set_bondable); + +void wait_connected(void) +{ + WAIT_FOR_FLAG(flag_is_connected); +} + +void wait_disconnected(void) +{ + WAIT_FOR_FLAG_UNSET(flag_is_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + UNSET_FLAG(flag_is_connected); +} + +BUILD_ASSERT(CONFIG_BT_MAX_CONN == 1, "This test assumes a single link."); +static void connected(struct bt_conn *conn, uint8_t err) +{ + ASSERT((!g_conn || (conn == g_conn)), "Unexpected new connection."); + + if (!g_conn) { + g_conn = bt_conn_ref(conn); + } + + if (err != 0) { + clear_g_conn(); + return; + } + + SET_FLAG(flag_is_connected); + + if (GET_FLAG(call_bt_conn_set_bondable) && bt_conn_set_bondable(conn, GET_FLAG(bondable))) { + ASSERT(0, "Fail during setting bondable flag for given connection."); + } +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +void clear_g_conn(void) +{ + struct bt_conn *conn; + + conn = g_conn; + g_conn = NULL; + ASSERT(conn, "Test error: No g_conn!\n"); + bt_conn_unref(conn); +} + +/* The following flags are raised by events and lowered by test code. */ +DEFINE_FLAG(flag_pairing_complete); +DEFINE_FLAG(flag_bonded); +DEFINE_FLAG(flag_not_bonded); + +static void pairing_complete(struct bt_conn *conn, bool bonded) +{ + SET_FLAG(flag_pairing_complete); + + if (bonded) { + SET_FLAG(flag_bonded); + } else { + SET_FLAG(flag_not_bonded); + } +} + +static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = { + .pairing_complete = pairing_complete, +}; + +void bs_bt_utils_setup(void) +{ + int err; + + err = bt_enable(NULL); + ASSERT(!err, "bt_enable failed.\n"); + err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb); + ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n"); +} + +static void scan_connect_to_first_result__device_found(const bt_addr_le_t *addr, int8_t rssi, + uint8_t type, struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + int err; + + if (g_conn != NULL) { + return; + } + + /* We're only interested in connectable events */ + if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) { + FAIL("Unexpected advertisement type."); + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + printk("Got scan result, connecting.. dst %s, RSSI %d\n", addr_str, rssi); + + err = bt_le_scan_stop(); + ASSERT(!err, "Err bt_le_scan_stop %d", err); + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn); + ASSERT(!err, "Err bt_conn_le_create %d", err); +} + +void scan_connect_to_first_result(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, scan_connect_to_first_result__device_found); + ASSERT(!err, "Err bt_le_scan_start %d", err); +} + +void disconnect(void) +{ + int err; + + err = bt_conn_disconnect(g_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + ASSERT(!err, "Err bt_conn_disconnect %d", err); +} + +void unpair(int id) +{ + int err; + + err = bt_unpair(id, BT_ADDR_LE_ANY); + ASSERT(!err, "Err bt_unpair %d", err); +} + +void set_security(bt_security_t sec) +{ + int err; + + err = bt_conn_set_security(g_conn, sec); + ASSERT(!err, "Err bt_conn_set_security %d", err); +} + +void advertise_connectable(int id, bt_addr_le_t *directed_dst) +{ + int err; + struct bt_le_adv_param param = {}; + + param.id = id; + param.interval_min = 0x0020; + param.interval_max = 0x4000; + param.options |= BT_LE_ADV_OPT_ONE_TIME; + param.options |= BT_LE_ADV_OPT_CONNECTABLE; + + if (directed_dst) { + param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; + param.peer = directed_dst; + } + + err = bt_le_adv_start(¶m, NULL, 0, NULL, 0); + ASSERT(err == 0, "Advertising failed to start (err %d)\n", err); +} + +void set_bondable(bool enable) +{ + if (enable) { + SET_FLAG(bondable); + } else { + UNSET_FLAG(bondable); + } +} + +void enable_bt_conn_set_bondable(bool enable) +{ + if (enable) { + SET_FLAG(call_bt_conn_set_bondable); + } else { + UNSET_FLAG(call_bt_conn_set_bondable); + } +} diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h new file mode 100644 index 00000000000000..fc440c6bec8688 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/bs_bt_utils.h @@ -0,0 +1,85 @@ +/** + * Common functions and helpers for BSIM GATT tests + * + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "bs_types.h" +#include "bstests.h" +#include "time_machine.h" +#include "zephyr/sys/__assert.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern enum bst_result_t bst_result; + +#define DECLARE_FLAG(flag) extern atomic_t flag +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define GET_FLAG(flag) \ + (bool)atomic_get(&flag) + +#define ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + FAIL(__VA_ARGS__); \ + } \ + } while (0) + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +void test_tick(bs_time_t HW_device_time); +void test_init(void); + +DECLARE_FLAG(flag_pairing_complete); +DECLARE_FLAG(flag_bonded); +DECLARE_FLAG(flag_not_bonded); + +extern struct bt_conn *g_conn; +void wait_connected(void); +void wait_disconnected(void); +void clear_g_conn(void); +void bs_bt_utils_setup(void); +void scan_connect_to_first_result(void); +void disconnect(void); +void unpair(int id); +void set_security(bt_security_t sec); +void advertise_connectable(int id, bt_addr_le_t *directed_dst); +void set_bondable(bool enable); +void enable_bt_conn_set_bondable(bool enable); diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c new file mode 100644 index 00000000000000..f31261b68c09dd --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/central.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "zephyr/bluetooth/addr.h" +#include "zephyr/bluetooth/conn.h" + +#include + +#include + +void central(void) +{ + bs_bt_utils_setup(); + + printk("== Bonding id a - global bondable mode ==\n"); + BUILD_ASSERT(CONFIG_BT_BONDABLE, "CONFIG_BT_BONDABLE must be enabled by default."); + enable_bt_conn_set_bondable(false); + scan_connect_to_first_result(); + wait_connected(); + set_security(BT_SECURITY_L2); + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_bonded); + disconnect(); + wait_disconnected(); + unpair(BT_ID_DEFAULT); + clear_g_conn(); + + printk("== Bonding id a - bond per-connection ==\n"); + enable_bt_conn_set_bondable(true); + set_bondable(true); + scan_connect_to_first_result(); + wait_connected(); + set_security(BT_SECURITY_L2); + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_bonded); + disconnect(); + wait_disconnected(); + clear_g_conn(); + + printk("== Bonding id b - bond per-connection ==\n"); + scan_connect_to_first_result(); + wait_connected(); + set_security(BT_SECURITY_L2); + TAKE_FLAG(flag_pairing_complete); + TAKE_FLAG(flag_not_bonded); + disconnect(); + wait_disconnected(); + clear_g_conn(); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/main.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/main.c new file mode 100644 index 00000000000000..7553f7b5f83665 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/main.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "bstests.h" + +void central(void); +void peripheral(void); + +static const struct bst_test_instance test_to_add[] = { + { + .test_id = "central", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = central, + }, + { + .test_id = "peripheral", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = peripheral, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_to_add); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c b/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c new file mode 100644 index 00000000000000..5e11d6ac712fd6 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/src/peripheral.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_bt_utils.h" +#include "zephyr/bluetooth/addr.h" +#include "zephyr/bluetooth/bluetooth.h" +#include "zephyr/bluetooth/conn.h" +#include "zephyr/toolchain/gcc.h" + +#include +#include + +void peripheral(void) +{ + bs_bt_utils_setup(); + + int id_a; + int id_b; + + id_a = bt_id_create(NULL, NULL); + ASSERT(id_a >= 0, "bt_id_create id_a failed (err %d)\n", id_a); + + id_b = bt_id_create(NULL, NULL); + ASSERT(id_b >= 0, "bt_id_create id_b failed (err %d)\n", id_b); + + printk("== Bonding id a - global bondable mode ==\n"); + BUILD_ASSERT(CONFIG_BT_BONDABLE, "CONFIG_BT_BONDABLE must be enabled by default."); + enable_bt_conn_set_bondable(false); + advertise_connectable(id_a, NULL); + wait_connected(); + /* Central should bond here and trigger a disconnect. */ + wait_disconnected(); + unpair(id_a); + clear_g_conn(); + + printk("== Bonding id a - bond per-connection true ==\n"); + enable_bt_conn_set_bondable(true); + set_bondable(true); + advertise_connectable(id_a, NULL); + wait_connected(); + /* Central should bond here and trigger a disconnect. */ + wait_disconnected(); + clear_g_conn(); + + printk("== Bonding id b - bond per-connection false ==\n"); + set_bondable(false); + advertise_connectable(id_b, NULL); + wait_connected(); + /* Central should pair without bond here and trigger a disconnect. */ + wait_disconnected(); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_compile.sh b/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_compile.sh new file mode 100755 index 00000000000000..f03de68b83f362 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_compile.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +# Read variable definitions output by _env.sh +source "${bash_source_dir}/_env.sh" + +: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}" +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be defined}" + +WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}" +BOARD="${BOARD:-nrf52_bsim}" +BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" +INCR_BUILD=1 +mkdir -p ${WORK_DIR} +source ${ZEPHYR_BASE}/tests/bsim/compile.source +app="tests/bsim/bluetooth/$test_name" compile diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_env.sh b/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_env.sh new file mode 100755 index 00000000000000..173f0d2eedfcc0 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/_env.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}" + +test_name="security_bond_per_connection" +bsim_bin="${BSIM_OUT_PATH}/bin" +verbosity_level=2 +BOARD="${BOARD:-nrf52_bsim}" +simulation_id="$test_name" +central_exe="${bsim_bin}/bs_${BOARD}_tests_bsim_bluetooth_host_${test_name}_prj_conf" +peripheral_exe="${central_exe}" + +function print_var { + # Print a shell-sourceable variable definition. + local var_name="$1" + local var_repr="${!var_name@Q}" + echo "$var_name=$var_repr" +} + +print_var test_name +print_var bsim_bin +print_var verbosity_level +print_var BOARD +print_var simulation_id +print_var central_exe +print_var peripheral_exe diff --git a/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/run_test.sh new file mode 100755 index 00000000000000..351f44523cc1f2 --- /dev/null +++ b/tests/bsim/bluetooth/host/security/bond_per_connection/test_scripts/run_test.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +set -eu +bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + +# Read variable definitions output by _env.sh +source "${bash_source_dir}/_env.sh" +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +EXECUTE_TIMEOUT=30 + +cd ${BSIM_OUT_PATH}/bin + +Execute "$central_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -RealEncryption=1 + +Execute "$peripheral_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral -RealEncryption=1 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs