medfall

A super great game engine
Log | Files | Refs

commit 516314b7eca2efdfbdb276e907c1bd245f2bfe3a
parent b93548485bcbf4444b0a33e19faa1b198e88ed4e
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sun, 18 Feb 2018 20:39:05 +0200

Add CSPRNG

Diffstat:
rng/csprng.cc | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rng/csprng.h | 6++++++
2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/rng/csprng.cc b/rng/csprng.cc @@ -0,0 +1,63 @@ +/* + * NOTE: this isn't fork safe! + */ + +#include "intrinsics.h" +#include "log.h" +#include "ggentropy.h" +#include "platform_mutex.h" +#include "platform_time.h" + +#include "libs/monocypher/monocypher.h" + +static Mutex mtx; +static crypto_chacha_ctx chacha; +static double time_of_last_stir; +static size_t bytes_since_stir; + +void csprng_init() { + u8 entropy[ 32 + 8 ]; + bool ok = ggentropy( entropy, sizeof( entropy ) ); + if( !ok ) + FATAL( "ggentropy" ); + + mutex_init( &mtx ); + + time_of_last_stir = get_time(); + bytes_since_stir = 0; + + crypto_chacha20_init( &chacha, entropy, entropy + 32 ); +} + +static void stir_if_necessary() { + // stir every 64k or 5 minutes + if( bytes_since_stir < kilobytes( 64 ) ) + return; + + double now = get_time(); + if( now - time_of_last_stir < 300 ) + return; + + u8 entropy[ 32 ]; + bool ok = ggentropy( entropy, sizeof( entropy ) ); + if( !ok ) + { + WARN( "ggentropy failed, not stirring" ); + return; + } + + u8 ciphertext[ 32 ]; + crypto_chacha20_encrypt( &chacha, ciphertext, entropy, sizeof( entropy ) ); + + time_of_last_stir = now; + bytes_since_stir = 0; +} + +void csprng( void * buf, size_t n ) { + SCOPED_MUTEX_LOCK( &mtx ); + + stir_if_necessary(); + bytes_since_stir += n; + + crypto_chacha20_stream( &chacha, ( u8 * ) buf, n ); +} diff --git a/rng/csprng.h b/rng/csprng.h @@ -0,0 +1,6 @@ +#pragma once + +#include <stddef.h> + +void csprng_init(); +void csprng( void * buf, size_t n );