From 93e359cb4db9793eef4fd13302ebe9b7b251de4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Mon, 1 Apr 2019 16:51:58 +0200 Subject: [PATCH] nimble: Fix handling and storing encryption key size The key size was not properly persisted across connections. Fixes #403. --- apps/btshell/src/btshell.h | 3 ++- apps/btshell/src/cmd.c | 12 ++++++++++-- apps/btshell/src/main.c | 5 ++++- nimble/host/include/host/ble_gap.h | 6 ++++-- nimble/host/src/ble_gap.c | 9 ++++++--- nimble/host/src/ble_sm.c | 8 ++++++-- nimble/host/src/ble_sm_priv.h | 5 +++-- nimble/host/src/ble_sm_sc.c | 2 ++ 8 files changed, 37 insertions(+), 13 deletions(-) diff --git a/apps/btshell/src/btshell.h b/apps/btshell/src/btshell.h index 9def8f53f..9078b8c71 100644 --- a/apps/btshell/src/btshell.h +++ b/apps/btshell/src/btshell.h @@ -160,7 +160,8 @@ int btshell_l2cap_update(uint16_t conn_handle, 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, +int btshell_sec_restart(uint16_t conn_handle, uint8_t key_size, + uint8_t *ltk, uint16_t ediv, uint64_t rand_val, int auth); int btshell_tx_start(uint16_t conn_handle, uint16_t len, uint16_t rate, uint16_t num); diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c index 57d18acd3..79785dd0e 100644 --- a/apps/btshell/src/cmd.c +++ b/apps/btshell/src/cmd.c @@ -2768,6 +2768,7 @@ cmd_security_encryption(int argc, char **argv) uint16_t ediv; uint64_t rand_val; uint8_t ltk[16]; + uint8_t key_size; int rc; int auth; @@ -2784,7 +2785,7 @@ cmd_security_encryption(int argc, char **argv) ediv = parse_arg_uint16("ediv", &rc); if (rc == ENOENT) { - rc = btshell_sec_restart(conn_handle, NULL, 0, 0, 0); + rc = btshell_sec_restart(conn_handle, 0, NULL, 0, 0, 0); } else { rand_val = parse_arg_uint64("rand", &rc); if (rc != 0) { @@ -2798,13 +2799,20 @@ cmd_security_encryption(int argc, char **argv) return rc; } + key_size = parse_arg_uint8("key_size", &rc); + if (rc != 0) { + console_printf("invalid 'key_size' parameter\n"); + return rc; + } + rc = parse_arg_byte_stream_exact_length("ltk", ltk, 16); if (rc != 0) { console_printf("invalid 'ltk' parameter\n"); return rc; } - rc = btshell_sec_restart(conn_handle, ltk, ediv, rand_val, auth); + rc = btshell_sec_restart(conn_handle, key_size, + ltk, ediv, rand_val, auth); } if (rc != 0) { diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c index ee486807b..d7f6a79d6 100644 --- a/apps/btshell/src/main.c +++ b/apps/btshell/src/main.c @@ -1754,6 +1754,7 @@ btshell_sec_start(uint16_t conn_handle) int btshell_sec_restart(uint16_t conn_handle, + uint8_t key_size, uint8_t *ltk, uint16_t ediv, uint64_t rand_val, @@ -1793,12 +1794,14 @@ btshell_sec_restart(uint16_t conn_handle, } ltk = value_sec.ltk; + key_size = value_sec.key_size; ediv = value_sec.ediv; rand_val = value_sec.rand_num; auth = value_sec.authenticated; } - rc = ble_gap_encryption_initiate(conn_handle, ltk, ediv, rand_val, auth); + rc = ble_gap_encryption_initiate(conn_handle, key_size, ltk, + ediv, rand_val, auth); return rc; } diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index c249a8a93..616ad91bc 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -1179,6 +1179,7 @@ int ble_gap_pair_initiate(uint16_t conn_handle); * * @param conn_handle The handle corresponding to the connection to * start encryption. + * @param key_size Encryption key size * @param ltk Long Term Key to be used for encryption. * @param udiv Encryption Diversifier for LTK * @param rand_val Random Value for EDIV and LTK @@ -1191,8 +1192,9 @@ int ble_gap_pair_initiate(uint16_t conn_handle); * this connection is already in progress; * Other nonzero on error. */ -int ble_gap_encryption_initiate(uint16_t conn_handle, const uint8_t *ltk, - uint16_t ediv, uint64_t rand_val, int auth); +int ble_gap_encryption_initiate(uint16_t conn_handle, uint8_t key_size, + const uint8_t *ltk, uint16_t ediv, + uint64_t rand_val, int auth); /** * Retrieves the most-recently measured RSSI for the specified connection. A diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 1c5fc9393..216ca283f 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -4302,8 +4302,9 @@ ble_gap_security_initiate(uint16_t conn_handle) */ rc = ble_store_read_peer_sec(&key_sec, &value_sec); if (rc == 0 && value_sec.ltk_present) { - rc = ble_sm_enc_initiate(conn_handle, value_sec.ltk, - value_sec.ediv, value_sec.rand_num, + rc = ble_sm_enc_initiate(conn_handle, value_sec.key_size, + value_sec.ltk, value_sec.ediv, + value_sec.rand_num, value_sec.authenticated); if (rc != 0) { goto done; @@ -4343,6 +4344,7 @@ ble_gap_pair_initiate(uint16_t conn_handle) int ble_gap_encryption_initiate(uint16_t conn_handle, + uint8_t key_size, const uint8_t *ltk, uint16_t ediv, uint64_t rand_val, @@ -4364,7 +4366,8 @@ ble_gap_encryption_initiate(uint16_t conn_handle, return BLE_HS_EROLE; } - rc = ble_sm_enc_initiate(conn_handle, ltk, ediv, rand_val, auth); + rc = ble_sm_enc_initiate(conn_handle, key_size, ltk, + ediv, rand_val, auth); return rc; } diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index b688a6698..bc20b9d15 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -1969,7 +1969,9 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om, } if (res->app_status == 0) { - res->app_status = ble_sm_enc_initiate(conn_handle, value_sec.ltk, + res->app_status = ble_sm_enc_initiate(conn_handle, + value_sec.key_size, + value_sec.ltk, value_sec.ediv, value_sec.rand_num, value_sec.authenticated); @@ -2505,7 +2507,8 @@ ble_sm_slave_initiate(uint16_t conn_handle) * Initiates the encryption procedure for the specified connection. */ int -ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk, uint16_t ediv, +ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, + const uint8_t *ltk, uint16_t ediv, uint64_t rand_val, int auth) { struct ble_sm_result res; @@ -2528,6 +2531,7 @@ ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk, uint16_t ediv, res.app_status = BLE_HS_ENOMEM; } else { proc->conn_handle = conn_handle; + proc->key_size = key_size; proc->state = BLE_SM_PROC_STATE_ENC_RESTORE; proc->flags |= BLE_SM_PROC_F_INITIATOR; if (auth) { diff --git a/nimble/host/src/ble_sm_priv.h b/nimble/host/src/ble_sm_priv.h index 11192b3fc..b8586e57b 100644 --- a/nimble/host/src/ble_sm_priv.h +++ b/nimble/host/src/ble_sm_priv.h @@ -396,8 +396,9 @@ int32_t ble_sm_timer(void); void ble_sm_connection_broken(uint16_t conn_handle); int ble_sm_pair_initiate(uint16_t conn_handle); int ble_sm_slave_initiate(uint16_t conn_handle); -int ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk, - uint16_t ediv, uint64_t rand_val, int auth); +int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, + const uint8_t *ltk, uint16_t ediv, + uint64_t rand_val, int auth); int ble_sm_init(void); #define BLE_SM_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \ diff --git a/nimble/host/src/ble_sm_sc.c b/nimble/host/src/ble_sm_sc.c index ed91917fc..1293de3a4 100644 --- a/nimble/host/src/ble_sm_sc.c +++ b/nimble/host/src/ble_sm_sc.c @@ -460,12 +460,14 @@ ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res) proc->our_keys.ediv = 0; proc->our_keys.rand_val = 0; proc->our_keys.ediv_rand_valid = 1; + proc->our_keys.key_size = proc->key_size; memcpy(proc->peer_keys.ltk, proc->ltk, sizeof proc->peer_keys.ltk); proc->peer_keys.ltk_valid = 1; proc->peer_keys.ediv = 0; proc->peer_keys.rand_val = 0; proc->peer_keys.ediv_rand_valid = 1; + proc->peer_keys.key_size = proc->key_size; if (proc->flags & BLE_SM_PROC_F_INITIATOR) { ble_sm_sc_random_advance(proc);