fix(core): preserve BLE peer count info during suspend
What changed, and why it matters
This small firmware patch makes sure a Bluetooth Low Energy (BLE) connection counter is saved before the device goes to sleep and restored when it wakes up. Without this, the device could forget how many peers it thinks are connected after suspend/resume, which might confuse the wallet's Bluetooth state machine and lead to minor glitches or unexpected behavior. There is no direct evidence in the commit that this is an exploitable security vulnerability.
Treat as a low-risk robustness fix. Review whether `peer_count` is used in any security-relevant decisions (e.g., pairing authorization, connection acceptance) and ensure the resumed value is validated against the BLE stack after resume. No urgent action required absent additional context.
Security signals we found
State desynchronization across suspend/resume could theoretically cause incorrect access-control decisions based on stale or zero peer count.
No input validation or bounds checking is added for the restored peer_count value.
No changelog entry suggests the fix is treated as routine robustness rather than a security issue.
Evidence from the diff
The change adds a peer_count field to ble_wakeup_params_t and copies drv->peer_count into it during ble_suspend(), then restores it in ble_resume(). Previously this counter was not persisted across the suspend/resume cycle, so the BLE driver state could desynchronize from the actual stack state. The patch is purely state-preservation; it does not add validation, bounds checks, or logic changes beyond copying the byte.
Changed components
Trezor Core BLE driver (`core/embed/io/ble/stm32/ble.c`)Trezor Core BLE public header (`core/embed/io/ble/inc/io/ble.h`)BLE suspend/resume state managementInspect captured patch +3 / −0
diff --git a/core/embed/io/ble/inc/io/ble.h b/core/embed/io/ble/inc/io/ble.h
index 720693551..484445774 100644
--- a/core/embed/io/ble/inc/io/ble.h
+++ b/core/embed/io/ble/inc/io/ble.h
@@ -70,6 +70,7 @@ typedef struct {
typedef struct {
bool accept_msgs;
bool reboot_on_resume;
+ uint8_t peer_count;
ble_mode_t mode_requested;
uint8_t connected_addr[6];
uint8_t connected_addr_type;
diff --git a/core/embed/io/ble/stm32/ble.c b/core/embed/io/ble/stm32/ble.c
index 286f2420e..918d31d72 100644
--- a/core/embed/io/ble/stm32/ble.c
+++ b/core/embed/io/ble/stm32/ble.c
@@ -573,6 +573,7 @@ void ble_suspend(ble_wakeup_params_t *wakeup_params) {
bool connected = drv->connected;
wakeup_params->accept_msgs = connected;
wakeup_params->mode_requested = drv->mode_requested;
+ wakeup_params->peer_count = drv->peer_count;
memcpy(&wakeup_params->adv_data, &drv->adv_cmd, sizeof(drv->adv_cmd));
ble_deinit_common(drv);
@@ -611,6 +612,7 @@ bool ble_resume(const ble_wakeup_params_t *wakeup_params) {
irq_key_t key = irq_lock();
drv->connected_addr_type = wakeup_params->connected_addr_type;
+ drv->peer_count = wakeup_params->peer_count;
memcpy(drv->connected_addr, wakeup_params->connected_addr,
sizeof(drv->connected_addr));
memcpy(&drv->adv_cmd, &wakeup_params->adv_data, sizeof(drv->adv_cmd));
Why this scored 19/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.