commit 516314b7eca2efdfbdb276e907c1bd245f2bfe3a
parent b93548485bcbf4444b0a33e19faa1b198e88ed4e
Author: Michael Savage <mikejsavage@gmail.com>
Date: Sun, 18 Feb 2018 20:39:05 +0200
Add CSPRNG
Diffstat:
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 );