diff --git a/nimble/host/include/host/ble_sm.h b/nimble/host/include/host/ble_sm.h index 9bd25adfc..ef4ec11b1 100644 --- a/nimble/host/include/host/ble_sm.h +++ b/nimble/host/include/host/ble_sm.h @@ -97,6 +97,7 @@ struct ble_sm_io { #if NIMBLE_BLE_SM int ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey); +int ble_sm_unbond(uint8_t peer_id_addr_type, const uint8_t *peer_id_addr); #else #define ble_sm_inject_io(conn_handle, pkey) \ ((void)(conn_handle), BLE_HS_ENOTSUP) diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index 3421b065b..76811ee0e 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -2155,6 +2155,42 @@ ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk, uint16_t ediv, return res.app_status; } +/** + * Deletes the bonding association with the specified peer. That is, this + * function erases the security material that was persisted when we paired with + * the specified peer. + * + * @param peer_id_addr_type The identity address type of the peer. + * @param peer_id_addr The peer's identity address. + * + * @return 0 on success; + * BLE_HS_ENOENT if there is no bond to the + * specified peer. + */ +int +ble_sm_unbond(uint8_t peer_id_addr_type, const uint8_t *peer_id_addr) +{ + struct ble_store_key_sec key_sec = { 0 }; + int peer_rc; + int our_rc; + int rc; + + key_sec.peer_addr_type = peer_id_addr_type; + memcpy(key_sec.peer_addr, peer_id_addr, sizeof key_sec.peer_addr); + + our_rc = ble_store_delete_our_sec(&key_sec); + peer_rc = ble_store_delete_peer_sec(&key_sec); + + if (our_rc == BLE_HS_ENOENT && peer_rc == BLE_HS_ENOENT) { + rc = BLE_HS_ENOENT; + } else if (our_rc == 0) { + rc = peer_rc; + } else { + rc = our_rc; + } + return rc; +} + static int ble_sm_rx(uint16_t conn_handle, struct os_mbuf **om) { diff --git a/nimble/host/test/src/ble_hs_test_util.c b/nimble/host/test/src/ble_hs_test_util.c index b0edcd330..ef4f9a10a 100644 --- a/nimble/host/test/src/ble_hs_test_util.c +++ b/nimble/host/test/src/ble_hs_test_util.c @@ -2070,6 +2070,52 @@ ble_hs_test_util_num_cccds(void) } } +int +ble_hs_test_util_num_our_secs(void) +{ + struct ble_store_value_sec val; + struct ble_store_key_sec key = { 0 }; + int rc; + + key.peer_addr_type = BLE_STORE_ADDR_TYPE_NONE; + for (key.idx = 0; ; key.idx++) { + rc = ble_store_read_our_sec(&key, &val); + switch (rc) { + case 0: + break; + + case BLE_HS_ENOENT: + return key.idx; + + default: + TEST_ASSERT_FATAL(0); + } + } +} + +int +ble_hs_test_util_num_peer_secs(void) +{ + struct ble_store_value_sec val; + struct ble_store_key_sec key = { 0 }; + int rc; + + key.peer_addr_type = BLE_STORE_ADDR_TYPE_NONE; + for (key.idx = 0; ; key.idx++) { + rc = ble_store_read_peer_sec(&key, &val); + switch (rc) { + case 0: + break; + + case BLE_HS_ENOENT: + return key.idx; + + default: + TEST_ASSERT_FATAL(0); + } + } +} + static int ble_hs_test_util_store_read(int obj_type, union ble_store_key *key, union ble_store_value *value) diff --git a/nimble/host/test/src/ble_hs_test_util.h b/nimble/host/test/src/ble_hs_test_util.h index b0f389c51..75865e24a 100644 --- a/nimble/host/test/src/ble_hs_test_util.h +++ b/nimble/host/test/src/ble_hs_test_util.h @@ -273,6 +273,8 @@ void ble_hs_test_util_assert_mbufs_freed( const struct ble_hs_test_util_mbuf_params *params); void ble_hs_test_util_post_test(void *arg); int ble_hs_test_util_num_cccds(void); +int ble_hs_test_util_num_our_secs(void); +int ble_hs_test_util_num_peer_secs(void); void ble_hs_test_util_init_no_start(void); void ble_hs_test_util_init(void); diff --git a/nimble/host/test/src/ble_sm_test_util.c b/nimble/host/test/src/ble_sm_test_util.c index d702ce69e..7f40ff930 100644 --- a/nimble/host/test/src/ble_sm_test_util.c +++ b/nimble/host/test/src/ble_sm_test_util.c @@ -1797,6 +1797,9 @@ ble_sm_test_util_us_lgcy_good_once(struct ble_sm_test_params *params) void ble_sm_test_util_us_lgcy_good(struct ble_sm_test_params *params) { + uint8_t id_addr_type; + int rc; + /*** We are master. */ /* We initiate pairing. */ @@ -1809,6 +1812,14 @@ ble_sm_test_util_us_lgcy_good(struct ble_sm_test_params *params) /* Verify link can be restored via the encryption procedure. */ ble_sm_test_util_bonding_all(params, 1); + + /* Verify programmatic unbonding. */ + id_addr_type = ble_hs_misc_addr_type_to_id(params->resp_addr_type); + rc = ble_sm_unbond(id_addr_type, params->resp_id_addr); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0); + TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0); } static void @@ -1924,6 +1935,9 @@ ble_sm_test_util_peer_lgcy_good_once(struct ble_sm_test_params *params) void ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_params *params) { + uint8_t id_addr_type; + int rc; + /*** Peer is master. */ /* Peer performs IO first; peer initiates pairing. */ @@ -1948,6 +1962,14 @@ ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_params *params) /* Verify link can be restored via the encryption procedure. */ ble_sm_test_util_bonding_all(params, 0); + + /* Verify programmatic unbonding. */ + id_addr_type = ble_hs_misc_addr_type_to_id(params->init_addr_type); + rc = ble_sm_unbond(id_addr_type, params->init_id_addr); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0); + TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0); } static void @@ -2110,6 +2132,9 @@ ble_sm_test_util_us_sc_good_once(struct ble_sm_test_params *params) void ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params) { + uint8_t id_addr_type; + int rc; + /*** We are master. */ /* We initiate pairing. */ @@ -2124,6 +2149,14 @@ ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params) /* Verify link can be restored via the encryption procedure. */ ble_sm_test_util_bonding_all(params, 1); + + /* Verify programmatic unbonding. */ + id_addr_type = ble_hs_misc_addr_type_to_id(params->resp_addr_type); + rc = ble_sm_unbond(id_addr_type, params->resp_id_addr); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0); + TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0); } static void @@ -2298,6 +2331,9 @@ ble_sm_test_util_peer_sc_good_once(struct ble_sm_test_params *params) void ble_sm_test_util_peer_sc_good(struct ble_sm_test_params *params) { + uint8_t id_addr_type; + int rc; + /*** Peer is master. */ /* Peer performs IO first; peer initiates pairing. */ @@ -2322,6 +2358,14 @@ ble_sm_test_util_peer_sc_good(struct ble_sm_test_params *params) /* Verify link can be restored via the encryption procedure. */ ble_sm_test_util_bonding_all(params, 0); + + /* Verify programmatic unbonding. */ + id_addr_type = ble_hs_misc_addr_type_to_id(params->init_addr_type); + rc = ble_sm_unbond(id_addr_type, params->init_id_addr); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0); + TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0); } void