From d33cdbe5dc2ef7052658c48d68fce23e03458a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Mon, 24 Sep 2018 11:07:42 +0200 Subject: [PATCH] host: Add API to unpair a peer device This API allows to unpair 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. This function is used in policy for SM key overflow. Instead of just deleting the keys from storage, the host performs tasks described above to ensure correct behavior. --- apps/btshell/src/btshell.h | 1 + apps/btshell/src/cmd.c | 60 ++++++++++++++++++++++++++++++ apps/btshell/src/main.c | 13 +++++++ nimble/host/include/host/ble_gap.h | 28 ++++++++++++++ nimble/host/src/ble_gap.c | 52 ++++++++++++++++++++++++++ nimble/host/src/ble_store_util.c | 2 +- 6 files changed, 155 insertions(+), 1 deletion(-) 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;