OSC-2026-0001 · github.com/Coldcard/firmware
critical findings-validated claude-fable-5 2026-08-04 signed: nostr
- Repository
- github.com/Coldcard/firmware
- Commit
- bcc2c382a324690a2fcf972c0bac3b79bf923f7b
- Scope path
- stm32/COLDCARD/
- Model
- claude-fable-5
- Harness
- claude-code
- Prompts
- prompts/entropy-rng-audit-v1.md
- Independent runs
- 1
- Transcript sha256
- 7e7330c5a5a78ddc12401eb9eb8b7b1d5f3fca97b4f90491ee12fc9166c0a41b
- Auditor
- TheIcarusWings (theicaruswings)
- Signature
- nostr-schnorr · npub19tzp8lf3klmqj3dz9mz0qnuvjp7uyy9993gmljmyaxs8phztj7wsnujvq5
Scope. Retrospective, source-grounded audit of the publicly-disclosed Coldcard seed-entropy vulnerability at the last vulnerable commit (bcc2c382, parent of the fix ca724637). In scope: entropy/RNG code paths feeding BIP-39 seed generation on STM32 builds; TRNG-vs-software-PRNG selection; build-time RNG symbol linkage. NOT in scope: PIN/secure-element logic, PSBT handling, USB stack. The ngu.random->C rng_get binding lives in an unfetched submodule and is inferred from the fix's symbol-level assertions plus the Python call sites (confidence: high).
Findings
critical OSC-2026-0001-F1 validated
BIP-39 seed generation draws from a software PRNG instead of the STM32 hardware TRNG. The board file stm32/COLDCARD/rng.c exports the hardware reader only as static rng_get_or_fault() and never defines a global rng_get(); the linker therefore resolves rng_get() to MicroPython's upstream ports/stm32/rng.c, whose implementation falls back to the Yasmarang software PRNG (pyb_rng_yasmarang). Seed material generated via ngu.random (shared/seed.py:605 `seed = ngu.random.bytes(32)`) is thereby drawn from a weak PRNG, cutting effective Mk2/Mk3 seed entropy from 128 bits to ~40 bits (brute-forceable). Confirmed by the fix commit ca724637, which adds a board-level rng_get() wrapping the TRNG, poisons pyb_rng_yasmarang, and adds an arm-none-eabi-nm build-time symbol check asserting the correct rng_get is linked.
Validated by theicaruswings — Validated against source: read the fix diff ca72463709f4e3f8964952039d5caf955f566a87 and the pre-fix tree bcc2c382a324690a2fcf972c0bac3b79bf923f7b. Consistent with Coinkite's advisory (2026-07-31) and Block Engineering's independent analysis. See transcripts/OSC-2026-0001.md for full reproduction steps.