fix(storage): use `rng_fill_buffer_strong()`
What changed, and why it matters
This commit changes how the Trezor hardware wallet generates random numbers used to protect PINs, wipe codes, and encrypted storage. It replaces direct calls to a basic random function with a stronger random-number wrapper for sensitive operations, and adds a weaker wrapper for less critical uses. The change suggests the developers want to enforce a stricter random source for security-critical material, but the commit itself does not explain whether the old function was actually weak or exploitable.
Treat as a hardening commit unless additional context shows the replaced `random_buffer()` calls were using a weak/predictable entropy source. Review the implementation of `rng_fill_buffer_strong()` on the target platform to confirm it uses a hardware TRNG or approved DRBG. Monitor Trezor's security advisories and changelog for any follow-up disclosure.
Security signals we found
RNG source changed for PIN/wipe-code salt generation
New `rng_fill_buffer_strong()` wrapper added for security-sensitive random material
Plain `rng_fill_buffer()` used for non-secret IV generation
Failure paths added when strong RNG fails
No changelog entry and no explicit security description in commit message
Evidence from the diff
The patch introduces rng_fill_buffer() (weak/regular) and rng_fill_buffer_strong() wrappers around random_buffer(). In storage/storage.c, it switches set_wipe_code(), set_pin(), and storage_upgrade() from random_buffer() to rng_fill_buffer_strong(), with added failure handling. The IV generation in storage_set_encrypted() is moved to the plain rng_fill_buffer(). The test header mirrors the new API. The diff implies a security-hardening refactor to separate strong vs. regular RNG requirements, but no vulnerability details, CVE, or advisory are provided.
Changed components
Trezor firmware storage subsystemlegacy secure RNG headerstorage PIN/wipe-code encryptionstorage encrypted blob IV generationC unit-test RNG shimInspect captured patch +20 / −4
diff --git a/legacy/sec/rng.h b/legacy/sec/rng.h
index 3485f640..2cd4528b 100644
--- a/legacy/sec/rng.h
+++ b/legacy/sec/rng.h
@@ -29,3 +29,8 @@ static inline bool rng_fill_buffer_strong(void* buffer, size_t buffer_size) {
random_buffer((uint8_t*)buffer, buffer_size);
return true;
}
+
+static inline bool rng_fill_buffer(void* buffer, size_t buffer_size) {
+ random_buffer((uint8_t*)buffer, buffer_size);
+ return true;
+}
diff --git a/storage/storage.c b/storage/storage.c
index 807484cf..48d80a51 100644
--- a/storage/storage.c
+++ b/storage/storage.c
@@ -408,7 +408,9 @@ static secbool set_wipe_code(const uint8_t *wipe_code, size_t wipe_code_len) {
uint8_t *tag = salt + WIPE_CODE_SALT_SIZE;
memcpy(data, wipe_code, wipe_code_len);
- random_buffer(salt, WIPE_CODE_SALT_SIZE);
+ if (!rng_fill_buffer_strong(salt, WIPE_CODE_SALT_SIZE)) {
+ return secfalse;
+ }
hmac_sha256(salt, WIPE_CODE_SALT_SIZE, wipe_code, wipe_code_len, tag);
secbool ret =
@@ -857,7 +859,9 @@ static secbool set_pin(const uint8_t *pin, size_t pin_len,
uint8_t kek[SHA256_DIGEST_LENGTH] = {0};
uint8_t keiv[12] = {0};
chacha20poly1305_ctx ctx = {0};
- random_buffer(rand_salt, STORAGE_SALT_SIZE);
+ ensure(
+ rng_fill_buffer_strong(rand_salt, STORAGE_SALT_SIZE) ? sectrue : secfalse,
+ "rng_fill_buffer_strong failed");
ensure(derive_kek_set(pin, pin_len, rand_salt, ext_salt, kek),
"derive_kek_set failed");
rfc7539_init(&ctx, kek, keiv);
@@ -1409,7 +1413,7 @@ static secbool storage_set_encrypted(const uint16_t key, const void *val,
// Write the IV to the flash.
uint8_t buffer[CHACHA20_BLOCK_SIZE] = {0};
- random_buffer(buffer, CHACHA20_IV_SIZE);
+ rng_fill_buffer(buffer, CHACHA20_IV_SIZE);
if (sectrue != norcow_update_bytes(key, buffer, CHACHA20_IV_SIZE)) {
return secfalse;
@@ -1859,7 +1863,9 @@ static secbool storage_upgrade(void) {
const uint16_t V0_PIN_FAIL_KEY = 0x0001;
secbool ret = secfalse;
if (norcow_active_version == 0) {
- random_buffer(cached_keys, sizeof(cached_keys));
+ if (!rng_fill_buffer_strong(cached_keys, sizeof(cached_keys))) {
+ return secfalse;
+ }
// Initialize the storage authentication tag.
auth_init();
diff --git a/storage/tests/c/sec/rng.h b/storage/tests/c/sec/rng.h
index 3e4e3e63..61fb4fef 100644
--- a/storage/tests/c/sec/rng.h
+++ b/storage/tests/c/sec/rng.h
@@ -29,3 +29,8 @@ static inline bool rng_fill_buffer_strong(void* buffer, size_t buffer_size) {
random_buffer((uint8_t*)buffer, buffer_size);
return true;
}
+
+static inline bool rng_fill_buffer(void* buffer, size_t buffer_size) {
+ random_buffer((uint8_t*)buffer, buffer_size);
+ return true;
+}
Why this scored 57/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.