medfall

A super great game engine
Log | Files | Refs

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 }