csprng.cc (1244B)
1 /* 2 * NOTE: this isn't fork safe! 3 */ 4 5 #include "intrinsics.h" 6 #include "log.h" 7 #include "ggentropy.h" 8 #include "platform_mutex.h" 9 #include "platform_time.h" 10 11 #include "libs/monocypher/monocypher.h" 12 13 static Mutex mtx; 14 static crypto_chacha_ctx chacha; 15 static double time_of_last_stir; 16 static size_t bytes_since_stir; 17 18 void csprng_init() { 19 u8 entropy[ 32 + 8 ]; 20 bool ok = ggentropy( entropy, sizeof( entropy ) ); 21 if( !ok ) 22 FATAL( "ggentropy" ); 23 24 mutex_init( &mtx ); 25 26 time_of_last_stir = get_time(); 27 bytes_since_stir = 0; 28 29 crypto_chacha20_init( &chacha, entropy, entropy + 32 ); 30 } 31 32 static void stir_if_necessary() { 33 // stir every 64k or 5 minutes 34 if( bytes_since_stir < kilobytes( 64 ) ) 35 return; 36 37 double now = get_time(); 38 if( now - time_of_last_stir < 300 ) 39 return; 40 41 u8 entropy[ 32 ]; 42 bool ok = ggentropy( entropy, sizeof( entropy ) ); 43 if( !ok ) { 44 WARN( "ggentropy failed, not stirring" ); 45 return; 46 } 47 48 u8 ciphertext[ 32 ]; 49 crypto_chacha20_encrypt( &chacha, ciphertext, entropy, sizeof( entropy ) ); 50 51 time_of_last_stir = now; 52 bytes_since_stir = 0; 53 } 54 55 void csprng( void * buf, size_t n ) { 56 SCOPED_MUTEX_LOCK( &mtx ); 57 58 stir_if_necessary(); 59 bytes_since_stir += n; 60 61 crypto_chacha20_stream( &chacha, ( u8 * ) buf, n ); 62 }