diff --git a/apps/btshell/src/btshell.h b/apps/btshell/src/btshell.h index 0d3a50aa2..595fd986e 100644 --- a/apps/btshell/src/btshell.h +++ b/apps/btshell/src/btshell.h @@ -155,6 +155,7 @@ int btshell_l2cap_update(uint16_t conn_handle, struct ble_l2cap_sig_update_params *params); int btshell_sec_start(uint16_t conn_handle); int btshell_sec_pair(uint16_t conn_handle); +int btshell_sec_unpair(ble_addr_t *peer_addr); int btshell_sec_restart(uint16_t conn_handle, uint8_t *ltk, uint16_t ediv, uint64_t rand_val, int auth); int btshell_tx_start(uint16_t handle, uint16_t len, uint16_t rate, diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c index 9ca66713d..106d3ff6c 100644 --- a/apps/btshell/src/cmd.c +++ b/apps/btshell/src/cmd.c @@ -2624,6 +2624,59 @@ static const struct shell_cmd_help security_pair_help = { }; #endif +/***************************************************************************** + * $security-unpair * + *****************************************************************************/ + +static int +cmd_security_unpair(int argc, char **argv) +{ + ble_addr_t peer; + int rc; + + rc = parse_arg_all(argc - 1, argv + 1); + if (rc != 0) { + return rc; + } + + rc = parse_arg_mac("peer_addr", peer.val); + if (rc == 0) { + + peer.type = parse_arg_kv_dflt("peer_addr_type", + cmd_peer_addr_types, + BLE_ADDR_PUBLIC, &rc); + if (rc != 0) { + console_printf("invalid 'peer_addr_type' parameter\n"); + return rc; + } + } else { + console_printf("invalid 'peer_addr' parameter\n"); + return rc; + } + + rc = ble_gap_unpair(&peer); + if (rc != 0) { + console_printf("error unpairing; rc=%d\n", rc); + return rc; + } + + return 0; +} + +#if MYNEWT_VAL(SHELL_CMD_HELP) +static const struct shell_param security_unpair_params[] = { + {"peer_addr_type", "usage: =[public|random|public_id|random_id], default: public"}, + {"peer_addr", "usage: =[XX:XX:XX:XX:XX:XX]"}, + {NULL, NULL} +}; + +static const struct shell_cmd_help security_unpair_help = { + .summary = "unpair a peer device", + .usage = NULL, + .params = security_unpair_params, +}; +#endif + /***************************************************************************** * $security-start * *****************************************************************************/ @@ -3717,6 +3770,13 @@ static const struct shell_cmd btshell_commands[] = { .sc_cmd_func = cmd_security_pair, #if MYNEWT_VAL(SHELL_CMD_HELP) .help = &security_pair_help, +#endif + }, + { + .sc_cmd = "security-unpair", + .sc_cmd_func = cmd_security_unpair, +#if MYNEWT_VAL(SHELL_CMD_HELP) + .help = &security_unpair_help, #endif }, { diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c index a794fb87a..f79d089b0 100644 --- a/apps/btshell/src/main.c +++ b/apps/btshell/src/main.c @@ -1625,6 +1625,19 @@ btshell_sec_pair(uint16_t conn_handle) return rc; } +int +btshell_sec_unpair(ble_addr_t *peer_addr) +{ +#if !NIMBLE_BLE_SM + return BLE_HS_ENOTSUP; +#endif + + int rc; + + rc = ble_gap_unpair(peer_addr); + return rc; +} + int btshell_sec_start(uint16_t conn_handle) { diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index c485028be..46728e900 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -1181,6 +1181,34 @@ int ble_gap_encryption_initiate(uint16_t conn_handle, const uint8_t *ltk, */ int ble_gap_conn_rssi(uint16_t conn_handle, int8_t *out_rssi); +/** + * Unpairs a device with the specified address. The keys related to that peer + * device are removed from storage and peer address is removed from the resolve + * list from the controller. If a peer is connected, the connection is terminated. + * + * @param peer_addr Address of the device to be unpaired + * + * @return 0 on success; + * A BLE host HCI return code if the controller + * rejected the request; + * A BLE host core return code on unexpected + * error. + */ +int ble_gap_unpair(const ble_addr_t *peer_addr); + +/** + * Unpairs the oldest bonded peer device. The keys related to that peer + * device are removed from storage and peer address is removed from the resolve + * list from the controller. If a peer is connected, the connection is terminated. + * + * @return 0 on success; + * A BLE host HCI return code if the controller + * rejected the request; + * A BLE host core return code on unexpected + * error. + */ +int ble_gap_unpair_oldest_peer(void); + #define BLE_GAP_PRIVATE_MODE_NETWORK 0 #define BLE_GAP_PRIVATE_MODE_DEVICE 1 int ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode); diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 835afe72a..c370502b2 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -4329,6 +4329,58 @@ ble_gap_encryption_initiate(uint16_t conn_handle, return rc; } +int +ble_gap_unpair(const ble_addr_t *peer_addr) +{ + struct ble_hs_conn *conn; + int rc; + + if (ble_addr_cmp(peer_addr, BLE_ADDR_ANY) == 0) { + return BLE_HS_EINVAL; + } + + conn = ble_hs_conn_find_by_addr(peer_addr); + if (conn != NULL) { + rc = ble_gap_terminate(conn->bhc_handle, BLE_ERR_REM_USER_CONN_TERM); + if ((rc != BLE_HS_EALREADY) && (rc != BLE_HS_ENOTCONN)) { + return rc; + } + } + + rc = ble_hs_pvcy_remove_entry(peer_addr->type, + peer_addr->val); + if (rc != 0) { + return rc; + } + + return ble_store_util_delete_peer(peer_addr); +} + +int +ble_gap_unpair_oldest_peer(void) +{ + ble_addr_t oldest_peer_id_addr; + int num_peers; + int rc; + + rc = ble_store_util_bonded_peers( + &oldest_peer_id_addr, &num_peers, 1); + if (rc != 0) { + return rc; + } + + if (num_peers == 0) { + return 0; + } + + rc = ble_gap_unpair(&oldest_peer_id_addr); + if (rc != 0) { + return rc; + } + + return 0; +} + void ble_gap_passkey_event(uint16_t conn_handle, struct ble_gap_passkey_params *passkey_params) diff --git a/nimble/host/src/ble_store_util.c b/nimble/host/src/ble_store_util.c index 216c78e64..444cc55d7 100644 --- a/nimble/host/src/ble_store_util.c +++ b/nimble/host/src/ble_store_util.c @@ -236,7 +236,7 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg) case BLE_STORE_OBJ_TYPE_OUR_SEC: case BLE_STORE_OBJ_TYPE_PEER_SEC: case BLE_STORE_OBJ_TYPE_CCCD: - return ble_store_util_delete_oldest_peer(); + return ble_gap_unpair_oldest_peer(); default: return BLE_HS_EUNKNOWN;