Skip to content

Retained key material / stale display state: transaction.c node and eip712.c domain statics #399

Description

@BitHighlander

Summary

Two more function-local/module statics hold derived key material that no teardown path clears. Same class as the signing.c privkey and fsm.c derived-node leaks fixed in #393, found by the same sweep but left unfixed.

1. lib/firmware/transaction.c:272

if (in->address_n_count > 0) {
    static CONFIDENTIAL HDNode node;

Populated via memcpy(&node, root, sizeof(HDNode)) inside compile_output(). No memzero anywhere in the file. Being a function-local static, it is unreachable from fsm_abortAllSigningFlows() without either hoisting it to file scope or adding an abort hook — the same treatment fsm_getDerivedNode()'s node received.

2. lib/firmware/eip712.c:423-424

dsname / dsversion / dschainId / dsverifyingContract are cleared only inside dsConfirm() (eip712.c:509-512, which correctly clears on both approve and cancel). Every early return from parseVals() — including user cancellation and every parse error — leaves them populated.

These are not secrets, so the impact is display integrity rather than key disclosure: stale domain name / version / chainId / verifying-contract values can persist into a subsequent EIP-712 confirmation. Given this is the clear-signing path, showing the user a domain from a previous, abandoned transaction is a real integrity concern.

Acceptance criteria

  • transaction.c node zeroed on every exit and reachable from the central teardown
  • eip712.c domain statics cleared on every exit from parseVals(), not only via dsConfirm()
  • Regression test: abandoned EIP-712 parse followed by a new one shows no stale domain

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity-relevant defect or hardening

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions