Skip to content

upstream #384: fault injection hardening, nanopb memleak, BIP39 validation#64

Closed
BitHighlander wants to merge 6 commits intodevelopfrom
upstream/security-hardening
Closed

upstream #384: fault injection hardening, nanopb memleak, BIP39 validation#64
BitHighlander wants to merge 6 commits intodevelopfrom
upstream/security-hardening

Conversation

@BitHighlander
Copy link
Owner

Summary

Cherry-pick of upstream keepkey#384

Security hardening: fault injection countermeasures, nanopb memory leak fix, BIP39 recovery validation.

Test plan

  • CI green
  • Existing tests pass

BitHighlander and others added 6 commits March 16, 2026 21:11
- Point device-protocol and python-keepkey submodules to upstream master
  (includes BIP-85, Solana, Tron, TON wire IDs and proto definitions)
- Add nanopb .options files for Solana, Tron, TON (field size constraints)
- Add Bip85Mnemonic.mnemonic max_size:241 to messages.options
- Update lib/transport/CMakeLists.txt with new proto sources, options,
  headers, and protoc compilation commands
- Fix CI: use pre-installed clang-format instead of apt-get install
  (eliminates 3-minute timeout on GitHub runners)
- Update Zcash transparent branch ID from Sapling to NU6
…double-hash (F3)

Replace early-return ECDSA verify chain with bitwise-OR accumulation
and sentinel counter. A single voltage glitch can no longer skip one
branch to fall through to SIG_OK — attacker must now corrupt all three
verify results AND the sentinel.

Add double SHA-256 computation with constant-time memcmp_s comparison
to detect transient faults during hash computation.

References: VULN-21020, fault-injection-assessment.md finding F3
…eck (F5)

Remove redundant ~1 second full ECDSA re-verification in firmware main.
The bootloader already performed authoritative signature verification
before jumping here. Replace with fast metadata presence check that
validates signature indices are present and distinct.

Eliminates the wide timing window (VULN-21020 class) where a voltage
glitch during the long-running crypto re-check could bypass protections.

References: VULN-21020, fault-injection-assessment.md finding F5
Moves which_field tag assignment after the conditional memset and only
resets when the oneof variant changes. Prevents allocated memory from
being zeroed before release when PB_ENABLE_MALLOC is active.

Ref: keepkey#361
Upstream: nanopb 4fe23595732b6f1254cfc11a9b8d6da900b55b0c
The condition on line 578 was inverted — `!enforce_wordlist` meant the
wordlist check was skipped when enforce_wordlist was true (the default).
Invalid words were silently accepted and only caught later as a generic
"Invalid mnemonic" checksum error, giving users no indication which
word was wrong.

Flip the condition so that when enforce_wordlist is set, words that
fail auto-complete against the BIP39 list are rejected immediately
with a clear error before the mnemonic is finalized.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously, wordlist validation only happened at finalization after all
words were entered. Invalid words were silently accepted and the user
had to complete the entire 12/24-word entry before getting a vague
"Invalid mnemonic" error with no indication which word was wrong.

Add a BIP39 check in the space handler of recovery_character() that
rejects immediately with "Word not found in BIP39 wordlist" when the
decoded characters don't match any entry. Combined with the
enforce_wordlist condition fix, both per-word and finalization
validation now work correctly.
@BitHighlander
Copy link
Owner Author

Already integrated — all 5 security hardening commits are in our develop (signatures_ok, nanopb leak, BIP39 validation).

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