The safe path was replaced
New-wallet generation stopped calling Coldcard’s custom hardware RNG and started calling the libngu random interface.
ckcc.rng_bytes(seed) → random.bytes(32)View integration blame FORENSIC CODE REVIEW · COLDCARD MK3 · FIRMWARE 4.x
A safe hardware path, an unsafe library assumption, a broken build guard, and an unchecked integration combined into one predictable wallet-seed path.
01 / FAILURE CHAIN
Each layer relied on an assumption from another layer. No layer verified the complete path from the seed request to physical entropy.
New-wallet generation stopped calling Coldcard’s custom hardware RNG and started calling the libngu random interface.
ckcc.rng_bytes(seed) → random.bytes(32)View integration blame For STM32 builds, libngu treated the global rng_get() function as the hardware random source. Coldcard’s custom hardware function used a different interface.
CHIP_TRNG_32() → rng_get()View adapter blame Coldcard defined MICROPY_HW_ENABLE_RNG as 0. The #ifndef check saw that the name existed and allowed the unsafe build.
#ifndef MICROPY_HW_ENABLE_RNGCompare the board setting Because the hardware implementation was disabled, the global rng_get() symbol came from MicroPython’s deterministic Yasmarang fallback, not the STM32 hardware RNG.
rng_get() → pyb_rng_yasmarang()View fallback source 02 / TIMELINE
Peter’s original 2018 configuration came first and was safe through its own interface. The harmful integration came after the libngu adapter existed.
24 JUL 2018
Peter D. Gray
The board disables MicroPython’s standard hardware-RNG feature and uses a custom Coldcard reader. This design works through ckcc.rng_bytes.
28 JAN 2021
Switck
The adapter calls global rng_get(). Its safety guard uses #ifndef and cannot detect a macro whose value is 0.
01 MAR 2021
Peter D. Gray
The integration replaces the verified Coldcard path without confirming which rng_get() implementation the final binary links.
17 MAR 2021
Coldcard v4.0.0
The release turns two dormant compatibility problems into a security defect in new-wallet seed generation.
Coldcard’s unusual configuration was not enough to cause the defect.
AFTER 01 MAR 2021The new integration connected every failure condition.
03 / RESPONSIBILITY
This assessment ranks direct engineering responsibility for the defect. It does not claim malicious intent or assign legal liability.
Most responsible for the user-impacting bug
The decisive change moved the most sensitive operation—new wallet-seed generation—across a library boundary. That change required proof that the final firmware still reached hardware entropy. The March 2021 integration did not preserve or verify that invariant.
The integration changed the security boundary for wallet seeds. It made the unsafe path reachable and shipped it without a binary-level source check.
The adapter made an unsafe platform assumption. Its incorrect preprocessor guard failed at the exact job it was meant to perform.
Review and release tests did not prove entropy provenance in the linked firmware. Output statistics could not detect this failure.
The fallback supplied the weak stream, but it followed the disabled-hardware configuration. The higher layers should have rejected or avoided it.
THE COUNTERFACTUAL TEST
Without Switck’s faulty adapter: the build stops or connects to the correct hardware source.
Without Peter’s integration: Coldcard seed generation stays on its existing hardware-RNG path.
04 / NASA–JPL COUNTERFACTUAL
Yes—but not through one magic rule. Four JPL rules would have reduced the risk. Independent verification of the compiled release would have provided the strongest stop.
WHAT THESE RULES ARE
Gerard Holzmann developed the Power of Ten at the NASA/JPL Laboratory for Reliable Software. They are coding guidelines, not proof that software is safe and not rules that governed Coldcard.
Read all ten rulesUse assertions to detect conditions that must never occur.
Assert that the selected entropy source is a hardware RNG. A byte-diversity check is not enough because a software PRNG can produce varied-looking output.
A source-aware assertion stops startup or the build.
Check function results and validate all parameters.
Make libngu receive an explicit hardware-RNG provider with a verifiable capability. Do not discover a security dependency through a global symbol name.
The incompatible Coldcard adapter cannot be connected.
Limit preprocessor use to inclusion and simple macros.
Remove hidden platform selection from #ifdef branches. If a build condition is unavoidable, test the macro value, not only whether its name exists.
MICROPY_HW_ENABLE_RNG=0 fails closed.
Enable all warnings and run strong static analyzers.
Analyze each board configuration and inspect the final link map. Add a release check that proves rng_get resolves to the intended hardware implementation.
The unexpected software symbol becomes release-blocking evidence.
THE CONTROL MOST LIKELY TO SAVE THE RELEASE
Wallet seeds must originate from the STM32 hardware RNG.
The link map must identify the approved hardware implementation.
Disassembly and hardware tests must confirm the release path.
A reviewer who did not write the integration must approve the evidence.
Source review alone can miss symbol resolution. This gate checks the exact artifact sent to users. NASA’s active software-assurance standard calls for a systematic life-cycle approach that includes independent verification and validation.
NASA-STD-8739.8B ↗Important limit: Rules 8 and 10 would improve detection, but they do not guarantee it. A static analyzer may accept the legal C code. The release-level entropy trace is the decisive safeguard.NASA Software Engineering Handbook ↗