reseed with full 32 bytes of digest from SE1/SE2 entropy sources
What changed, and why it matters
This commit fixes a security weakness in how the COLDCARD MK4 hardware wallet seeds its random number generator (RNG). Previously, the firmware took a 256-bit hash of entropy from two secure elements, but only used the first 32 bits (4 bytes) of that hash to reseed the RNG. The change now uses the full 256-bit (32-byte) digest. More entropy bits means the RNG's initial state is much harder to predict, which matters when the device is generating cryptographic secrets like Bitcoin seed phrases. The commit also adds length checks to make sure the expected amount of entropy is actually received from each secure element.
Treat as a security-hardening fix. Users should update to a release containing this commit once available. Developers should verify that downstream firmware variants (earlier MK revisions, Q) apply the same full-digest seeding pattern and that the length assertions do not introduce a denial-of-service path if secure-element entropy length ever differs under error conditions.
Security signals we found
Reduction in entropy used for RNG seeding from 256 bits to 32 bits in prior code
Use of full SHA-256d digest for RNG reseed
Addition of length assertions on secure-element entropy inputs
Changelog explicitly labels change as 'Security Improvement'
Related changelog entries mention master seed generation and RNG fault handling
Evidence from the diff
In shared/mk4.py’s rng_seeding(), the firmware previously called ngu.hash.sha256d(a+b) on entropy from SE1 (callgate.read_rng(1)) and SE2 (callgate.read_rng(2)), then unpacked only the first 4 bytes as a 32-bit unsigned integer via ustruct.unpack(‘I’, n[0:4]) and passed that to ngu.random.reseed(). The patch removes the truncation, passing the full 32-byte sha256d digest to reseed(). It also adds assertions that SE1 returns 32 bytes and SE2 returns 8 bytes. The changelog frames this as a security improvement: RNG seeding now uses the full 256-bit digest instead of 32 bits.
Changed components
shared/mk4.pyCOLDCARD MK4 RNG seeding routinengu.random.reseed() callerInspect captured patch +4 / −1
### releases/Next-ChangeLog.md
@@ -6,6 +6,8 @@ This lists the new changes that have not yet been published in a normal release.
- Security Improvement: Master seed generation mixes entropy from both Secure
Elements with the STM32 TRNG (previously TRNG only).
+- Security Improvement: RNG is seeded with the full 256-bit digest of entropy
+ from both Secure Elements (previously truncated to 32 bits).
- Bugfix: Detect RNG_SR_SEIS and RNG_SR_SECS, retry safely, and fail closed on persistent faults.
- Bugfix: Prevent access to Seed Vault entries through Seed XOR restore in Delta Mode. Thanks to
Rety for reporting this.
### shared/mk4.py
@@ -42,9 +42,10 @@ def rng_seeding():
a = callgate.read_rng(1) # SE1
b = callgate.read_rng(2) # SE2
+ assert len(a) == 32
+ assert len(b) == 8
n = ngu.hash.sha256d(a+b)
- n, = ustruct.unpack('I', n[0:4])
ngu.random.reseed(n)
Why this scored 59/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.