@@ -87,14 +87,31 @@ async fn main(spawner: Spawner) -> ! {
8787 cfg_if:: cfg_if! {
8888 if #[ cfg( any( feature = "esp32c5" , feature = "esp32c61" ) ) ] {
8989 // ESP32-C5/C61 have no TRNG peripheral — use the basic Rng directly.
90+ // Until the TODO above is resolved, key material on these chips is
91+ // only as good as the bare RNG register, so say so out loud.
92+ warn!( "No TRNG on this chip: RNG is not cryptographically secure until the radio is up" ) ;
9093 let rng = esp_hal:: rng:: Rng :: new( ) ;
9194 register_custom_rng( rng) ;
9295 } else {
93- let trng_source = TrngSource :: new( peripherals. RNG , peripherals. ADC1 ) ;
94- let trng = Trng :: try_new( ) . unwrap( ) ;
96+ // The TrngSource must outlive every consumer of randomness, not
97+ // just this block. `Trng::downgrade` hands back `Rng`, a
98+ // zero-sized handle that simply reads the RNG register, and
99+ // dropping the TrngSource calls `revert_trng()` which switches the
100+ // ADC entropy source back off. Anything drawn afterwards is no
101+ // longer cryptographically secure.
102+ //
103+ // That matters because none of the key material is generated here:
104+ // the SSH host key, WiFi SSID/PSK and MAC are all minted further
105+ // down in `store::load_or_create`, and sunset draws fresh session
106+ // and key-exchange material for every connection later still.
107+ //
108+ // `main` never returns, so binding it here keeps the entropy
109+ // source enabled for the lifetime of the program.
110+ let _trng_source = TrngSource :: new( peripherals. RNG , peripherals. ADC1 ) ;
111+ let trng = Trng :: try_new( )
112+ . expect( "TrngSource was just created, so the TRNG must be available" ) ;
95113 let rng = trng. downgrade( ) ;
96114 register_custom_rng( rng) ;
97- drop( trng_source) ;
98115 }
99116 }
100117
@@ -125,6 +142,18 @@ async fn main(spawner: Spawner) -> ! {
125142 tx : tx_num,
126143 } ;
127144
145+ // On first boot this mints the SSH host key and the WiFi PSK, so the
146+ // entropy source enabled above has to still be running. Guard the
147+ // invariant rather than trusting a comment: `debug-assertions` are on
148+ // even in release for this workspace, so reintroducing an early drop of
149+ // the `TrngSource` fails loudly on the bench instead of silently
150+ // producing predictable keys.
151+ #[ cfg( not( any( feature = "esp32c5" , feature = "esp32c61" ) ) ) ]
152+ debug_assert ! (
153+ TrngSource :: is_enabled( ) ,
154+ "entropy source was disabled before host key generation"
155+ ) ;
156+
128157 debug ! ( "Loading config" ) ;
129158 let flash_config = {
130159 let Some ( flash_storage_guard) = flash:: get_flash_n_buffer ( ) else {
0 commit comments