Merge pull request #2263 from KeystoneHQ/driver-optimize
What changed, and why it matters
This commit updates the hardware random number generator (TRNG) driver in a cryptocurrency hardware wallet firmware. It adds detection for a physical fault/attack signal from the TRNG and, if triggered, wipes the random data and aborts via an assertion. This is a defensive hardening change that makes it harder for an attacker to feed bad randomness into cryptographic key generation, which could otherwise let them guess or recover private keys.
Review whether the assertion path leaves the device in a safe, user-visible failure state rather than a crash/reboot loop. Verify that TRNG_IT_RNG0_ATTACK is documented by the MHSCPU vendor as a true attack/fault indicator and that the polling loop has a safe timeout. Audit all callers of TrngGet() to ensure they handle a zero-filled buffer correctly if assertion behavior is ever softened. Consider adding a factory-recovery or warning screen when the TRNG attack flag is raised.
Security signals we found
Added TRNG fault/attack status detection (TRNG_IT_RNG0_ATTACK)
Zeroization of sensitive local buffer and output buffer on TRNG failure
Assertion abort on detected TRNG attack condition
Secure memory helpers (memset_s) introduced for clearing random material
Driver hardening in entropy source used for cryptographic key generation
Evidence from the diff
The patch refactors src/driver/drv_trng.c. A new helper TrngReadBlock() starts the TRNG and polls TRNG_Get() until data is ready, while checking TRNG_IT_RNG0_ATTACK. If the attack interrupt/status is set, it returns false. TrngGet() now uses this helper, zeroizes both the local 128-bit block and the entire caller buffer on failure, asserts(false), and returns. The change also adds null-pointer handling for the buffer and uses memset_s/memcpy_s-style secure clearing. The driver now treats a TRNG attack/fault condition as fatal rather than silently returning potentially manipulated entropy.
Changed components
src/driver/drv_trng.cTRNG0 driverFirmware entropy/Random number generation subsystemInspect captured patch +29 / −5
### src/driver/drv_trng.c
@@ -1,7 +1,22 @@
#include "drv_trng.h"
#include "mhscpu.h"
-//#include "string.h"
-//#include "log_print.h"
+#include "mhscpu_trng.h"
+#include "assert.h"
+#include "user_memory.h"
+
+static bool TrngReadBlock(uint32_t output[4])
+{
+ TRNG_Start(TRNG0);
+
+ while (TRNG_Get(output, TRNG0) != 0) {
+ if (TRNG_GetITStatus(TRNG_IT_RNG0_ATTACK) == SET) {
+ return false;
+ }
+ }
+
+ // Data-ready and attack can be asserted at the same time.
+ return TRNG_GetITStatus(TRNG_IT_RNG0_ATTACK) == RESET;
+}
void TrngInit(void)
{
@@ -11,15 +26,24 @@ void TrngInit(void)
void TrngGet(void *buf, uint32_t len)
{
- uint32_t buf4[4];
+ uint32_t buf4[4] = {0};
+
+ ASSERT(buf != NULL || len == 0);
for (uint32_t i = 0; i < len; i += 16) {
- TRNG_Start(TRNG0);
- while (0 != TRNG_Get(buf4, TRNG0));
+ if (!TrngReadBlock(buf4)) {
+ memset_s(buf4, sizeof(buf4), 0, sizeof(buf4));
+ memset_s(buf, len, 0, len);
+ ASSERT(false);
+ return;
+ }
+
if (len - i >= 16) {
memcpy((uint8_t *)buf + i, buf4, 16);
} else {
memcpy((uint8_t *)buf + i, buf4, len - i);
}
}
+
+ memset_s(buf4, sizeof(buf4), 0, sizeof(buf4));
}Why this scored 67/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.