January 01, 1970
Keywords: boot entropy, embedded systems, defense-in-depth, radio burst entropy, SRAM PUF, ESP32, Zephyr, entropy as a service, ML-KEM, ML-DSA
Cryptography begins before the first secure packet. A device wakes, initializes drivers, joins a wireless network, and asks a random number generator for values that must already be unpredictable. If these first values are weak, later cryptography inherits the weakness, often invisibly.
The historical record is blunt. The Debian OpenSSL bug collapsed a distribution’s effective key space [1]; Internet-wide scans later traced shared and factorable RSA keys to headless devices generating keys at first boot [2], [3]; smart cards repeated primes [4]; and Dual EC and Juniper show the same danger from deliberate backdoors [5], [6]. The common design error is not that a particular statistical test was missing. It is that the system trusted one opaque source, while the output did not reveal that the source had failed.
Embedded devices are fertile ground for this mistake. Thousands of units may run identical firmware on identical silicon, wake into the same reset vector, and perform the same short network task. The RNG API can keep returning plausible bytes even when the physical source behind it has changed state, a failure mode seen in firmware studies [7]. On ESP32-class boards, for example, the RNG register still returns bytes when documented analog entropy inputs are inactive; in that state, the output is pseudorandom by specification [8]. Section 7.1 shows that this rejected state passes the same statistical screens as RF-active states. Output tests can support a source model, but they cannot replace it.
To mitigate this, we propose a defense-in-depth boot path in which a sensor mixes several roots with different trust bases. The first seed survives the loss, absence, or misbehavior of any one root, as long as at least one credited root remains unknown to the adversary. The network-assisted roots require a connection to a trusted node in the local IoT network, for example a gateway or a dedicated entropy node:
Device intrinsic startup state. Uninitialized SRAM provides physically unclonable function (PUF) material [9], [10]. Stable bits act as a device-bound secret, and noisy bits contribute per-boot variability.
Radio burst extraction. The trusted node sends a public packet burst. The sensor samples its RNG and packet timing during that window and derives a seed locally. The burst receives no entropy credit.
Asymmetric entropy capsules. The trusted node pays the first randomized cryptographic cost, sending a signed KEM seed capsule to a pre-provisioned client public key. The client performs deterministic verification, decapsulation, and hashing [11], [12].
A source-state admission policy decides which roots receive entropy credit on each boot, and a combiner derives the seed from all available roots without summing their claims. The paper develops this credit discipline, defines radio burst extraction under a fully public burst model, and implements the radio burst and capsule paths as open Zephyr artifacts for ESP32 boards. The measurements use separated raw captures, RF state controls, and post-quantum microbenchmarks.
Weak-key scans and direct boot-time measurements establish the cold-start problem for headless devices [2], [3]. Robust pool constructions [13] and IoT PRNG guidelines [14] address conditioning and recovery, while entropy-source standards separate tests from credit. SP 800-90B requires a model of the noise source, its expected entropy, and its health tests [15]; AIS 20/31 makes the source assumptions explicit through functionality classes [16]; and Saarinen’s critique of black-box batteries warns that weak generators can pass statistical screens and still be cryptographically useless [17].
Remote entropy services move the source off the device. Entropy-as-a-Service delivers randomness to systems that cannot gather enough locally [18]; our previous QEaaS prototype delivered QRNG-backed entropy to ESP32-class clients over CoAP/DTLS with post-quantum primitives [19]. Such services can refill a device after boot and, with a pre-provisioned client public key, can also cover cold start. The tradeoff is that the server generating the bits also knows them. Capsules use that tradeoff as one root, while the public key protects the delivered seed from outside observers. RFC 8937 takes a local hedging route, mixing long-term private-key material into protocol randomness [20].
Physical layer key generation starts from another intuition. Two nearby radios observe the same wireless channel from opposite ends and distill a shared key from measurements that an outside observer cannot reproduce exactly [21]–[23]. Induced-randomness and RIS variants add controlled perturbations when the channel is too static [24]–[26]. Radio burst extraction makes a narrower claim. The trusted node’s burst is public, the client samples its own local response, and the trusted node receives no entropy credit.
Wireless TRNG work also treats the radio path as part of the randomness mechanism. Suzuki and Kaminaga embed a TRNG inside the communication system itself [27]; here the radio packet train is only an actuator, and credited material is sampled inside the client. SRAM power-up state supplies a complementary root. It has long been used as both an identifying fingerprint and a true-random source [9], [10], [28]. We use the stable component for local secrecy and the noisy component for possible freshness, while separate entropy credit awaits cold power and population measurements.
At first boot, a node may need random values before it has evidence that any local source is ready. DTLS 1.3 consumes randomness in fresh protocol values and ephemeral key exchange [29], [30]. KEM-based protocols still need randomness; they only decide which party pays the randomized step [11], [31]. A pre-shared-key mode moves the problem to provisioning, storage, and rotation.
The first seed must therefore depend on at least one input that the adversary cannot determine. We call such an input a root of unpredictability. It may provide secrecy because the value is hidden from a remote adversary, freshness because it changes from boot to boot, or both. Network messages can coordinate the protocol and record what happened, but cannot by themselves create a secret seed.
We assume a strong local adversary. It observes all radio traffic, knows the firmware, extraction functions, access point configuration, schedules, payload patterns, and nonces, and can replay, delay, drop, inject, interfere, and stand near the node. It does not have code execution and cannot read internal memory or registers. It may try to degrade local entropy sources, for example by jamming, saturating the receiver front end, or injecting periodic signals into a physical noise source [32].
The adversary wins if it can predict the node’s first seed with non-negligible advantage. For a root of unpredictability \(R\) collected during public events \(S\), the requirement is \[H_\infty(R \mid S, O_A) \geq k,\] where \(O_A\) is the adversary’s observation and influence of the RF and network environment, and \(k\) is empirical and platform-specific. We do not assume a value of \(k\) for any root. The artifacts gather per-root evidence, and the architecture remains safe when a claim fails.
The architecture admits roots independently and mixes all available material. If one root is absent, degraded, or later judged uncreditable, the seed can still rely on another credited root whose value is outside the adversary’s view. No credit is assigned merely because several inputs were combined.
Uninitialized SRAM settles into a power-up pattern shaped mostly by per-cell manufacturing mismatch, with a minority of cells that flip between power-ups [9], [28]. The stable majority can provide device-local secret material against a remote adversary; the noisy minority can add per-boot variation. We do not reconstruct a stable SRAM key. The combiner hashes the observed bytes as one noisy input, and deployments that need a stable identity can add helper-data or fuzzy-extractor constructions [10], [33]. The read must happen at cold power-up before initialization touches the region. Our current ESP32 data comes from controlled resets of one board, so SRAM is mixed only as additional material; entropy credit awaits a cold-power study across boots and boards.
The second root uses the wireless environment as an actuator. The trusted node sends a public burst descriptor and a controlled packet train; the sensor samples local uncertainty during the burst window and derives its contribution internally. Learning the result would require reproducing the sensor’s analog response and timing observations.
On the ESP32 this root also moves the chip RNG into its documented true-entropy state, because the high speed ADC is enabled with the radio [8]. Plain association can make WDEV eligible under this model. The burst adds a bounded receive window, audit data, liveness evidence, and timing side material. For the predictability study, we use a deterministic burst so every trial presents the same public stimulus. The implementation also supports randomized payloads and jittered intervals. Section 5 gives the measurement method; Section 7.2 evaluates it.
The third root uses pre-provisioned asymmetric key material to break the bootstrapping loop. Before deployment, the device receives a decapsulation private key, or a protected seed from which that key is derived, plus a trust anchor for the trusted node. The trusted node holds or obtains the matching client public key. The capsule exchange in Figure 1 runs before DTLS over UDP or CoAP over UDP; the client does only deterministic verification, decapsulation, and hashing before accepting the seed [11], [12].
The capsule is the fallback root. If local source state is unavailable, jammed, or outside policy, it still seeds the device at the cost of enrollment and trust in the trusted node. Per-boot freshness comes from new encapsulation randomness at that trusted node. A capsule-only boot using ML-KEM-512 is bounded by Category 1 confidentiality, roughly the 128-bit security level; the 256-bit value names the pool input size, while the KEM category sets confidentiality. Deployment profiles should size the KEM for the target security level and use a classical and post-quantum hybrid, for example X25519 and ML-KEM.2 Capsules deliver protected remote entropy; radio burst extraction stimulates local entropy the trusted node cannot learn.
Replay protection cannot depend on a fresh client nonce at first boot. The prototype binds each capsule to the device identity, trusted node identity, algorithm profile, and boot transcript; deployments should also keep persistent replay state, such as a monotonic counter or a record of accepted capsule sequence numbers. Without that state, replayed capsules can be mixed as non-harmful auxiliary input, but they cannot receive capsule-only freshness credit.
Credit is a policy decision made per boot, per root, from state the firmware can check. In our ESP32 admission policy, WDEV output is credited only when Wi-Fi or Bluetooth puts the chip in the documented analog source state; RF-disabled output is rejected regardless of its byte distribution. SRAM is credited only after verified cold power-up. Timing jitter enters as side material. Capsule material is credited after signature, transcript, and replay checks pass. If an active attacker degrades a source, firmware rejects that source or falls back to the capsule.
Let \(P\) be the SRAM startup read, \(R\) the radio burst response, \(C\) the decapsulated capsule material, and \(W\) direct chip RNG output under gating, with any absent root replaced by an empty string and its absence recorded in the transcript \(T\). The seed is \[\begin{align} \rho &= H(P \parallel R \parallel C \parallel W),\\ seed &= \mathsf{HKDF-SHA256}\big(\mathsf{ikm}=\rho,\;\mathsf{salt}=H(T),\\ &\qquad \mathsf{info}=\texttt{boot-entropy-combiner-v1}\big), \end{align}\] where \(H\) denotes SHA-256, \(\rho\) is the pre-extraction digest of the encoded roots, ikm is HKDF’s input keying material, and \(T\) binds the public burst descriptors, capsule transcript, and root availability flags. Each root is encoded with an explicit length and a domain tag before concatenation [35].
The security argument is deliberately modest. HKDF extracts a pseudorandom key from input material that may be non-uniform or partly influenced by an attacker, provided enough entropy remains after conditioning on public context [35]; robust pools and PRNGs with input give the same engineering lesson for continual mixing [13], [36]. If at least one credited root remains hidden after conditioning on the public transcript and the other inputs, then hashing the encoded roots before HKDF preserves an unpredictable seed under the usual random oracle heuristic. The derivation creates no new credit. We assign the seed the credit of the single best supported root, never the sum across roots, because summation would need an independence argument between analog RNG noise, timing jitter, and SRAM mismatch on the same die. Production systems should inject the derived seed into the normal pool, such as the operating system pool or a compact BLAKE2s pool, before applications consume randomness [37]. If every credited root is predictable given the adversary’s view, so is the seed.
A radio burst measurement consists of a public burst plan \(B_i\) and a local device response \(R_i\). The node first sends a boot-style UDP HELLO. The collector replies with
a START message and then zero or more BURST packets: \[\begin{align}
B_i = (&\mathsf{trial}_i,\mathsf{nonce}_i,\mathsf{burst\_count},\\
&\mathsf{interval},\mathsf{sample\_bytes}).
\end{align}\] Here \(\mathsf{trial}_i\) identifies the trial, \(\mathsf{nonce}_i\) is the collector challenge, \(\mathsf{burst\_count}\) is the number
of burst packets, \(\mathsf{interval}\) is the nominal inter-packet spacing, and \(\mathsf{sample\_bytes}\) is the amount of WDEV output sampled by the client. The HELLO, nonce,
schedule, and \(\mathsf{trial}_i\) are public and receive zero entropy credit. The main experiment reuses the same START nonce, burst count, spacing, and payload in every trial, so a changing public stimulus
cannot explain a changing client response. The implementation can also send random payloads and jittered packet intervals for weaker-observer deployments; in the full-observer model used here, every packet and timing choice is public metadata.
The device response is \[R_i = W_i \parallel J_i,\] where \(W_i\) is the sequence of chip RNG bytes sampled during the burst window and \(J_i\) is the sequence of packet arrival deltas observed by the device. Per trial, the firmware derives \[\begin{align} \rho_i &= H(R_i), \qquad \tau_i = H(B_i),\\ seed_i &= \mathsf{HKDF-SHA256}\big(\mathsf{ikm}=\rho_i,\;\mathsf{salt}=\tau_i,\\ &\qquad \mathsf{info}=\texttt{radio-burst-entropy-v1}\big), \end{align}\] which becomes the \(R\) input of Section 4.5. The evaluation isolates this root by removing PUF samples, stored seeds, capsules, KEM, TLS, and DTLS from the measured path [35].
The artifacts are standalone Zephyr applications for the ESP32-DevKitC V4 (ESP32-WROOM-32, dual core Xtensa LX6 at 240 MHz); the workshop version is release v0.1.0 of wireless-boot-entropy-zephyr: https://github.com/perlab-uc3m/wireless-boot-entropy-zephyr/releases/tag/v0.1.0. All wireless benchmarks used a TP-Link Archer AX73 router; the ESP32
associated over 802.11n at 2.4 GHz, and host-side collectors and capsule servers ran on a Dell OptiPlex 3000 with an Intel Core i5-12500T, 15.69 GiB RAM, Ubuntu 22.04.2, and Gigabit Ethernet to the router. WDEV refers to the ESP32 wireless device RNG path
exposed by WDEV_RND_REG (also RNG_DATA_REG, 0x3FF75144) and used by Zephyr’s ESP32 entropy driver [8]. The radio burst and RF-state measurements bypass the custom Zephyr BLAKE2s pool and read the stock entropy device, so they characterize the WDEV source directly. The capsule benchmark build disables local hardware
refills after entropy device initialization, isolating the deterministic client path.
The radio burst path starts when the device under test (DUT) joins Wi-Fi and sends the burst artifact’s public HELLO, distinct from the capsule BOOT_HELLO. The collector script, scripts/aeb_collector.py, answers
with a binary START and emits the burst train. After each valid burst packet, the DUT records the packet arrival delta and samples WDEV output; lost packets are counted and represented by local filler. Firmware logs hashes of the WDEV bytes,
timing stream, combined response, and derived seed, while entropy-test runs upload pre-hash WDEV bytes in binary UDP chunks so \(W_i\), \(J_i\), and \(W_i \parallel
J_i\) remain separable.
The collector controls nonce mode, burst count, interval, payload mode, and trial count, then writes a run manifest with WDEV trials, packet deltas, schedule residuals, and joint responses. In --fixed-nonce mode, repeated trials reuse the
same public challenge; randomized runs record their public schedules and payload hashes.
The esp32-rf-rng-state harness captures bulk WDEV output under controlled RF conditions: RF disabled, with the Wi-Fi driver omitted as the documented pseudorandom control; Wi-Fi idle after association and DHCP; Wi-Fi scan with periodic
scans; and, in the reproduction runs, a deterministic UDP burst condition matching the radio burst workload.
The capsule prototype runs on ESP32 with local hardware refills disabled after entropy device initialization in the benchmark build, isolating the deterministic client-side cost of the post-quantum profile. The client sends an 88 B
BOOT_HELLO with its device id, boot counter, uptime, and SRAM and timing commitments. The firmware records both reset-to-seed time and the scheme-specific BOOT_HELLO-to-capsule exchange after Wi-Fi and DHCP are complete. The
prototype server uses a configured ML-KEM client public key and signs a capsule bound to the hello hash. A deployment can instead carry a verifiable public key or certificate in the hello.
The evaluation reports ESP32 RNG source states, fixed burst response, capsule latency, and SRAM startup measurements.
We captured 256 MB streams from RF disabled, associated idle, associated scan, and deterministic UDP burst ESP32 conditions, plus Linux /dev/urandom on the same OptiPlex host as a baseline. ENT [38], SP 800-90B [15], Borel
normality, AIS31 P1/P2, GM/T 0005-2021, PractRand [39], and TestU01 Rabbit [40] were run through our randlab wrapper.3 Table 1 reports the compact result. The SP 800-90B column is the conservative non-IID value, \(\min(H_\mathrm{original}, 8H_\mathrm{bitstring})\), across byte and bitstring views. RF disabled is
the key control. ESP32 documentation identifies it as pseudorandom, yet it passes the same output screens as RF-active modes. Entropy credit must come from source-state policy.
| Condition | Policy role | ENT entropy | SP 800-90B non-IID | Other screens | Rabbit flags |
|---|---|---|---|---|---|
| RF disabled | Reject, documented pseudorandom | 7.999999 | 7.112 | ENT, Borel, AIS31, GM/T, PractRand pass | 3 |
| Wi-Fi idle | Eligible RF-active source state | 7.999999 | 7.204 | ENT, Borel, AIS31, GM/T, PractRand pass | 2 |
| Wi-Fi scan | Eligible RF-active source state | 7.999999 | 7.137 | ENT, Borel, AIS31, GM/T, PractRand pass | 3 |
| UDP burst | Target burst workload | 7.999999 | 7.198 | ENT, Borel, AIS31, GM/T, PractRand pass | 3 |
| /dev/urandom | Host control | 7.999999 | 7.044 | ENT, Borel, AIS31, GM/T, PractRand pass | 0 |
Rabbit flags appear in every ESP32 state, including the documented pseudorandom control and UDP burst workload, while the host control shows none. The other batteries remain useful regression checks; RF-disabled output still receives no entropy credit.
The central radio burst experiment holds the public burst plan constant and asks how much local material the node obtains. The source-separated run used a fixed nonce, constant 64 byte payloads, 64 bursts per trial, 1000 \(\mu\)s nominal spacing, and 8192 pre-hash WDEV bytes per trial. One startup trial was missed, leaving 127 complete trials, 1040384 B of WDEV output, and 8128 packet arrival samples. All commitments matched the uploaded files.
Figure 2 reports the timing evidence. Operationally, the full 64 packet stimulus fits in a short boot window. The measured START-to-last-BURST window was 89.48 ms \(\pm\) 4.69 ms across 127 trials, including the programmed 20 ms start delay before the first burst packet.
The entropy calculation credits WDEV bytes only. It relies on the RF-active source-state model from Section 4.4; SP 800-90B quantifies WDEV under that model without distinguishing a physical source from a well-seeded PRNG. For credit, we use the lower of 7.348 bits/B from this run and 7.198 bits/B from a larger 256 MB UDP burst benchmark. With 8192 WDEV bytes per trial, one 64 packet boot window contains about 59.0 kbit, or 7.20 KiB, of conservative raw-source min-entropy before extraction into a 256-bit seed. All WDEV windows had distinct hashes, and a 2000-pair sample had mean Hamming distance 49.998%, with range 49.271% to 50.722%. These are sanity checks; the entropy claim still comes from admitting the RF-active source state. Timing remains uncredited side material because the schedule and an attacker can influence it.
The compiled 1 MB source-separated WDEV stream from these trials passed all batteries, including TestU01 Rabbit.
| Metric | Value |
|---|---|
| Seeded boots | 10 / 10 |
| Time to first credited seed, median [range] | 9705 [5989, 14311] ms |
| Time to first credited seed | 9949.2 \(\pm\) 2911.6 ms |
| BOOT_HELLO-to-capsule exchange | 303.5 [9, 422] ms |
| BOOT_HELLO send call | 1535 [1375, 1541] μs |
| ML-DSA verification | 12877 [12872, 12887] μs |
| ML-KEM decapsulation | 5219 μs |
| HKDF-SHA256 | 608 [604, 608] μs |
| Combined client crypto | 18704 [18698, 18712] μs |
| Capsule size | 3252 |
| Heap peak after capsule | 48144 |
Table 2 gives the capsule benchmark. The ML-KEM-512 + ML-DSA-44 profile seeded 10/10 boots, and the server log records one served capsule for each successful boot. The full reset-to-seed number is useful
operationally, but it is not the right quantity to compare with the burst measurement window in Section 7.2. Once Wi-Fi and DHCP are complete, the median BOOT_HELLO-to-capsule exchange is
303.5 ms, and deterministic client work adds 18.704 ms median. The remaining seconds come from common boot and network setup, including the firmware’s fixed 1 s post-DHCP delay. The fallback is usable because the boot-starved client performs deterministic
work, and that work is not what makes the boot slow.
Our SRAM startup data remains preliminary. A linker-defined .noinit region lets the firmware read 4096 B before normal initialization clears memory. Five automated EN/RTS reset dumps of that region gave a global ones fraction of 49.86%, a
pairwise Hamming distance of 6.10% (range 6.00% to 6.22%), 28,663 stable bits (87.47%), and a 2059-bit sum of per-bit min-entropy.
These reset measurements show that the capture hook works and that the region contains structure worth analyzing. They are not cold-power evidence. EN/RTS resets do not fully discharge SRAM cells. We therefore treat SRAM as auxiliary material (\(P\)), not as a credited entropy root. A cold-start claim would need the usual PUF-style study across boards, power-off durations, and environments, with bias, stability, uniqueness, and min-entropy reported explicitly [9], [10].
The combined seed is only as strong as the credited physical source that remains unpredictable. The architecture provides a measurement path and a fail-safe policy, but it does not certify a source by construction. For radio burst extraction, the central assumption is that a full observer of the public burst cannot predict the node’s WDEV samples; that remains a platform-specific empirical claim.
The radio burst evidence is from one board. Deployment credit would require multi-board replication, larger source-separated datasets, and power-cycle restarts between burst trials. A co-located second receiver observing the same public packet train would also help measure what part of the response is truly local to the target.
The Rabbit flags across 256 MB ESP32 WDEV states remain unexplained. The 1 MB source-separated WDEV stream passes Rabbit, but the larger-run flags still argue for conditioning raw WDEV output. SRAM has only the reset-based check in Section 7.4. Because the current firmware samples WDEV at the application layer after packet delivery, low-level metrics like CSI, hardware timestamps, and thermal or current telemetry are currently inaccessible and left for future work. The capsule root requires enrollment and a trusted node.
The history of randomness failures argues against certifying any single root of boot entropy, especially on constrained wireless devices that boot deterministically on opaque silicon. We proposed a defense-in-depth boot path that combines device intrinsic startup state, radio burst extraction, and asymmetric entropy capsules under source-state admission. The combiner preserves the entropy of any credited root that remains unknown to the adversary under standard extractor assumptions.
The measurements support the stance more than any single source claim. A documented pseudorandom RNG state can be statistically indistinguishable from a true-entropy state, so gating must be enforced through firmware policy. Under the RF-active source-state model, identical public bursts produce distinct local responses; a 64-packet window contains about 59.0 kbit of conservative local raw-source min-entropy before extraction into a 256-bit seed. The capsule fallback costs a client with no credited entropy only deterministic work, dominated by the network stack. A seed remains secure unless the adversary can compromise or predict every credited root.
The radio burst firmware, collector, and supporting code are available in the wireless-boot-entropy-zephyr repository: https://github.com/perlab-uc3m/wireless-boot-entropy-zephyr. The workshop version used for this paper is archived as release v0.1.0: https://github.com/perlab-uc3m/wireless-boot-entropy-zephyr/releases/tag/v0.1.0.