Summary
Reset and recovery abort paths do not wipe all mnemonic material, and one recovery finalization error leaves the ceremony armed.
Found while auditing PR #604 at exact head 1d446ccbc9cf32a6e499990e65bcf7b358f1325b.
Evidence
Reset mnemonic survives cancellation
lib/firmware/reset.c:394 calls mnemonic_from_data().
deps/crypto/trezor-firmware/crypto/bip39.c:65-100 stores the result in static CONFIDENTIAL char mnemo[...]; only mnemonic_clear() wipes it.
lib/firmware/reset.c:405-416, :448-452, and :493-499 abort after mnemonic creation without calling mnemonic_clear().
- The
exit: cleanup at reset.c:509-518 wipes display-format buffers, not the BIP-39 static.
Recovery fragments survive cancellation
lib/firmware/recovery_cipher.c:426-427 declares function-static confidential coded_word and decoded_word buffers.
recovery_cipher_reset() at :64-72, called by setup_abort(), wipes the global mnemonic and cipher but cannot reach those function statics.
- They are wiped only on the next word's local control flow (
:429-434, :467-469).
Invalid final word count stays armed
recovery_cipher_finalize() at :548-556 returns on an invalid inferred word count without calling recovery_cipher_abort() / setup_abort().
Impact
Medium — confidential seed material and ceremony authorization outlive cancel/error boundaries. Exploiting the residual bytes for disclosure requires another memory-read primitive, but the armed-state error is directly host reachable and violates the ceremony isolation contract.
Acceptance criteria
Summary
Reset and recovery abort paths do not wipe all mnemonic material, and one recovery finalization error leaves the ceremony armed.
Found while auditing PR #604 at exact head
1d446ccbc9cf32a6e499990e65bcf7b358f1325b.Evidence
Reset mnemonic survives cancellation
lib/firmware/reset.c:394callsmnemonic_from_data().deps/crypto/trezor-firmware/crypto/bip39.c:65-100stores the result in staticCONFIDENTIAL char mnemo[...]; onlymnemonic_clear()wipes it.lib/firmware/reset.c:405-416,:448-452, and:493-499abort after mnemonic creation without callingmnemonic_clear().exit:cleanup atreset.c:509-518wipes display-format buffers, not the BIP-39 static.Recovery fragments survive cancellation
lib/firmware/recovery_cipher.c:426-427declares function-static confidentialcoded_wordanddecoded_wordbuffers.recovery_cipher_reset()at:64-72, called bysetup_abort(), wipes the global mnemonic and cipher but cannot reach those function statics.:429-434,:467-469).Invalid final word count stays armed
recovery_cipher_finalize()at:548-556returns on an invalid inferred word count without callingrecovery_cipher_abort()/setup_abort().Impact
Medium — confidential seed material and ceremony authorization outlive cancel/error boundaries. Exploiting the residual bytes for disclosure requires another memory-read primitive, but the armed-state error is directly host reachable and violates the ceremony isolation contract.
Acceptance criteria
mnemonic_clear()on every reset exit aftermnemonic_from_data(), including direct-return cancellation.recovery_cipher_reset().setup_abort().setup_isArmed()is false.