fix(core): Wait for Tropic to boot before trying to start session.
What changed, and why it matters
This commit fixes a timing issue in the Trezor hardware wallet's communication with the Tropic secure chip. Previously, the code simply waited a fixed 100 milliseconds and hoped the chip was ready. Now it actively polls the chip for up to 1 second, waiting until it responds as ready before starting a secure session. This reduces the chance that the chip is still busy when sensitive operations begin, which could otherwise cause failures or potentially unpredictable behavior.
Treat as a hardening fix rather than a confirmed vulnerability. Review whether `LT_L1_CHIP_BUSY` is the only error state that indicates incomplete boot, and ensure the timeout and retry logic cannot be abused to induce a denial-of-service or to leak timing information. Consider adding a changelog entry documenting the robustness improvement.
Security signals we found
Timing/race condition in secure-element initialization
Possible LT_L1_CHIP_BUSY state at session start
Session establishment depends on chip readiness
Fix replaces blind delay with active readiness polling
Evidence from the diff
The patch replaces a fixed hal_delay(100) with a polling loop that repeatedly calls lt_get_info_riscv_fw_ver() until the Tropic chip no longer returns LT_L1_CHIP_BUSY, up to a 1000 ms timeout. The previous arbitrary delay risked starting a session while the chip was still booting. The new approach waits for an explicit readiness signal from the chip before proceeding to session_start().
Changed components
core/embed/sec/tropic/tropic.cTropic secure element driverSecure session initializationInspect captured patch +11 / −3
diff --git a/core/embed/sec/tropic/tropic.c b/core/embed/sec/tropic/tropic.c
index 903241343..36d162d0a 100644
--- a/core/embed/sec/tropic/tropic.c
+++ b/core/embed/sec/tropic/tropic.c
@@ -40,6 +40,9 @@
#ifdef SECURE_MODE
+// Maximum time to wait for Tropic to boot. Chosen arbitrarily.
+#define TROPIC_BOOT_TIMEOUT_MS 1000
+
typedef struct {
bool initialized;
pkey_index_t pairing_key_index;
@@ -123,9 +126,14 @@ bool tropic_init(void) {
goto cleanup;
}
- // Note: Without the delay below Tropic01 may return LT_L1_CHIP_BUSY. The
- // length was chosen arbitrarily. A shorter delay may be sufficient.
- hal_delay(100);
+ // Wait for Tropic to boot before issuing any session commands.
+ uint32_t boot_start_ms = hal_ticks_ms();
+ while (hal_ticks_ms() - boot_start_ms < TROPIC_BOOT_TIMEOUT_MS) {
+ uint8_t ver[LT_L2_GET_INFO_RISCV_FW_SIZE] = {0};
+ if (lt_get_info_riscv_fw_ver(&drv->handle, ver) != LT_L1_CHIP_BUSY) {
+ break;
+ }
+ }
#ifndef TREZOR_EMULATOR
if (session_start(drv, TROPIC_PRIVILEGED_PAIRING_KEY_SLOT)) {
Why this scored 46/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.