@@ -7,33 +7,46 @@ use hermit_sync::InterruptTicketMutex;
77use rand_chacha:: rand_core:: { RngCore , SeedableRng } ;
88use rand_chacha:: ChaCha20Rng ;
99
10- use crate :: arch:: kernel:: processor:: seed_entropy;
10+ use crate :: arch:: kernel:: processor:: { get_timer_ticks , seed_entropy} ;
1111use crate :: errno:: ENOSYS ;
1212
13+ // Reseed every second for increased security while maintaining the performance of
14+ // the PRNG.
15+ const RESEED_INTERVAL : u64 = 1000000 ;
16+
1317bitflags ! {
1418 pub struct Flags : u32 { }
1519}
1620
17- static POOL : InterruptTicketMutex < Option < ChaCha20Rng > > = InterruptTicketMutex :: new ( None ) ;
21+ struct Pool {
22+ rng : ChaCha20Rng ,
23+ last_reseed : u64 ,
24+ }
25+
26+ static POOL : InterruptTicketMutex < Option < Pool > > = InterruptTicketMutex :: new ( None ) ;
1827
1928/// Fills `buf` with random data, respecting the options in `flags`.
2029///
2130/// Returns the number of bytes written or `-ENOSYS` if the system does not support
2231/// random data generation.
2332pub fn read ( buf : & mut [ u8 ] , _flags : Flags ) -> isize {
2433 let pool = & mut * POOL . lock ( ) ;
34+ let now = get_timer_ticks ( ) ;
2535 let pool = match pool {
26- Some ( pool) => pool,
27- pool @ None => {
36+ Some ( pool) if now . saturating_sub ( pool . last_reseed ) <= RESEED_INTERVAL => pool,
37+ pool => {
2838 if let Some ( seed) = seed_entropy ( ) {
29- pool. insert ( ChaCha20Rng :: from_seed ( seed) )
39+ pool. insert ( Pool {
40+ rng : ChaCha20Rng :: from_seed ( seed) ,
41+ last_reseed : now,
42+ } )
3043 } else {
3144 return -ENOSYS as isize ;
3245 }
3346 }
3447 } ;
3548
36- pool. fill_bytes ( buf) ;
49+ pool. rng . fill_bytes ( buf) ;
3750 // Slice lengths are always <= isize::MAX so this return value cannot conflict
3851 // with error numbers.
3952 buf. len ( ) as isize
0 commit comments