Fix crash when clearing NRF52 BLE bonds (#6609)

* Fix crash before clearing BLE bonds

* Prevent clients re-pairing BLE during factory reset
Clients seem able to re-pair BLE after clearing bonds during factory reset, even after advertising disabled. This seems to primarily occur on Android devices, which seem to more actively maintain the BLE connection.
As a workaround, `NRF52Bluetooth::shutdown` swaps the BLE pairing callback to one which actively rejects new connections.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
pull/6614/head
todd-herbert 2025-04-18 10:11:42 +12:00 zatwierdzone przez GitHub
rodzic e2f6600cb9
commit 74b3dc34e4
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
3 zmienionych plików z 32 dodań i 12 usunięć

Wyświetl plik

@ -450,7 +450,6 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
nvs_flash_erase();
#endif
#ifdef ARCH_NRF52
Bluefruit.begin();
LOG_INFO("Clear bluetooth bonds!");
bond_print_list(BLE_GAP_ROLE_PERIPH);
bond_print_list(BLE_GAP_ROLE_CENTRAL);

Wyświetl plik

@ -210,17 +210,8 @@ void NRF52Bluetooth::shutdown()
{
// Shutdown bluetooth for minimum power draw
LOG_INFO("Disable NRF52 bluetooth");
uint8_t connection_num = Bluefruit.connected();
if (connection_num) {
for (uint8_t i = 0; i < connection_num; i++) {
LOG_INFO("NRF52 bluetooth disconnecting handle %d", i);
Bluefruit.disconnect(i);
}
// Wait for disconnection
while (Bluefruit.connected())
yield();
LOG_INFO("All bluetooth connections ended");
}
Bluefruit.Security.setPairPasskeyCallback(NRF52Bluetooth::onUnwantedPairing); // Actively refuse (during factory reset)
disconnect();
Bluefruit.Advertising.stop();
}
void NRF52Bluetooth::startDisabled()
@ -372,6 +363,33 @@ bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passke
LOG_INFO("BLE passkey pair: match_request=%i", match_request);
return true;
}
// Actively refuse new BLE pairings
// After clearing bonds (at factory reset), clients seem initially able to attempt to re-pair, even with advertising disabled.
// On NRF52Bluetooth::shutdown, we change the pairing callback to this method, to aggressively refuse any connection attempts.
bool NRF52Bluetooth::onUnwantedPairing(uint16_t conn_handle, uint8_t const passkey[6], bool match_request)
{
NRF52Bluetooth::disconnect();
return false;
}
// Disconnect any BLE connections
void NRF52Bluetooth::disconnect()
{
uint8_t connection_num = Bluefruit.connected();
if (connection_num) {
// Close all connections. We're only expecting one.
for (uint8_t i = 0; i < connection_num; i++)
Bluefruit.disconnect(i);
// Wait for disconnection
while (Bluefruit.connected())
yield();
LOG_INFO("Ended BLE connection");
}
}
void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_status)
{
if (auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {

Wyświetl plik

@ -19,4 +19,7 @@ class NRF52Bluetooth : BluetoothApi
static void onConnectionSecured(uint16_t conn_handle);
static bool onPairingPasskey(uint16_t conn_handle, uint8_t const passkey[6], bool match_request);
static void onPairingCompleted(uint16_t conn_handle, uint8_t auth_status);
static bool onUnwantedPairing(uint16_t conn_handle, uint8_t const passkey[6], bool match_request);
static void disconnect();
};