Skip to content

rp23xx: add TRNG driver (hardware /dev/random and /dev/urandom)#19400

Open
ricardgb wants to merge 1 commit into
apache:masterfrom
ricardgb:rp23xx-trng-driver
Open

rp23xx: add TRNG driver (hardware /dev/random and /dev/urandom)#19400
ricardgb wants to merge 1 commit into
apache:masterfrom
ricardgb:rp23xx-trng-driver

Conversation

@ricardgb

Copy link
Copy Markdown
Contributor

Summary

The RP2350 (rp23xx) embeds an Arm CryptoCell-style true random number
generator — a sampled ring oscillator conditioned by von-Neumann, CRNGT and
autocorrelation health tests, presenting 192 bits in the six EHR_DATA words —
but there is no driver for it, so /dev/urandom on rp23xx is the software
xorshift PRNG.

This adds arch/arm/src/rp23xx/rp23xx_rng.c, a polling driver that serves the
conditioned hardware bits as /dev/random and /dev/urandom. Entropy is drawn
rarely (an mbedtls CTR_DRBG seeds once and reseeds occasionally), so a blocking
poll is used rather than interrupt plumbing; health-test failures discard the
block and re-arm the source, so only conditioned entropy is ever returned.

New CONFIG_RP23XX_TRNG selects ARCH_HAVE_RNG, which switches /dev/urandom
from the software PRNG to the hardware source (backing getrandom() and thus any
entropy consumer, e.g. mbedtls).

Impact

  • rp23xx gains a real hardware entropy source; opt-in via CONFIG_RP23XX_TRNG.
  • No change when the option is off (default n).

Testing

Tested on a Raspberry Pi Pico 2 W:

  • /dev/random and /dev/urandom register from the TRNG;
  • a 32-byte read returns at real ring-oscillator sampling latency (~10 ms);
  • two independent 32-byte samples differ (live, non-stuck source);
  • the CryptoCell CRNGT continuous test — which would stall a stuck source —
    passes, and mbedtls seeds its CTR_DRBG from /dev/urandom successfully.

Disclosure: this change was prepared by an AI agent (Claude Code) at the
direction of the author, who reviewed and tested it on hardware before
submission.

🤖 Generated with Claude Code

@ricardgb ricardgb requested a review from jerpelea as a code owner July 11, 2026 11:24
@ricardgb ricardgb force-pushed the rp23xx-trng-driver branch from 65925e5 to 27e4ec0 Compare July 11, 2026 11:55
Comment thread arch/arm/src/rp23xx/rp23xx_rng.c Outdated
Comment thread arch/arm/src/rp23xx/rp23xx_rng.c Outdated
Comment thread arch/arm/src/rp23xx/rp23xx_rng.c Outdated
Comment thread arch/arm/src/rp23xx/rp23xx_rng.c Outdated
@github-actions github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Size: M The size of the change in this PR is medium labels Jul 11, 2026
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

The RP2350 embeds an Arm CryptoCell-style true random number generator:
a sampled ring oscillator conditioned by von-Neumann, CRNGT and
autocorrelation health tests, presenting 192 bits in the six EHR_DATA
words.  Add a polling driver that serves those conditioned bits as
/dev/random and /dev/urandom.  Entropy is drawn rarely (an mbedtls
CTR_DRBG seeds once and reseeds occasionally), so a blocking poll is
used rather than interrupt plumbing; the hardware health-test failures
discard the block and re-arm the source, so only conditioned entropy is
returned.

A startup self-test gates the source before it is trusted: it draws a
sample of the conditioned output and rejects a stuck source (identical
consecutive 192-bit blocks), a constant byte, or an absurd run of equal
bytes.  On failure the source is marked unhealthy and every read returns
-EIO, so an entropy consumer fail-stops rather than minting keys on a
broken source.  (The statistical quality is covered by the hardware
VN/CRNGT/autocorr tests; this catches the gross, silent failure modes.)

New CONFIG_RP23XX_TRNG selects ARCH_HAVE_RNG, which switches
/dev/urandom from the software xorshift PRNG to the hardware source
(backing getrandom() and thus any entropy consumer such as mbedtls).

Tested on a Raspberry Pi Pico 2 W: /dev/random and /dev/urandom
register, the startup self-test passes, a read returns at real ring-
oscillator sampling latency (~10 ms / 32 B), two independent samples
differ, and mbedtls seeds its CTR_DRBG from /dev/urandom successfully.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
@ricardgb ricardgb force-pushed the rp23xx-trng-driver branch from 27e4ec0 to d2531b2 Compare July 11, 2026 16:11
@ricardgb

Copy link
Copy Markdown
Contributor Author

Thanks for the review @xiaoxiang781216 — all four points addressed in d2531b2:

  • dropped the local MIN fallback and used the sys/param.h macro directly (added the include)
  • n = MIN(len - got, RP23XX_TRNG_EHR_BYTES); and return got; casts removed as suggested
  • sample[][] in the startup health check is no longer static (192 bytes on the stack)

Also fixed the check CI failures from the previous push (nxstyle long lines and codespell hits on "EHR"); tools/checkpatch.sh -c -u -m -g now passes locally on the commit.

(As before: this change was made with the help of an AI agent and human-reviewed before pushing.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants