What changed, and why it matters
This bootloader patch makes the device explicitly turn off its Bluetooth Low Energy (BLE) radio when the hardware receives a power-off command. Without this fix, the BLE chip might stay on during shutdown, which could waste battery, cause unexpected radio behavior, or keep the device discoverable longer than intended. The change is defensive and improves shutdown hygiene rather than fixing an obvious remote attack.
Treat as a low-to-moderate hardening fix. Verify that ble_init/ ble_issue_command cannot be abused from untrusted firmware, confirm the 5-second timeout does not block safe shutdown, and ensure other reset/reboot paths also disable BLE if needed. No urgent user action is indicated by the diff alone.
Security signals we found
Bluetooth/BLE power state not explicitly cleared on shutdown before patch
Adds explicit BLE_SWITCH_OFF command during bootloader power-off sequence
Potential information-disclosure or side-channel risk from BLE remaining active after intended power-off
Battery-drain / denial-of-availability risk if radio stays on unexpectedly
Evidence from the diff
In core/embed/projects/bootloader/main.c, the bootloader now checks for BOOT_COMMAND_POWER_OFF and, when USE_BLE is defined, initializes the BLE stack, waits up to 5 seconds for the BLE state to become known, then issues a BLE_SWITCH_OFF command. Previously the bootloader path for power-off did not contain this explicit BLE shutdown sequence. The patch is additive and partial: it does not show what happened before or whether other shutdown paths already handled BLE.
Changed components
Trezor Core bootloaderBLE subsystem (conditional on USE_BLE)Power-off command handlerInspect captured patch +20 / −0
diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c
index e1ab04e9..2c9e407c 100644
--- a/core/embed/projects/bootloader/main.c
+++ b/core/embed/projects/bootloader/main.c
@@ -174,6 +174,26 @@ static secbool boot_sequence(void) {
turn_on = false;
}
+ if (cmd == BOOT_COMMAND_POWER_OFF) {
+#ifdef USE_BLE
+ ble_init();
+
+ uint32_t timeout = ticks_timeout(5000);
+ ble_state_t state = {0};
+ do {
+ ble_get_state(&state);
+ if (state.state_known) {
+ break;
+ }
+ } while (!ticks_expired(timeout));
+
+ ble_command_t stop_cmd = {
+ .data_len = BLE_SWITCH_OFF,
+ };
+ ble_issue_command(&stop_cmd);
+#endif
+ }
+
uint32_t press_start = 0;
bool turn_on_locked = false;
bool bld_locked = false;
Why this scored 35/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.