From: Nikos Mavrogiannopoulos Date: Sun, 4 Jul 2010 07:45:34 +0000 (+0200) Subject: Added a windows version of the RNG. X-Git-Tag: gnutls_2_11_3~112 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4ef54a780d581dabafcca1b42e3d413ead491184;p=thirdparty%2Fgnutls.git Added a windows version of the RNG. --- diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c index 84ef1a8c7d..c4a0057d17 100644 --- a/lib/nettle/rnd.c +++ b/lib/nettle/rnd.c @@ -29,18 +29,9 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #define SOURCES 2 -static void* rnd_mutex; - #define RND_LOCK if (gnutls_mutex_lock(&rnd_mutex)!=0) abort() #define RND_UNLOCK if (gnutls_mutex_unlock(&rnd_mutex)!=0) abort() @@ -52,10 +43,99 @@ enum { static struct yarrow256_ctx yctx; static struct yarrow_source ysources[SOURCES]; static time_t device_last_read = 0; -static int device_fd; +static time_t trivia_time_count = 0; + +static void* rnd_mutex; + +#define DEVICE_READ_SIZE 16 +#define DEVICE_READ_SIZE_MAX 32 +#define DEVICE_READ_INTERVAL 1200 + +#ifdef _WIN32 + +# include + +static HCRYPTPROV device_fd = NULL; + +static int do_trivia_source(int init) +{ + struct { + FILETIME now; + unsigned count; + } event; + + unsigned entropy = 0; + + GetSystemTimeAsFileTime(&event.now); + event.count = 0; + + if (init) { + trivia_time_count = 0; + } else { + event.count = trivia_time_count++; + entropy = 1; + } + + return yarrow256_update(&yctx, RANDOM_SOURCE_TRIVIA, entropy, + sizeof(event), (const uint8_t *) &event); +} +static int do_device_source(int init) +{ + time_t now = time(NULL); + int read_size = DEVICE_READ_SIZE; + + if (init) { + int old; + + if(!CryptAcquireContext(&device_fd, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT|CRYPT_VERIFYCONTEXT)) { + _gnutls_debug_log("error in CryptAcquireContext!\n"); + return GNUTLS_E_INTERNAL_ERROR; + } + device_last_read = now; + read_size = DEVICE_READ_SIZE_MAX; /* initially read more data */ + } + + if ((device_fd != NULL) + && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL))) { + + /* More than a minute since we last read the device */ + uint8_t buf[DEVICE_READ_SIZE_MAX]; + + if(!CryptGenRandom(device_fd, (DWORD)read_size, buf)) { + _gnutls_debug_log("Error in CryptGenRandom: %s\n", GetLastError()); + return GNUTLS_E_INTERNAL_ERROR; + } + + device_last_read = now; + return yarrow256_update(&yctx, RANDOM_SOURCE_DEVICE, read_size*8/2 /* we trust the system RNG */, + read_size, buf); + } + return 0; +} + +static void wrap_nettle_rnd_deinit(void* ctx) +{ + RND_LOCK; + CryptReleaseContext(device_fd, 0); + RND_UNLOCK; + + gnutls_mutex_deinit(&rnd_mutex); + rnd_mutex = NULL; +} + +#else /* POSIX */ + +# include +# include +# include +# include +# include +# include +# include + +static int device_fd; static time_t trivia_previous_time = 0; -static time_t trivia_time_count = 0; static int do_trivia_source(int init) { @@ -105,9 +185,6 @@ static int do_trivia_source(int init) sizeof(event), (const uint8_t *) &event); } -#define DEVICE_READ_SIZE 16 -#define DEVICE_READ_SIZE_MAX 32 -#define DEVICE_READ_INTERVAL 1200 static int do_device_source(int init) { time_t now = time(NULL); @@ -119,7 +196,7 @@ static int do_device_source(int init) device_fd = open("/dev/urandom", O_RDONLY); if (device_fd < 0) { _gnutls_debug_log("Cannot open urandom!\n"); - abort(); + return GNUTLS_E_FILE_ERROR; } old = fcntl(device_fd, F_GETFD); @@ -152,14 +229,14 @@ static int do_device_source(int init) ("Failed to read /dev/urandom: end of file\n"); } - return 0; + return GNUTLS_E_INTERNAL_ERROR; } done += res; } device_last_read = now; - return yarrow256_update(&yctx, RANDOM_SOURCE_DEVICE, read_size*8/3 /* be more conservative */, + return yarrow256_update(&yctx, RANDOM_SOURCE_DEVICE, read_size*8/2 /* we trust the RNG */, read_size, buf); } return 0; @@ -175,6 +252,9 @@ static void wrap_nettle_rnd_deinit(void* ctx) rnd_mutex = NULL; } +#endif + + static int wrap_nettle_rnd_init(void **ctx) { int ret; @@ -187,8 +267,18 @@ int ret; } yarrow256_init(&yctx, SOURCES, ysources); - do_device_source(1); - do_trivia_source(1); + + ret = do_device_source(1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = do_trivia_source(1); + if (ret < 0) { + gnutls_assert(); + return ret; + } yarrow256_slow_reseed(&yctx); @@ -200,9 +290,21 @@ int ret; static int wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize) { +int ret; + RND_LOCK; - do_trivia_source( 0); - do_device_source( 0); + + ret = do_trivia_source( 0); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = do_device_source( 0); + if (ret < 0) { + gnutls_assert(); + return ret; + } yarrow256_random(&yctx, datasize, data); RND_UNLOCK;