Bluetooth: host: Log security keys needed by sniffer

Log the security keys that the sniffer needs in order to sucessfully
decrypt the connection.
This option allows the sniffer to work in the cases where enabling
using the SMP debug keys is not wanted, either because it changes the
way the peer behaves or is denied by the peer.
It also enables the sniffer to decrypt a connection where the bond
already exists.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-11-19 09:26:34 +01:00 committed by Johan Hedberg
commit 200f4687e0
8 changed files with 123 additions and 7 deletions

View file

@ -52,6 +52,7 @@ BT_DEBUG_SMP,n
BT_OOB_DATA_FIXED,n
BT_FIXED_PASSKEY,n
BT_DEBUG_KEYS,n
BT_LOG_SNIFFER_INFO,n
BT_USE_DEBUG_KEYS,n
BT_STORE_DEBUG_KEYS,n
BT_CONN_DISABLE_SECURITY,n

Can't render this file because it has a wrong number of fields in line 44.

View file

@ -76,9 +76,9 @@ if(CONFIG_BT_HCI_HOST)
endif()
endif()
if(CONFIG_BT_DEBUG_SMP OR CONFIG_BT_DEBUG_KEYS)
message(WARNING "One or both these options are enabled:
CONFIG_BT_DEBUG_SMP CONFIG_BT_DEBUG_KEYS.
if(CONFIG_BT_DEBUG_SMP OR CONFIG_BT_DEBUG_KEYS OR CONFIG_BT_LOG_SNIFFER_INFO)
message(WARNING "One of these options are enabled:
CONFIG_BT_DEBUG_SMP CONFIG_BT_DEBUG_KEYS CONFIG_BT_LOG_SNIFFER_INFO.
Private security keys such as the LTK will be printed out, do not use in
production."
)

View file

@ -754,6 +754,17 @@ config BT_DEBUG_SERVICE
endif # BT_DEBUG
config BT_LOG_SNIFFER_INFO
bool "Bluetooth log information for sniffer"
help
This option enables the Bluetooth stack to log information such as
DH private key and LTK keys, which can be used by sniffers to decrypt
the connection without the use of Debug keys.
WARNING: This option prints out private security keys such as
the Long Term Key.
Use of this feature in production is strongly discouraged
config BT_TESTING
bool "Bluetooth Testing"
help

View file

@ -664,7 +664,16 @@ static int le_set_private_addr(uint8_t id)
}
le_rpa_timeout_submit();
return err;
if (err) {
return err;
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
BT_INFO("RPA: %s", bt_addr_str(&rpa));
}
return 0;
}
static int le_adv_set_private_addr(struct bt_le_ext_adv *adv)
@ -711,7 +720,15 @@ static int le_adv_set_private_addr(struct bt_le_ext_adv *adv)
le_rpa_timeout_submit();
}
return err;
if (err) {
return err;
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
BT_INFO("RPA: %s", bt_addr_str(&rpa));
}
return 0;
}
#else
static int le_set_private_addr(uint8_t id)
@ -726,7 +743,16 @@ static int le_set_private_addr(uint8_t id)
BT_ADDR_SET_NRPA(&nrpa);
return set_random_address(&nrpa);
err = set_random_address(&nrpa);
if (err) {
return err;
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
BT_INFO("NRPA: %s", bt_addr_str(&nrpa));
}
return 0;
}
static int le_adv_set_private_addr(struct bt_le_ext_adv *adv)
@ -741,7 +767,16 @@ static int le_adv_set_private_addr(struct bt_le_ext_adv *adv)
BT_ADDR_SET_NRPA(&nrpa);
return set_adv_random_address(adv, &nrpa);
err = set_adv_random_address(adv, &nrpa);
if (err) {
return err;
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
BT_INFO("NRPA: %s", bt_addr_str(&nrpa));
}
return 0;
}
#endif /* defined(CONFIG_BT_PRIVACY) */
@ -6017,9 +6052,32 @@ static void bt_dev_show_info(void)
BT_INFO("Identity%s: %s", bt_dev.id_count > 1 ? "[0]" : "",
bt_addr_le_str(&bt_dev.id_addr[0]));
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
#if defined(CONFIG_BT_PRIVACY)
uint8_t irk[16];
sys_memcpy_swap(irk, bt_dev.irk[0], 16);
BT_INFO("IRK%s: 0x%s", bt_dev.id_count > 1 ? "[0]" : "",
bt_hex(irk, 16));
#endif
}
for (i = 1; i < bt_dev.id_count; i++) {
BT_INFO("Identity[%d]: %s",
i, bt_addr_le_str(&bt_dev.id_addr[i]));
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
#if defined(CONFIG_BT_PRIVACY)
uint8_t irk[16];
sys_memcpy_swap(irk, bt_dev.irk[i], 16);
BT_INFO("IRK[%d]: 0x%s", i, bt_hex(irk, 16));
#endif
}
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
bt_keys_foreach(BT_KEYS_ALL, bt_keys_show_sniffer_info, NULL);
}
BT_INFO("HCI: version %s (0x%02x) revision 0x%04x, manufacturer 0x%04x",

View file

@ -111,6 +111,10 @@ static uint8_t generate_keys(void)
/* make sure generated key isn't debug key */
} while (memcmp(ecc.private_key_be, debug_private_key_be, 32) == 0);
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
BT_INFO("SC private key 0x%s", bt_hex(ecc.private_key_be, 32));
}
return 0;
}

View file

@ -11,6 +11,7 @@
#include <stdlib.h>
#include <sys/atomic.h>
#include <sys/util.h>
#include <sys/byteorder.h>
#include <settings/settings.h>
@ -435,3 +436,27 @@ void bt_keys_update_usage(uint8_t id, const bt_addr_le_t *addr)
}
#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
#if defined(CONFIG_BT_LOG_SNIFFER_INFO)
void bt_keys_show_sniffer_info(struct bt_keys *keys, void *data)
{
uint8_t ltk[16];
if (keys->keys & BT_KEYS_LTK_P256) {
sys_memcpy_swap(ltk, keys->ltk.val, keys->enc_size);
BT_INFO("SC LTK: 0x%s", bt_hex(ltk, keys->enc_size));
}
if (keys->keys & BT_KEYS_SLAVE_LTK) {
sys_memcpy_swap(ltk, keys->slave_ltk.val, keys->enc_size);
BT_INFO("Legacy LTK: 0x%s (peripheral)",
bt_hex(ltk, keys->enc_size));
}
if (keys->keys & BT_KEYS_LTK) {
sys_memcpy_swap(ltk, keys->ltk.val, keys->enc_size);
BT_INFO("Legacy LTK: 0x%s (central)",
bt_hex(ltk, keys->enc_size));
}
}
#endif /* defined(CONFIG_BT_LOG_SNIFFER_INFO) */

View file

@ -124,3 +124,5 @@ void bt_keys_link_key_store(struct bt_keys_link_key *link_key);
/* BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING is enabled */
void bt_keys_update_usage(uint8_t id, const bt_addr_le_t *addr);
void bt_keys_link_key_update_usage(const bt_addr_t *addr);
void bt_keys_show_sniffer_info(struct bt_keys *keys, void *data);

View file

@ -1839,6 +1839,10 @@ static void smp_pairing_complete(struct bt_smp *smp, uint8_t status)
#endif /* CONFIG_BT_BREDR */
bool bond_flag = atomic_test_bit(smp->flags, SMP_FLAG_BOND);
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
bt_keys_show_sniffer_info(conn->le.keys, NULL);
}
if (bond_flag) {
bt_keys_store(conn->le.keys);
}
@ -2339,6 +2343,10 @@ static uint8_t legacy_request_tk(struct bt_smp *smp)
passkey %= 1000000;
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
BT_INFO("Legacy passkey %u", passkey);
}
if (bt_auth && bt_auth->passkey_display) {
atomic_set_bit(smp->flags, SMP_FLAG_DISPLAY);
bt_auth->passkey_display(conn, passkey);
@ -5287,6 +5295,13 @@ int bt_smp_le_oob_set_tk(struct bt_conn *conn, const uint8_t *tk)
return -EINVAL;
}
if (IS_ENABLED(CONFIG_BT_LOG_SNIFFER_INFO)) {
uint8_t oob[16];
sys_memcpy_swap(oob, tk, 16);
BT_INFO("Legacy OOB data 0x%s", bt_hex(oob, 16));
}
memcpy(smp->tk, tk, 16*sizeof(uint8_t));
legacy_user_tk_entry(smp);