From 887993e8b30624c9d268ae5028ff4c328012458d Mon Sep 17 00:00:00 2001 From: Simon Wilkinson Date: Fri, 16 Apr 2010 12:04:15 +0100 Subject: [PATCH] Add mutex protection for the fortuna PRNG The fortuna PRNG has an statically held internal state. Prevent concurrent access to this internal state by adding mutexes around all of the access classes. Signed-off-by: Love Hornquist Astrand --- lib/hcrypto/rand-fortuna.c | 44 +++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/hcrypto/rand-fortuna.c b/lib/hcrypto/rand-fortuna.c index c81eb9e2d..11027b46c 100644 --- a/lib/hcrypto/rand-fortuna.c +++ b/lib/hcrypto/rand-fortuna.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef KRB5 #include @@ -441,11 +442,21 @@ static int have_entropy; #define FORTUNA_RESEED_BYTE 10000 static unsigned resend_bytes; +/* + * This mutex protects all of the above static elements from concurrent + * access by multiple threads + */ +static HEIMDAL_MUTEX fortuna_mutex = HEIMDAL_MUTEX_INITIALIZER; + /* * Try our best to do an inital seed */ #define INIT_BYTES 128 +/* + * fortuna_mutex must be held across calls to this function + */ + static int fortuna_reseed(void) { @@ -537,6 +548,9 @@ fortuna_reseed(void) return entropy_p; } +/* + * fortuna_mutex must be held by callers of this function + */ static int fortuna_init(void) { @@ -555,32 +569,50 @@ fortuna_init(void) static void fortuna_seed(const void *indata, int size) { + HEIMDAL_MUTEX_lock(&fortuna_mutex); + fortuna_init(); add_entropy(&main_state, indata, size); if (size >= INIT_BYTES) have_entropy = 1; + + HEIMDAL_MUTEX_unlock(&fortuna_mutex); } static int fortuna_bytes(unsigned char *outdata, int size) { + int ret = 0; + + HEIMDAL_MUTEX_lock(&fortuna_mutex); + if (!fortuna_init()) - return 0; + goto out; + resend_bytes += size; if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) { resend_bytes = 0; fortuna_reseed(); } extract_data(&main_state, size, outdata); - return 1; + ret = 1; + +out: + HEIMDAL_MUTEX_unlock(&fortuna_mutex); + + return ret; } static void fortuna_cleanup(void) { + HEIMDAL_MUTEX_lock(&fortuna_mutex); + init_done = 0; have_entropy = 0; memset(&main_state, 0, sizeof(main_state)); + + HEIMDAL_MUTEX_unlock(&fortuna_mutex); } static void @@ -598,7 +630,13 @@ fortuna_pseudorand(unsigned char *outdata, int size) static int fortuna_status(void) { - return fortuna_init() ? 1 : 0; + int result; + + HEIMDAL_MUTEX_lock(&fortuna_mutex); + result = fortuna_init(); + HEIMDAL_MUTEX_unlock(&fortuna_mutex); + + return result ? 1 : 0; } const RAND_METHOD hc_rand_fortuna_method = {