diff --git a/scripts/kconfig/hardened.csv b/scripts/kconfig/hardened.csv index 1f11da6af58..3c2b250ec3a 100644 --- a/scripts/kconfig/hardened.csv +++ b/scripts/kconfig/hardened.csv @@ -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 diff --git a/subsys/bluetooth/host/CMakeLists.txt b/subsys/bluetooth/host/CMakeLists.txt index a56ff6b8c53..404011e7c69 100644 --- a/subsys/bluetooth/host/CMakeLists.txt +++ b/subsys/bluetooth/host/CMakeLists.txt @@ -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." ) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index afc82375bf1..326d7d1f347 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -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 diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index f33884df645..93e29c1186c 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -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", diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 517d9516a00..e8cd262d803 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -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; } diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index 7560d722e7a..97869b908ab 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -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) */ diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index 0798bef3eca..e51329d68c4 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -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); diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 75020fd85b1..dfb9231ce41 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -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);