rng: verify libngu bytes path reaches hardware driver
What changed, and why it matters
This commit adds build-time checks to ensure the firmware's random-number generator actually chains all the way down to the hardware chip. It does not fix a known exploit, but it prevents a future build misconfiguration from silently causing the wallet to use weaker random numbers, which could eventually make private keys guessable. Think of it as adding an assembly-line inspection that verifies a critical safety wire is connected end-to-end.
No immediate user action. Developers should ensure this check runs in CI for all firmware variants and that failures are treated as release-blocking. Review whether similar call-chain checks should cover other critical cryptographic paths (e.g., AES, secp256k1).
Security signals we found
Build-time integrity check for RNG call chain
Verifies hardware TRNG driver is reachable from high-level RNG consumer
Prevents silent fallback to non-hardware entropy sources in a misconfigured build
No runtime code change; purely Makefile/objdump verification
Evidence from the diff
The change extends an existing Makefile target (rng-code-check) in stm32/shared.mk. It now uses arm-none-eabi-objdump to inspect relocations in libngu/random.o and verifies that random_bytes -> my_random_bytes -> checked_chip_trng_read -> rng_get are linked by ARM BL/BLX calls. If any link is missing, the build fails. This is a defensive build-integrity control, not a runtime patch.
Changed components
stm32/shared.mkBuild-time RNG verification target (rng-code-check)libngu random.o linkageHardware RNG driver pathInspect captured patch +26 / −1
### stm32/shared.mk
@@ -56,7 +56,7 @@ firmware-signed.dfu: firmware-signed.bin
$(PYTHON_MAKE_DFU) -b $(FIRMWARE_BASE):$< $@
#
-# Verify correct RNG code was built in.
+# Verify correct RNG code was built in and the bytes consumer reaches it.
#
NM = arm-none-eabi-nm
.PHONY: rng-code-check
@@ -74,6 +74,31 @@ rng-code-check:
echo "ERROR: board rng.o does not define global rng_get"; \
printf '%s\n' "$$board_symbols"; \
exit 1; \
+ fi; \
+ libngu_random="$(BUILD_DIR)/libngu/random.o"; \
+ random_bytes_refs="$$($(OBJDUMP) -r -j .text.random_bytes \
+ "$$libngu_random")" || exit $$?; \
+ if ! printf '%s\n' "$$random_bytes_refs" \
+ | grep -Eq '[[:space:]]R_ARM_(THM_)?CALL[[:space:]]+my_random_bytes([+-].*)?$$'; then \
+ echo "ERROR: ngu.random.bytes does not call my_random_bytes"; \
+ printf '%s\n' "$$random_bytes_refs"; \
+ exit 1; \
+ fi; \
+ my_random_bytes_refs="$$($(OBJDUMP) -r -j .text.my_random_bytes \
+ "$$libngu_random")" || exit $$?; \
+ if ! printf '%s\n' "$$my_random_bytes_refs" \
+ | grep -Eq '[[:space:]]R_ARM_(THM_)?CALL[[:space:]]+checked_chip_trng_read([+-].*)?$$'; then \
+ echo "ERROR: my_random_bytes does not call checked_chip_trng_read"; \
+ printf '%s\n' "$$my_random_bytes_refs"; \
+ exit 1; \
+ fi; \
+ checked_trng_refs="$$($(OBJDUMP) -r -j .text.checked_chip_trng_read \
+ "$$libngu_random")" || exit $$?; \
+ if ! printf '%s\n' "$$checked_trng_refs" \
+ | grep -Eq '[[:space:]]R_ARM_(THM_)?CALL[[:space:]]+rng_get([+-].*)?$$'; then \
+ echo "ERROR: checked_chip_trng_read does not reach rng_get"; \
+ printf '%s\n' "$$checked_trng_refs"; \
+ exit 1; \
fi
# make the DFU file which is shared for upgradesWhy this scored 45/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.