Skip to content

7.15 audit 3/6: recovery and entropy - #361

Closed
BitHighlander wants to merge 4 commits into
release/715-audit-02-clearsigningfrom
release/715-audit-03-recovery-entropy
Closed

7.15 audit 3/6: recovery and entropy#361
BitHighlander wants to merge 4 commits into
release/715-audit-02-clearsigningfrom
release/715-audit-03-recovery-entropy

Conversation

@BitHighlander

Copy link
Copy Markdown
Owner

What changed

  • hardens the PIN KDF and storage migration path
  • adds seed locking, BIP-85 derivation, and recovery fixes
  • adds auditable device entropy and on-device dice input
  • clears the dice digest when PIN setup is cancelled
  • includes storage, recovery, BIP-85, authenticator, RNG, and dice tests/evidence

Why

These changes all govern seed creation, derivation, storage, and recovery. Keeping them together makes the secret-lifecycle audit continuous instead of splitting state transitions across PRs.

Validation

  • aggregate six-bundle container build and unit suite passed
  • storage migration, recovery, authenticator, and dice vectors passed
  • git diff --check

Stack: 3 of 6. Review only the diff from release/715-audit-02-clearsigning.

@BitHighlander

Copy link
Copy Markdown
Owner Author

CI queue note: this head was explicitly dispatched at https://github.com/BitHighlander/keepkey-firmware/actions/runs/31128231140 after the superseded 17-PR stack saturated the Actions queue. GitHub currently shows the jobs queued before runner assignment. The complete aggregate independently passed the CI-equivalent container suite locally: 405 firmware, 2 board, 18 crypto, and 7 Pallas constant-time tests, plus actionlint, gitleaks, the Pallas API-boundary gate, and git diff --check.

Storage:
- The PIN key-derivation function is versioned so its cost can be raised
  without breaking existing wallets, with the migration path documented in
  docs/security/pin-kdf-v19-migration.md.
- A wallet created by bitcoin-only firmware is stamped, and multi-chain
  firmware refuses to touch it (storage_isBitcoinOnlyLocked) rather than
  silently operating on a wallet whose owner chose a reduced attack surface.
- Storage layout reserves the clear-sign identity block and zeroes it on read
  and on wipe, so nothing there can outlive a factory reset.
- Orchard key derivation and seed fingerprinting are reachable through storage
  with progress reporting, guarded by the privacy build flag.
- docs/security/anti-rollback-security-epoch-rfc.md records the proposed
  security-epoch scheme; it is a design note, nothing here implements it.

BIP-85:
- GetBip85Mnemonic derives a child mnemonic and displays it under constant
  power, with PIN and initialization checks. Always available — it is a seed
  derivation, not a coin engine.

Recovery and authenticator:
- The cipher-recovery wordlist permutation now borrows the shared frame arena
  instead of another multi-kilobyte stack buffer.
- wipeAuthData reports failure instead of always claiming success, a cancelled
  authenticator action is distinguishable from an error, and a cancelled
  passphrase prompt aborts the request instead of continuing without one.
…isplay

RNG:
- The RNG source selection is explicit and reportable, and a host can pull bulk
  samples for a health audit: a per-boot 64 KB budget replaces the
  press-per-kilobyte prompt that made auditing real hardware impossible.
  Scope is stated honestly in the code and docs — bulk output supports HEALTH
  testing (stuck/biased output, repeated buffers, transport caching, gross
  correlation), not a bound on the entropy of the generator's internal state.
- On an uninitialized device, one press unlocks the bulk audit; on an
  initialized device the confirm still gates entropy after the budget is spent.
- The emulator gets a real CSPRNG (lib/emulator/random.c, BCryptGenRandom on
  Windows) instead of libc random(), which CI now enforces.

Dice:
- ResetDevice can request on-device dice entropy: short press advances 1-6,
  long press confirms, undo is available, and the roll digest is confirmed
  before the seed is mixed. Pre-initialization only.
- The abort path disarms EntropyAck, so an aborted reset can no longer leave the
  device accepting host-supplied entropy for the seed.
- Evidence frames under docs/security/evidence/dice-entropy-reset, reproducible
  with scripts/emulator/capture-dice-flow.py.

Internal entropy is no longer displayed or returned: it is seed pre-image
material. display_random stays in the wire schema for host compatibility and is
ignored.
Restores the RC18 invariant that fails the build if lib/rand/rng.c falls back to
libc random(). It was previously declared in the foundation slice, three PRs
before the emulatorRandom() implementation landed, so it only ever fired on code
its own PR could not fix. Here it guards a change that is present in the same
commit range, which is the whole point of a build-config invariant: the July 2026
COLDCARD loss came from a build selecting the wrong RNG silently, and a gate that
cries wolf is one reviewers learn to skip.
@BitHighlander
BitHighlander force-pushed the release/715-audit-02-clearsigning branch from 53b14bb to 6c27e11 Compare August 8, 2026 22:10
@BitHighlander
BitHighlander force-pushed the release/715-audit-03-recovery-entropy branch from e3457e0 to 39555bd Compare August 8, 2026 22:10
@BitHighlander

Copy link
Copy Markdown
Owner Author

Superseded by #364, which now carries the whole 7.15 stack against develop.

Once the CI gate stopped short-circuiting the build (the libc-random() invariant was asserted three slices before the fix that satisfies it, so check-submodules failed and every build/test job was SKIPPED), these branches compiled for the first time — and none of them compile. The topic-based split cuts across at least three signature/caller pairs:

  • audit-01: app_layout.h declares layout_cipher with 3 args; recovery_cipher.c:380 still calls it with 2. Caller is fixed in the recovery slice.
  • audit-02 / audit-03: thortx.c:265: implicit declaration of 'thorchain_confirm_full_memo' — callee lands in the chains slice.
  • audit-05: ethereum_address_checksum / hdnode_get_ethereum_pubkeyhash — resolved only by the bitcoin-only variant gating in 06.

The dependency graph is a tangle, not a chain, so re-slicing it by build order means re-authoring the release. Only the complete set compiles, and #364 is green. No content is dropped.

@BitHighlander
BitHighlander deleted the release/715-audit-03-recovery-entropy branch August 9, 2026 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant