diff options
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/random')
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rand-internal.h | 33 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/random-csprng.c | 1048 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/random-daemon.c | 34 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/random-fips.c | 175 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/random-system.c | 256 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/random.c | 292 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/random.h | 13 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rndegd.c | 22 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rndhw.c | 99 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rndlinux.c | 182 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rndunix.c | 62 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rndw32.c | 166 | ||||
-rw-r--r-- | plugins/MirOTR/Libgcrypt/random/rndw32ce.c | 199 |
13 files changed, 1711 insertions, 870 deletions
diff --git a/plugins/MirOTR/Libgcrypt/random/rand-internal.h b/plugins/MirOTR/Libgcrypt/random/rand-internal.h index 534d8284e5..79b23acefe 100644 --- a/plugins/MirOTR/Libgcrypt/random/rand-internal.h +++ b/plugins/MirOTR/Libgcrypt/random/rand-internal.h @@ -24,7 +24,7 @@ /* Constants used to define the origin of random added to the pool. The code is sensitive to the order of the values. */ -enum random_origins +enum random_origins { RANDOM_ORIGIN_INIT = 0, /* Used only for initialization. */ RANDOM_ORIGIN_EXTERNAL = 1, /* Added from an external source. */ @@ -44,6 +44,7 @@ void _gcry_random_progress (const char *what, int printchar, /*-- random-csprng.c --*/ void _gcry_rngcsprng_initialize (int full); +void _gcry_rngcsprng_close_fds (void); void _gcry_rngcsprng_dump_stats (void); void _gcry_rngcsprng_secure_alloc (void); void _gcry_rngcsprng_enable_quick_gen (void); @@ -54,25 +55,21 @@ gcry_error_t _gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality); void *_gcry_rngcsprng_get_bytes (size_t nbytes, enum gcry_random_level level); -void *_gcry_rngcsprng_get_bytes_secure (size_t nbytes, +void *_gcry_rngcsprng_get_bytes_secure (size_t nbytes, enum gcry_random_level level); void _gcry_rngcsprng_randomize (void *buffer, size_t length, enum gcry_random_level level); void _gcry_rngcsprng_set_seed_file (const char *name); void _gcry_rngcsprng_update_seed_file (void); void _gcry_rngcsprng_fast_poll (void); -void _gcry_rngcsprng_create_nonce (void *buffer, size_t length); -/*-- random-rngcsprng.c --*/ +/*-- random-fips.c --*/ void _gcry_rngfips_initialize (int full); +void _gcry_rngfips_close_fds (void); void _gcry_rngfips_dump_stats (void); int _gcry_rngfips_is_faked (void); gcry_error_t _gcry_rngfips_add_bytes (const void *buf, size_t buflen, int quality); -void *_gcry_rngfips_get_bytes (size_t nbytes, - enum gcry_random_level level); -void *_gcry_rngfips_get_bytes_secure (size_t nbytes, - enum gcry_random_level level); void _gcry_rngfips_randomize (void *buffer, size_t length, enum gcry_random_level level); void _gcry_rngfips_create_nonce (void *buffer, size_t length); @@ -92,6 +89,15 @@ gcry_err_code_t _gcry_rngfips_run_external_test (void *context, void _gcry_rngfips_deinit_external_test (void *context); +/*-- random-system.c --*/ +void _gcry_rngsystem_initialize (int full); +void _gcry_rngsystem_close_fds (void); +void _gcry_rngsystem_dump_stats (void); +int _gcry_rngsystem_is_faked (void); +gcry_error_t _gcry_rngsystem_add_bytes (const void *buf, size_t buflen, + int quality); +void _gcry_rngsystem_randomize (void *buffer, size_t length, + enum gcry_random_level level); @@ -119,10 +125,19 @@ int _gcry_rndw32_gather_random (void (*add) (const void *, size_t, enum random_origins), enum random_origins origin, size_t length, int level); -void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, +void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, enum random_origins), enum random_origins origin ); +/*-- rndw32ce.c --*/ +int _gcry_rndw32ce_gather_random (void (*add) (const void *, size_t, + enum random_origins), + enum random_origins origin, + size_t length, int level); +void _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t, + enum random_origins), + enum random_origins origin ); + /*-- rndhw.c --*/ int _gcry_rndhw_failed_p (void); void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t, diff --git a/plugins/MirOTR/Libgcrypt/random/random-csprng.c b/plugins/MirOTR/Libgcrypt/random/random-csprng.c index ccb90ee863..87235d82d4 100644 --- a/plugins/MirOTR/Libgcrypt/random/random-csprng.c +++ b/plugins/MirOTR/Libgcrypt/random/random-csprng.c @@ -1,6 +1,6 @@ /* random-csprng.c - CSPRNG style random number generator (libgcrypt classic) * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008 Free Software Foundation, Inc. + * 2007, 2008, 2010, 2012 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -101,11 +101,11 @@ up. Its allocated size is POOLSIZE+BLOCKLEN. Note that this is also an indication on whether the module has been fully initialized. */ -static unsigned char *rndpool; +static unsigned char *rndpool; /* KEYPOOL is used as a scratch copy to read out random from RNDPOOL. Its allocated size is also POOLSIZE+BLOCKLEN. */ -static unsigned char *keypool; +static unsigned char *keypool; /* This is the offset into RNDPOOL where the next random bytes are to be mixed in. */ @@ -137,7 +137,7 @@ static int pool_balance; /* After a mixing operation this variable will be set to true and cleared if new entropy has been added or a remix is required for - otehr reasons. */ + other reasons. */ static int just_mixed; /* The name of the seed file or NULL if no seed file has been defined. @@ -154,19 +154,19 @@ static int allow_seed_file_update; static int secure_alloc; /* This function pointer is set to the actual entropy gathering - function during initailization. After initialization it is + function during initialization. After initialization it is guaranteed to point to function. (On systems without a random gatherer module a dummy function is used).*/ static int (*slow_gather_fnc)(void (*)(const void*, size_t, - enum random_origins), - enum random_origins, size_t, int); + enum random_origins), + enum random_origins, size_t, int); -/* This function is set to the actual fast entropy gathering fucntion +/* This function is set to the actual fast entropy gathering function during initialization. If it is NULL, no such function is available. */ static void (*fast_gather_fnc)(void (*)(const void*, size_t, - enum random_origins), - enum random_origins); + enum random_origins), + enum random_origins); /* Option flag useful for debugging and the test suite. If set @@ -181,7 +181,7 @@ static int quick_test; static int faked_rng; /* This is the lock we use to protect all pool operations. */ -static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER; +static ath_mutex_t pool_lock; /* This is a helper for assert calls. These calls are used to assert that functions are called in a locked state. It is not meant to be @@ -189,10 +189,6 @@ static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER; test suite. */ static int pool_is_locked; -/* This is the lock we use to protect the buffer used by the nonce - generation. */ -static ath_mutex_t nonce_buffer_lock = ATH_MUTEX_INITIALIZER; - /* We keep some counters in this structure for the sake of the _gcry_random_dump_stats () function. */ @@ -221,7 +217,7 @@ static struct test this flag in a locked state because a wrong value does not harm and the trhead will find out itself that the daemon does not work and set it (again) to false. */ -static int allow_daemon; +static int allow_daemon; /* During initialization, the user may set a non-default socket name for accessing the random daemon. If this value is NULL, the @@ -234,23 +230,23 @@ static char *daemon_socket_name; /* --- Prototypes --- */ static void read_pool (byte *buffer, size_t length, int level ); -static void add_randomness (const void *buffer, size_t length, - enum random_origins origin); +static void add_randomness (const void *buffer, size_t length, + enum random_origins origin); static void random_poll (void); static void do_fast_random_poll (void); -static int (*getfnc_gather_random (void))(void (*)(const void*, size_t, - enum random_origins), - enum random_origins, size_t, int); +static int (*getfnc_gather_random (void))(void (*)(const void*, size_t, + enum random_origins), + enum random_origins, size_t, int); static void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t, - enum random_origins), - enum random_origins); + enum random_origins), + enum random_origins); static void read_random_source (enum random_origins origin, - size_t length, int level); + size_t length, int level); static int gather_faked (void (*add)(const void*, size_t, enum random_origins), - enum random_origins, size_t length, int level ); + enum random_origins, size_t length, int level ); - + /* --- Functions --- */ @@ -266,38 +262,33 @@ initialize_basics(void) int err; if (!initialized) - { - initialized = 1; - err = ath_mutex_init (&pool_lock); - if (err) - log_fatal ("failed to create the pool lock: %s\n", strerror (err) ); - - err = ath_mutex_init (&nonce_buffer_lock); - if (err) - log_fatal ("failed to create the nonce buffer lock: %s\n", - strerror (err) ); + { + initialized = 1; + err = ath_mutex_init (&pool_lock); + if (err) + log_fatal ("failed to create the pool lock: %s\n", strerror (err) ); #ifdef USE_RANDOM_DAEMON - _gcry_daemon_initialize_basics (); + _gcry_daemon_initialize_basics (); #endif /*USE_RANDOM_DAEMON*/ - /* Make sure that we are still using the values we have - traditionally used for the random levels. */ - gcry_assert (GCRY_WEAK_RANDOM == 0 - && GCRY_STRONG_RANDOM == 1 - && GCRY_VERY_STRONG_RANDOM == 2); - } + /* Make sure that we are still using the values we have + traditionally used for the random levels. */ + gcry_assert (GCRY_WEAK_RANDOM == 0 + && GCRY_STRONG_RANDOM == 1 + && GCRY_VERY_STRONG_RANDOM == 2); + } } /* Take the pool lock. */ static void lock_pool (void) { - int err; + int err; err = ath_mutex_lock (&pool_lock); if (err) - log_fatal ("failed to acquire the pool lock: %s\n", strerror (err)); + log_fatal ("failed to acquire the pool lock: %s\n", strerror (err)); pool_is_locked = 1; } @@ -305,12 +296,12 @@ lock_pool (void) static void unlock_pool (void) { - int err; + int err; pool_is_locked = 0; err = ath_mutex_unlock (&pool_lock); if (err) - log_fatal ("failed to release the pool lock: %s\n", strerror (err)); + log_fatal ("failed to release the pool lock: %s\n", strerror (err)); } @@ -319,37 +310,37 @@ static void initialize(void) { /* Although the basic initialization should have happened already, - we call it here to make sure that all prerequisites are met. */ + we call it here to make sure that all prerequisites are met. */ initialize_basics (); /* Now we can look the pool and complete the initialization if - necessary. */ + necessary. */ lock_pool (); if (!rndpool) - { - /* The data buffer is allocated somewhat larger, so that we can - use this extra space (which is allocated in secure memory) as - a temporary hash buffer */ - rndpool = (secure_alloc - ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN) - : gcry_xcalloc (1, POOLSIZE + BLOCKLEN)); - keypool = (secure_alloc - ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN) - : gcry_xcalloc (1, POOLSIZE + BLOCKLEN)); - - /* Setup the slow entropy gathering function. The code requires - that this function exists. */ - slow_gather_fnc = getfnc_gather_random (); - if (!slow_gather_fnc) - { - faked_rng = 1; - slow_gather_fnc = gather_faked; + { + /* The data buffer is allocated somewhat larger, so that we can + use this extra space (which is allocated in secure memory) as + a temporary hash buffer */ + rndpool = (secure_alloc + ? xcalloc_secure (1, POOLSIZE + BLOCKLEN) + : xcalloc (1, POOLSIZE + BLOCKLEN)); + keypool = (secure_alloc + ? xcalloc_secure (1, POOLSIZE + BLOCKLEN) + : xcalloc (1, POOLSIZE + BLOCKLEN)); + + /* Setup the slow entropy gathering function. The code requires + that this function exists. */ + slow_gather_fnc = getfnc_gather_random (); + if (!slow_gather_fnc) + { + faked_rng = 1; + slow_gather_fnc = gather_faked; } - - /* Setup the fast entropy gathering function. */ - fast_gather_fnc = getfnc_fast_random_poll (); - } + /* Setup the fast entropy gathering function. */ + fast_gather_fnc = getfnc_fast_random_poll (); + + } unlock_pool (); } @@ -364,9 +355,23 @@ void _gcry_rngcsprng_initialize (int full) { if (!full) - initialize_basics (); + initialize_basics (); else - initialize (); + initialize (); +} + + +/* Try to close the FDs of the random gather module. This is + currently only implemented for rndlinux. */ +void +_gcry_rngcsprng_close_fds (void) +{ + lock_pool (); +#if USE_RNDLINUX + _gcry_rndlinux_gather_random (NULL, 0, 0, 0); + pool_filled = 0; /* Force re-open on next use. */ +#endif + unlock_pool (); } @@ -374,21 +379,21 @@ void _gcry_rngcsprng_dump_stats (void) { /* In theory we would need to lock the stats here. However this - function is usually called during cleanup and then we _might_ run - into problems. */ + function is usually called during cleanup and then we _might_ run + into problems. */ log_info ("random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" - " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n", - POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, - rndstats.naddbytes, rndstats.addbytes, - rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, - rndstats.ngetbytes2, rndstats.getbytes2, - _gcry_rndhw_failed_p()? " (hwrng failed)":""); + " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n", + POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, + rndstats.naddbytes, rndstats.addbytes, + rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, + rndstats.ngetbytes2, rndstats.getbytes2, + _gcry_rndhw_failed_p()? " (hwrng failed)":""); } /* This function should be called during initialization and before - intialization of this module to place the random pools into secure + initialization of this module to place the random pools into secure memory. */ void _gcry_rngcsprng_secure_alloc (void) @@ -411,7 +416,7 @@ _gcry_rngcsprng_set_daemon_socket (const char *socketname) { #ifdef USE_RANDOM_DAEMON if (daemon_socket_name) - BUG (); + BUG (); daemon_socket_name = gcry_xstrdup (socketname); #else /*!USE_RANDOM_DAEMON*/ @@ -427,15 +432,15 @@ _gcry_rngcsprng_use_daemon (int onoff) { #ifdef USE_RANDOM_DAEMON int last; - + /* This is not really thread safe. However it is expected that this - function is being called during initialization and at that point - we are for other reasons not really thread safe. We do not want - to lock it because we might eventually decide that this function - may even be called prior to gcry_check_version. */ + function is being called during initialization and at that point + we are for other reasons not really thread safe. We do not want + to lock it because we might eventually decide that this function + may even be called prior to gcry_check_version. */ last = allow_daemon; if (onoff != -1) - allow_daemon = onoff; + allow_daemon = onoff; return last; #else /*!USE_RANDOM_DAEMON*/ @@ -451,7 +456,7 @@ int _gcry_rngcsprng_is_faked (void) { /* We need to initialize due to the runtime determination of - available entropy gather modules. */ + available entropy gather modules. */ initialize(); return (faked_rng || quick_test); } @@ -467,38 +472,38 @@ _gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality) const char *bufptr; if (quality == -1) - quality = 35; + quality = 35; else if (quality > 100) - quality = 100; + quality = 100; else if (quality < 0) - quality = 0; - + quality = 0; + if (!buf) - return gpg_error (GPG_ERR_INV_ARG); + return gpg_error (GPG_ERR_INV_ARG); if (!buflen || quality < 10) - return 0; /* Take a shortcut. */ + return 0; /* Take a shortcut. */ /* Because we don't increment the entropy estimation with FASTPOLL, - we don't need to take lock that estimation while adding from an - external source. This limited entropy estimation also means that - we can't take QUALITY into account. */ + we don't need to take lock that estimation while adding from an + external source. This limited entropy estimation also means that + we can't take QUALITY into account. */ initialize_basics (); bufptr = buf; while (buflen) - { - nbytes = buflen > POOLSIZE? POOLSIZE : buflen; - lock_pool (); - if (rndpool) - add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL); - unlock_pool (); - bufptr += nbytes; - buflen -= nbytes; - } + { + nbytes = buflen > POOLSIZE? POOLSIZE : buflen; + lock_pool (); + if (rndpool) + add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL); + unlock_pool (); + bufptr += nbytes; + buflen -= nbytes; + } return 0; -} +} + - /* Public function to fill the buffer with LENGTH bytes of cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is not very strong, GCRY_STRONG_RANDOM is strong enough for most @@ -506,7 +511,7 @@ _gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality) may be very slow. */ void _gcry_rngcsprng_randomize (void *buffer, size_t length, - enum gcry_random_level level) + enum gcry_random_level level) { unsigned char *p; @@ -515,15 +520,15 @@ _gcry_rngcsprng_randomize (void *buffer, size_t length, /* Handle our hack used for regression tests of Libgcrypt. */ if ( quick_test && level > GCRY_STRONG_RANDOM ) - level = GCRY_STRONG_RANDOM; + level = GCRY_STRONG_RANDOM; /* Make sure the level is okay. */ level &= 3; #ifdef USE_RANDOM_DAEMON if (allow_daemon - && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level)) - return; /* The daemon succeeded. */ + && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level)) + return; /* The daemon succeeded. */ allow_daemon = 0; /* Daemon failed - switch off. */ #endif /*USE_RANDOM_DAEMON*/ @@ -532,26 +537,26 @@ _gcry_rngcsprng_randomize (void *buffer, size_t length, /* Update the statistics. */ if (level >= GCRY_VERY_STRONG_RANDOM) - { - rndstats.getbytes2 += length; - rndstats.ngetbytes2++; - } + { + rndstats.getbytes2 += length; + rndstats.ngetbytes2++; + } else - { - rndstats.getbytes1 += length; - rndstats.ngetbytes1++; - } + { + rndstats.getbytes1 += length; + rndstats.ngetbytes1++; + } /* Read the random into the provided buffer. */ for (p = buffer; length > 0;) - { - size_t n; + { + size_t n; - n = length > POOLSIZE? POOLSIZE : length; - read_pool (p, n, level); - length -= n; - p += n; - } + n = length > POOLSIZE? POOLSIZE : length; + read_pool (p, n, level); + length -= n; + p += n; + } /* Release the pool lock. */ unlock_pool (); @@ -564,33 +569,33 @@ _gcry_rngcsprng_randomize (void *buffer, size_t length, Mix the pool: |........blocks*20byte........|20byte|..44byte..| - <..44byte..> <20byte> - | | - | +------+ - +---------------------------|----------+ - v v + <..44byte..> <20byte> + | | + | +------+ + +---------------------------|----------+ + v v |........blocks*20byte........|20byte|..44byte..| - <.....64bytes.....> - | - +----------------------------------+ - Hash - v + <.....64bytes.....> + | + +----------------------------------+ + Hash + v |.............................|20byte|..44byte..| <20byte><20byte><..44byte..> - | | - | +---------------------+ - +-----------------------------+ | - v v + | | + | +---------------------+ + +-----------------------------+ | + v v |.............................|20byte|..44byte..| - <.....64byte......> - | - +-------------------------+ - Hash - v + <.....64byte......> + | + +-------------------------+ + Hash + v |.............................|20byte|..44byte..| <20byte><20byte><..44byte..> - and so on until we did this for all blocks. + and so on until we did this for all blocks. To better protect against implementation errors in this code, we xor a digest of the entire pool into the pool before mixing. @@ -623,46 +628,46 @@ mix_pool(unsigned char *pool) memcpy(pool, hashbuf, 20 ); if (failsafe_digest_valid && pool == rndpool) - { - for (i=0; i < 20; i++) - pool[i] ^= failsafe_digest[i]; - } - + { + for (i=0; i < 20; i++) + pool[i] ^= failsafe_digest[i]; + } + p = pool; for (n=1; n < POOLBLOCKS; n++) - { - memcpy (hashbuf, p, DIGESTLEN); - - p += DIGESTLEN; - if (p+DIGESTLEN+BLOCKLEN < pend) - memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); - else - { - unsigned char *pp = p + DIGESTLEN; - - for (i=DIGESTLEN; i < BLOCKLEN; i++ ) - { - if ( pp >= pend ) - pp = pool; - hashbuf[i] = *pp++; - } - } - - _gcry_rmd160_mixblock ( &md, hashbuf); - memcpy(p, hashbuf, 20 ); + { + memcpy (hashbuf, p, DIGESTLEN); + + p += DIGESTLEN; + if (p+DIGESTLEN+BLOCKLEN < pend) + memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); + else + { + unsigned char *pp = p + DIGESTLEN; + + for (i=DIGESTLEN; i < BLOCKLEN; i++ ) + { + if ( pp >= pend ) + pp = pool; + hashbuf[i] = *pp++; + } } - /* Our hash implementation does only leave small parts (64 bytes) - of the pool on the stack, so it is okay not to require secure - memory here. Before we use this pool, it will be copied to the - help buffer anyway. */ - if ( pool == rndpool) - { - _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE); - failsafe_digest_valid = 1; - } - - _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */ + _gcry_rmd160_mixblock ( &md, hashbuf); + memcpy(p, hashbuf, 20 ); + } + + /* Our hash implementation does only leave small parts (64 bytes) + of the pool on the stack, so it is okay not to require secure + memory here. Before we use this pool, it will be copied to the + help buffer anyway. */ + if ( pool == rndpool) + { + _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE); + failsafe_digest_valid = 1; + } + + _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */ } @@ -670,8 +675,8 @@ void _gcry_rngcsprng_set_seed_file (const char *name) { if (seed_file_name) - BUG (); - seed_file_name = gcry_xstrdup (name); + BUG (); + seed_file_name = xstrdup (name); } @@ -682,6 +687,9 @@ _gcry_rngcsprng_set_seed_file (const char *name) static int lock_seed_file (int fd, const char *fname, int for_write) { +#ifdef __GCC__ +#warning Check whether we can lock on Windows. +#endif #if LOCK_SEED_FILE struct flock lck; struct timeval tv; @@ -693,23 +701,23 @@ lock_seed_file (int fd, const char *fname, int for_write) lck.l_whence = SEEK_SET; while (fcntl (fd, F_SETLK, &lck) == -1) - { - if (errno != EAGAIN && errno != EACCES) - { - log_info (_("can't lock `%s': %s\n"), fname, strerror (errno)); - return -1; - } - - if (backoff > 2) /* Show the first message after ~2.25 seconds. */ - log_info( _("waiting for lock on `%s'...\n"), fname); - - tv.tv_sec = backoff; - tv.tv_usec = 250000; - select (0, NULL, NULL, NULL, &tv); - if (backoff < 10) - backoff++ ; - } -#endif /*LOCK_SEED_FILE*/ + { + if (errno != EAGAIN && errno != EACCES) + { + log_info (_("can't lock `%s': %s\n"), fname, strerror (errno)); + return -1; + } + + if (backoff > 2) /* Show the first message after ~2.25 seconds. */ + log_info( _("waiting for lock on `%s'...\n"), fname); + + tv.tv_sec = backoff; + tv.tv_usec = 250000; + select (0, NULL, NULL, NULL, &tv); + if (backoff < 10) + backoff++ ; + } +#endif /*!LOCK_SEED_FILE*/ return 0; } @@ -727,7 +735,7 @@ lock_seed_file (int fd, const char *fname, int for_write) correlated to some extent. In the perfect scenario, the attacker can control (or at least guess) the PID and clock of the application, and drain the system's entropy pool to reduce the "up - to 16 bytes" above to 0. Then the dependencies of the inital + to 16 bytes" above to 0. Then the dependencies of the initial states of the pools are completely known. */ static int read_seed_file (void) @@ -740,83 +748,83 @@ read_seed_file (void) gcry_assert (pool_is_locked); if (!seed_file_name) - return 0; - + return 0; + #ifdef HAVE_DOSISH_SYSTEM - fd = _open( seed_file_name, O_RDONLY | O_BINARY ); + fd = open( seed_file_name, O_RDONLY | O_BINARY ); #else - fd = _open( seed_file_name, O_RDONLY ); + fd = open( seed_file_name, O_RDONLY ); #endif if( fd == -1 && errno == ENOENT) - { - allow_seed_file_update = 1; - return 0; - } + { + allow_seed_file_update = 1; + return 0; + } if (fd == -1 ) - { - log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); - return 0; - } + { + log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); + return 0; + } if (lock_seed_file (fd, seed_file_name, 0)) - { - _close (fd); - return 0; - } + { + close (fd); + return 0; + } if (fstat( fd, &sb ) ) - { - log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); - _close(fd); - return 0; - } + { + log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); + close(fd); + return 0; + } if (!S_ISREG(sb.st_mode) ) - { - log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); - _close(fd); - return 0; - } + { + log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); + close(fd); + return 0; + } if (!sb.st_size ) - { - log_info(_("note: random_seed file is empty\n") ); - _close(fd); - allow_seed_file_update = 1; - return 0; - } - if (sb.st_size != POOLSIZE ) - { - log_info(_("warning: invalid size of random_seed file - not used\n") ); - _close(fd); - return 0; - } + { + log_info(_("note: random_seed file is empty\n") ); + close(fd); + allow_seed_file_update = 1; + return 0; + } + if (sb.st_size != POOLSIZE ) + { + log_info(_("warning: invalid size of random_seed file - not used\n") ); + close(fd); + return 0; + } do - { - n = _read( fd, buffer, POOLSIZE ); - } + { + n = read( fd, buffer, POOLSIZE ); + } while (n == -1 && errno == EINTR ); if (n != POOLSIZE) - { - log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); - _close(fd);/*NOTREACHED*/ - return 0; - } - - _close(fd); + { + log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); + close(fd);/*NOTREACHED*/ + return 0; + } + + close(fd); add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT ); /* add some minor entropy to the pool now (this will also force a mixing) */ - { - pid_t x = getpid(); - add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT ); + { + pid_t x = getpid(); + add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT ); } { - time_t x = time(NULL); - add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT ); + time_t x = time(NULL); + add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT ); } - { - clock_t x = clock(); - add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT ); + { + clock_t x = clock(); + add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT ); } /* And read a few bytes from our entropy source. By using a level @@ -838,74 +846,74 @@ _gcry_rngcsprng_update_seed_file (void) int fd, i; /* We do only a basic initialization so that we can lock the pool. - This is required to cope with the case that this function is - called by some cleanup code at a point where the RNG has never - been initialized. */ + This is required to cope with the case that this function is + called by some cleanup code at a point where the RNG has never + been initialized. */ initialize_basics (); lock_pool (); if ( !seed_file_name || !rndpool || !pool_filled ) - { - unlock_pool (); - return; - } + { + unlock_pool (); + return; + } if ( !allow_seed_file_update ) - { - unlock_pool (); - log_info(_("note: random_seed file not updated\n")); - return; - } + { + unlock_pool (); + log_info(_("note: random_seed file not updated\n")); + return; + } /* At this point we know that there is something in the pool and - thus we can conclude that the pool has been fully initialized. */ + thus we can conclude that the pool has been fully initialized. */ /* Copy the entropy pool to a scratch pool and mix both of them. */ for (i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - { - *dp = *sp + ADD_VALUE; - } + i < POOLWORDS; i++, dp++, sp++ ) + { + *dp = *sp + ADD_VALUE; + } mix_pool(rndpool); rndstats.mixrnd++; mix_pool(keypool); rndstats.mixkey++; #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) - fd = _open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, - S_IRUSR|S_IWUSR ); + fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, + S_IRUSR|S_IWUSR ); #else # if LOCK_SEED_FILE - fd = _open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR ); + fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR ); # else - fd = _open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); + fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); # endif #endif if (fd == -1 ) - log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); + log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); else if (lock_seed_file (fd, seed_file_name, 1)) - { - _close (fd); - } + { + close (fd); + } #if LOCK_SEED_FILE else if (ftruncate (fd, 0)) - { - log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno)); - close (fd); - } + { + log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno)); + close (fd); + } #endif /*LOCK_SEED_FILE*/ - else - { - do - { - i = _write (fd, keypool, POOLSIZE ); - } - while (i == -1 && errno == EINTR); - if (i != POOLSIZE) - log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno)); - if (_close(fd)) - log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno)); - } - + else + { + do + { + i = write (fd, keypool, POOLSIZE ); + } + while (i == -1 && errno == EINTR); + if (i != POOLSIZE) + log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno)); + if (close(fd)) + log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno)); + } + unlock_pool (); } @@ -921,11 +929,11 @@ read_pool (byte *buffer, size_t length, int level) int i; unsigned long *sp, *dp; /* The volatile is there to make sure the compiler does not optimize - the code away in case the getpid function is badly attributed. - Note that we keep a pid in a static variable as well as in a - stack based one; the latter is to detect ill behaving thread - libraries, ignoring the pool mutexes. */ - static volatile pid_t my_pid = (pid_t)(-1); + the code away in case the getpid function is badly attributed. + Note that we keep a pid in a static variable as well as in a + stack based one; the latter is to detect ill behaving thread + libraries, ignoring the pool mutexes. */ + static volatile pid_t my_pid = (pid_t)(-1); volatile pid_t my_pid2; gcry_assert (pool_is_locked); @@ -933,128 +941,128 @@ read_pool (byte *buffer, size_t length, int level) retry: /* Get our own pid, so that we can detect a fork. */ my_pid2 = getpid (); - if (my_pid == (pid_t)(-1)) - my_pid = my_pid2; + if (my_pid == (pid_t)(-1)) + my_pid = my_pid2; if ( my_pid != my_pid2 ) - { - /* We detected a plain fork; i.e. we are now the child. Update - the static pid and add some randomness. */ - pid_t x; - - my_pid = my_pid2; - x = my_pid; - add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT); - just_mixed = 0; /* Make sure it will get mixed. */ - } + { + /* We detected a plain fork; i.e. we are now the child. Update + the static pid and add some randomness. */ + pid_t x; + + my_pid = my_pid2; + x = my_pid; + add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT); + just_mixed = 0; /* Make sure it will get mixed. */ + } gcry_assert (pool_is_locked); /* Our code does not allow to extract more than POOLSIZE. Better - check it here. */ + check it here. */ if (length > POOLSIZE) - { - log_bug("too many random bits requested\n"); - } + { + log_bug("too many random bits requested\n"); + } if (!pool_filled) - { - if (read_seed_file() ) - pool_filled = 1; - } + { + if (read_seed_file() ) + pool_filled = 1; + } /* For level 2 quality (key generation) we always make sure that the - pool has been seeded enough initially. */ + pool has been seeded enough initially. */ if (level == GCRY_VERY_STRONG_RANDOM && !did_initial_extra_seeding) - { - size_t needed; - - pool_balance = 0; - needed = length - pool_balance; - if (needed < POOLSIZE/2) - needed = POOLSIZE/2; - else if( needed > POOLSIZE ) - BUG (); - read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed, - GCRY_VERY_STRONG_RANDOM); - pool_balance += needed; - did_initial_extra_seeding = 1; - } + { + size_t needed; + + pool_balance = 0; + needed = length - pool_balance; + if (needed < POOLSIZE/2) + needed = POOLSIZE/2; + else if( needed > POOLSIZE ) + BUG (); + read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed, + GCRY_VERY_STRONG_RANDOM); + pool_balance += needed; + did_initial_extra_seeding = 1; + } /* For level 2 make sure that there is enough random in the pool. */ if (level == GCRY_VERY_STRONG_RANDOM && pool_balance < length) - { - size_t needed; - - if (pool_balance < 0) - pool_balance = 0; - needed = length - pool_balance; - if (needed > POOLSIZE) - BUG (); - read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed, - GCRY_VERY_STRONG_RANDOM); - pool_balance += needed; - } + { + size_t needed; + + if (pool_balance < 0) + pool_balance = 0; + needed = length - pool_balance; + if (needed > POOLSIZE) + BUG (); + read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed, + GCRY_VERY_STRONG_RANDOM); + pool_balance += needed; + } /* Make sure the pool is filled. */ while (!pool_filled) - random_poll(); + random_poll(); /* Always do a fast random poll (we have to use the unlocked version). */ do_fast_random_poll(); - + /* Mix the pid in so that we for sure won't deliver the same random - after a fork. */ + after a fork. */ { - pid_t apid = my_pid; - add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT); + pid_t apid = my_pid; + add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT); } /* Mix the pool (if add_randomness() didn't it). */ if (!just_mixed) - { - mix_pool(rndpool); - rndstats.mixrnd++; - } + { + mix_pool(rndpool); + rndstats.mixrnd++; + } /* Create a new pool. */ for(i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; + i < POOLWORDS; i++, dp++, sp++ ) + *dp = *sp + ADD_VALUE; /* Mix both pools. */ mix_pool(rndpool); rndstats.mixrnd++; mix_pool(keypool); rndstats.mixkey++; /* Read the requested data. We use a read pointer to read from a - different position each time. */ + different position each time. */ while (length--) - { - *buffer++ = keypool[pool_readpos++]; - if (pool_readpos >= POOLSIZE) - pool_readpos = 0; - pool_balance--; - } - + { + *buffer++ = keypool[pool_readpos++]; + if (pool_readpos >= POOLSIZE) + pool_readpos = 0; + pool_balance--; + } + if (pool_balance < 0) - pool_balance = 0; + pool_balance = 0; /* Clear the keypool. */ memset (keypool, 0, POOLSIZE); /* We need to detect whether a fork has happened. A fork might have - an identical pool and thus the child and the parent could emit - the very same random number. This test here is to detect forks - in a multi-threaded process. It does not work with all thread - implementations in particular not with pthreads. However it is - good enough for GNU Pth. */ + an identical pool and thus the child and the parent could emit + the very same random number. This test here is to detect forks + in a multi-threaded process. It does not work with all thread + implementations in particular not with pthreads. However it is + good enough for GNU Pth. */ if ( getpid () != my_pid2 ) - { - pid_t x = getpid(); - add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT); - just_mixed = 0; /* Make sure it will get mixed. */ - my_pid = x; /* Also update the static pid. */ - goto retry; - } + { + pid_t x = getpid(); + add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT); + just_mixed = 0; /* Make sure it will get mixed. */ + my_pid = x; /* Also update the static pid. */ + goto retry; + } } @@ -1073,28 +1081,28 @@ add_randomness (const void *buffer, size_t length, enum random_origins origin) rndstats.addbytes += length; rndstats.naddbytes++; while (length-- ) - { - rndpool[pool_writepos++] ^= *p++; - count++; - if (pool_writepos >= POOLSIZE ) - { - /* It is possible that we are invoked before the pool is - filled using an unreliable origin of entropy, for example - the fast random poll. To avoid flagging the pool as - filled in this case, we track the initial filling state - separately. See also the remarks about the seed file. */ - if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled) - { - pool_filled_counter += count; - count = 0; - if (pool_filled_counter >= POOLSIZE) - pool_filled = 1; - } - pool_writepos = 0; - mix_pool(rndpool); rndstats.mixrnd++; - just_mixed = !length; - } + { + rndpool[pool_writepos++] ^= *p++; + count++; + if (pool_writepos >= POOLSIZE ) + { + /* It is possible that we are invoked before the pool is + filled using an unreliable origin of entropy, for example + the fast random poll. To avoid flagging the pool as + filled in this case, we track the initial filling state + separately. See also the remarks about the seed file. */ + if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled) + { + pool_filled_counter += count; + count = 0; + if (pool_filled_counter >= POOLSIZE) + pool_filled = 1; + } + pool_writepos = 0; + mix_pool(rndpool); rndstats.mixrnd++; + just_mixed = !length; } + } } @@ -1109,28 +1117,28 @@ random_poll() /* Runtime determination of the slow entropy gathering module. */ static int (* -getfnc_gather_random (void))(void (*)(const void*, size_t, - enum random_origins), - enum random_origins, size_t, int) +getfnc_gather_random (void))(void (*)(const void*, size_t, + enum random_origins), + enum random_origins, size_t, int) { - int (*fnc)(void (*)(const void*, size_t, enum random_origins), - enum random_origins, size_t, int); - + int (*fnc)(void (*)(const void*, size_t, enum random_origins), + enum random_origins, size_t, int); + #if USE_RNDLINUX if ( !access (NAME_OF_DEV_RANDOM, R_OK) - && !access (NAME_OF_DEV_URANDOM, R_OK)) - { - fnc = _gcry_rndlinux_gather_random; - return fnc; - } + && !access (NAME_OF_DEV_URANDOM, R_OK)) + { + fnc = _gcry_rndlinux_gather_random; + return fnc; + } #endif #if USE_RNDEGD if ( _gcry_rndegd_connect_socket (1) != -1 ) - { - fnc = _gcry_rndegd_gather_random; - return fnc; - } + { + fnc = _gcry_rndegd_gather_random; + return fnc; + } #endif #if USE_RNDUNIX @@ -1143,6 +1151,11 @@ getfnc_gather_random (void))(void (*)(const void*, size_t, return fnc; #endif +#if USE_RNDW32CE + fnc = _gcry_rndw32ce_gather_random; + return fnc; +#endif + log_fatal (_("no entropy gathering module detected\n")); return NULL; /*NOTREACHED*/ @@ -1152,12 +1165,15 @@ getfnc_gather_random (void))(void (*)(const void*, size_t, (Currently a compile time method is used.) */ static void (* getfnc_fast_random_poll (void))( void (*)(const void*, size_t, - enum random_origins), - enum random_origins) + enum random_origins), + enum random_origins) { #if USE_RNDW32 return _gcry_rndw32_gather_random_fast; #endif +#if USE_RNDW32CE + return _gcry_rndw32ce_gather_random_fast; +#endif return NULL; } @@ -1171,27 +1187,27 @@ do_fast_random_poll (void) rndstats.fastpolls++; if (fast_gather_fnc) - fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL); + fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL); /* Continue with the generic functions. */ #if HAVE_GETHRTIME - { - hrtime_t tv; - tv = gethrtime(); - add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL ); + { + hrtime_t tv; + tv = gethrtime(); + add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL ); } #elif HAVE_GETTIMEOFDAY - { - struct timeval tv; - if( gettimeofday( &tv, NULL ) ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL ); - add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL ); + { + struct timeval tv; + if( gettimeofday( &tv, NULL ) ) + BUG(); + add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL ); + add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL ); } #elif HAVE_CLOCK_GETTIME { struct timespec tv; if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) - BUG(); + BUG(); add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL ); add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), RANDOM_ORIGIN_FASTPOLL ); } @@ -1206,15 +1222,15 @@ do_fast_random_poll (void) #ifdef HAVE_GETRUSAGE # ifdef RUSAGE_SELF - { - struct rusage buf; - /* QNX/Neutrino does return ENOSYS - so we just ignore it and add - whatever is in buf. In a chroot environment it might not work - at all (i.e. because /proc/ is not accessible), so we better - ignore all error codes and hope for the best. */ - getrusage (RUSAGE_SELF, &buf ); - add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL ); - memset( &buf, 0, sizeof buf ); + { + struct rusage buf; + /* QNX/Neutrino does return ENOSYS - so we just ignore it and add + whatever is in buf. In a chroot environment it might not work + at all (i.e. because /proc/ is not accessible), so we better + ignore all error codes and hope for the best. */ + getrusage (RUSAGE_SELF, &buf ); + add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL ); + memset( &buf, 0, sizeof buf ); } # else /*!RUSAGE_SELF*/ # ifdef __GCC__ @@ -1224,25 +1240,25 @@ do_fast_random_poll (void) #endif /*HAVE_GETRUSAGE*/ /* Time and clock are availabe on all systems - so we better do it - just in case one of the above functions didn't work. */ + just in case one of the above functions didn't work. */ { - time_t x = time(NULL); - add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL ); + time_t x = time(NULL); + add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL ); } - { - clock_t x = clock(); - add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL ); + { + clock_t x = clock(); + add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL ); } /* If the system features a fast hardware RNG, read some bytes from - there. */ + there. */ _gcry_rndhw_poll_fast (add_randomness, RANDOM_ORIGIN_FASTPOLL); } /* The fast random pool function as called at some places in libgcrypt. This is merely a wrapper to make sure that this module - is initalized and to look the pool. Note, that this function is a + is initialized and to lock the pool. Note, that this function is a NOP unless a random function has been used or _gcry_initialize (1) has been used. We use this hack so that the internal use of this function in cipher_open and md_open won't start filling up the @@ -1254,10 +1270,10 @@ _gcry_rngcsprng_fast_poll (void) lock_pool (); if (rndpool) - { - /* Yes, we are fully initialized. */ - do_fast_random_poll (); - } + { + /* Yes, we are fully initialized. */ + do_fast_random_poll (); + } unlock_pool (); } @@ -1267,131 +1283,45 @@ static void read_random_source (enum random_origins orgin, size_t length, int level ) { if ( !slow_gather_fnc ) - log_fatal ("Slow entropy gathering module not yet initialized\n"); + log_fatal ("Slow entropy gathering module not yet initialized\n"); if ( slow_gather_fnc (add_randomness, orgin, length, level) < 0) - log_fatal ("No way to gather entropy for the RNG\n"); + log_fatal ("No way to gather entropy for the RNG\n"); } static int gather_faked (void (*add)(const void*, size_t, enum random_origins), - enum random_origins origin, size_t length, int level ) + enum random_origins origin, size_t length, int level ) { static int initialized=0; size_t n; char *buffer, *p; - + (void)add; (void)level; - + if ( !initialized ) - { - log_info(_("WARNING: using insecure random number generator!!\n")); - initialized=1; + { + log_info(_("WARNING: using insecure random number generator!!\n")); + initialized=1; #ifdef HAVE_RAND - srand( time(NULL)*getpid()); + srand( time(NULL)*getpid()); #else - srandom( time(NULL)*getpid()); + srandom( time(NULL)*getpid()); #endif - } + } - p = buffer = gcry_xmalloc( length ); + p = buffer = xmalloc( length ); n = length; #ifdef HAVE_RAND while ( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); + *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); #else while ( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); + *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); #endif add_randomness ( buffer, length, origin ); - gcry_free (buffer); + xfree (buffer); return 0; /* okay */ } - - -/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ -void -_gcry_rngcsprng_create_nonce (void *buffer, size_t length) -{ - static unsigned char nonce_buffer[20+8]; - static int nonce_buffer_initialized = 0; - static volatile pid_t my_pid; /* The volatile is there to make sure the - compiler does not optimize the code away - in case the getpid function is badly - attributed. */ - volatile pid_t apid; - unsigned char *p; - size_t n; - int err; - - /* Make sure we are initialized. */ - initialize (); - -#ifdef USE_RANDOM_DAEMON - if (allow_daemon - && !_gcry_daemon_create_nonce (daemon_socket_name, buffer, length)) - return; /* The daemon succeeded. */ - allow_daemon = 0; /* Daemon failed - switch off. */ -#endif /*USE_RANDOM_DAEMON*/ - - /* Acquire the nonce buffer lock. */ - err = ath_mutex_lock (&nonce_buffer_lock); - if (err) - log_fatal ("failed to acquire the nonce buffer lock: %s\n", - strerror (err)); - - apid = getpid (); - /* The first time intialize our buffer. */ - if (!nonce_buffer_initialized) - { - time_t atime = time (NULL); - pid_t xpid = apid; - - my_pid = apid; - - if ((sizeof apid + sizeof atime) > sizeof nonce_buffer) - BUG (); - - /* Initialize the first 20 bytes with a reasonable value so that - a failure of gcry_randomize won't affect us too much. Don't - care about the uninitialized remaining bytes. */ - p = nonce_buffer; - memcpy (p, &xpid, sizeof xpid); - p += sizeof xpid; - memcpy (p, &atime, sizeof atime); - - /* Initialize the never changing private part of 64 bits. */ - gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM); - - nonce_buffer_initialized = 1; - } - else if ( my_pid != apid ) - { - /* We forked. Need to reseed the buffer - doing this for the - private part should be sufficient. */ - gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM); - /* Update the pid so that we won't run into here again and - again. */ - my_pid = apid; - } - - /* Create the nonce by hashing the entire buffer, returning the hash - and updating the first 20 bytes of the buffer with this hash. */ - for (p = buffer; length > 0; length -= n, p += n) - { - _gcry_sha1_hash_buffer (nonce_buffer, - nonce_buffer, sizeof nonce_buffer); - n = length > 20? 20 : length; - memcpy (p, nonce_buffer, n); - } - - - /* Release the nonce buffer lock. */ - err = ath_mutex_unlock (&nonce_buffer_lock); - if (err) - log_fatal ("failed to release the nonce buffer lock: %s\n", - strerror (err)); - -} diff --git a/plugins/MirOTR/Libgcrypt/random/random-daemon.c b/plugins/MirOTR/Libgcrypt/random/random-daemon.c index 2e03ba00e5..98a015363a 100644 --- a/plugins/MirOTR/Libgcrypt/random/random-daemon.c +++ b/plugins/MirOTR/Libgcrypt/random/random-daemon.c @@ -28,6 +28,7 @@ sensitive data. */ +#error This dameon needs to be fixed due to the ath changes #include <config.h> #include <stdio.h> @@ -53,7 +54,7 @@ static ath_mutex_t daemon_lock = ATH_MUTEX_INITIALIZER; /* The socket connected to the daemon. */ -static int daemon_socket = -1; +static int daemon_socket = -1; /* Creates a socket connected to the daemon. On success, store the socket fd in *SOCK. Returns error code. */ @@ -78,7 +79,7 @@ connect_to_socket (const char *socketname, int *sock) } /* Set up address. */ - srvr_addr = gcry_malloc (sizeof *srvr_addr); + srvr_addr = gcry_malloc (sizeof *srvr_addr); if (! srvr_addr) { log_error ("malloc failed: %s\n", strerror (errno)); @@ -148,7 +149,7 @@ static int writen (int fd, const void *buffer, size_t length) { ssize_t n; - + while (length) { do @@ -171,7 +172,7 @@ readn (int fd, void *buf, size_t buflen, size_t *ret_nread) size_t nleft = buflen; int nread; char *p; - + p = buf; while (nleft > 0) { @@ -180,7 +181,7 @@ readn (int fd, void *buf, size_t buflen, size_t *ret_nread) { if (nread == EINTR) nread = 0; - else + else return -1; } else if (!nread) @@ -262,14 +263,14 @@ call_daemon (const char *socketname, err = gcry_error_from_errno (errno); break; } - + /* Retrieve response. */ rc = readn (daemon_socket, buf, 2, &nread); if (rc == -1) { err = gcry_error_from_errno (errno); - log_error ("read error: %s\n", gcry_strerror (err)); + log_error ("read error: %s\n", _gcry_strerror (err)); break; } if (nread && buf[0]) @@ -307,10 +308,10 @@ call_daemon (const char *socketname, if (rc == -1) { err = gcry_error_from_errno (errno); - log_error ("read error: %s\n", gcry_strerror (err)); + log_error ("read error: %s\n", _gcry_strerror (err)); break; } - + if (nread != nbytes) { log_error ("too little random data read\n"); @@ -333,7 +334,7 @@ call_daemon (const char *socketname, support GCRY_STRONG_RANDOM and GCRY_VERY_STRONG_RANDOM here. Return 0 on success. */ int -_gcry_daemon_randomize (const char *socketname, +_gcry_daemon_randomize (const char *socketname, void *buffer, size_t length, enum gcry_random_level level) { @@ -344,17 +345,4 @@ _gcry_daemon_randomize (const char *socketname, return err ? -1 : 0; } - -/* Internal function to fill BUFFER with NBYTES of data usable for a - nonce. Returns 0 on success. */ -int -_gcry_daemon_create_nonce (const char *socketname, void *buffer, size_t length) -{ - gcry_error_t err; - - err = call_daemon (socketname, buffer, length, 1, 0); - - return err ? -1 : 0; -} - /* END */ diff --git a/plugins/MirOTR/Libgcrypt/random/random-fips.c b/plugins/MirOTR/Libgcrypt/random/random-fips.c index 2667e71fd8..d00825e2a1 100644 --- a/plugins/MirOTR/Libgcrypt/random/random-fips.c +++ b/plugins/MirOTR/Libgcrypt/random/random-fips.c @@ -72,7 +72,7 @@ integer variable is only used to check the locking state; that is, it is not meant to be thread-safe but merely as a failsafe feature to assert proper locking. */ -static ath_mutex_t fips_rng_lock = ATH_MUTEX_INITIALIZER; +static ath_mutex_t fips_rng_lock; static int fips_rng_is_locked; @@ -135,7 +135,7 @@ struct rng_context unsigned char guard_2[1]; - /* The last result from the x931_aes fucntion. Only valid if + /* The last result from the x931_aes function. Only valid if compare_value_valid is set. */ unsigned char compare_value[16]; @@ -157,7 +157,7 @@ struct rng_context /* We need to keep track of the process which did the initialization so that we can detect a fork. The volatile modifier is required so that the compiler does not optimize it away in case the getpid - function is badly attributed. */ + function is badly attributed. */ pid_t key_init_pid; pid_t seed_init_pid; }; @@ -192,7 +192,7 @@ basic_initialization (void) static int initialized; int my_errno; - if (!initialized) + if (initialized) return; initialized = 1; @@ -200,10 +200,10 @@ basic_initialization (void) if (my_errno) log_fatal ("failed to create the RNG lock: %s\n", strerror (my_errno)); fips_rng_is_locked = 0; - + /* Make sure that we are still using the values we have traditionally used for the random levels. */ - gcry_assert (GCRY_WEAK_RANDOM == 0 + gcry_assert (GCRY_WEAK_RANDOM == 0 && GCRY_STRONG_RANDOM == 1 && GCRY_VERY_STRONG_RANDOM == 2); @@ -262,7 +262,7 @@ check_guards (rng_context_t rng_ctx) timestamp we construct is made up the real time and three counters: Buffer: 00112233445566778899AABBCCDDEEFF - !--+---!!-+-!!+!!--+---!!--+---! + !--+---!!-+-!!+!!--+---!!--+---! seconds ---------/ | | | | microseconds -----------/ | | | counter2 -------------------/ | | @@ -272,7 +272,7 @@ check_guards (rng_context_t rng_ctx) Counter 2 is just 12 bits wide and used to track fractions of milliseconds whereas counters 1 and 0 are combined to a free running 64 bit counter. */ -static void +static void x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) { gcry_assert (length == 16); /* This length is required for use with AES. */ @@ -281,7 +281,7 @@ x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) /* If the random context indicates that a test DT should be used, take the DT value from the context. For safety reasons we do this only if the context is not one of the regular contexts. */ - if (rng_ctx->test_dt_ptr + if (rng_ctx->test_dt_ptr && rng_ctx != nonce_context && rng_ctx != std_rng_context && rng_ctx != strong_rng_context) @@ -301,7 +301,7 @@ x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) static u32 last_sec, last_usec; static u32 counter1, counter0; static u16 counter2; - + unsigned int usec; struct timeval tv; @@ -350,11 +350,11 @@ x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) /* Add the free running counter. */ buffer[8] = ((counter1 >> 24) & 0xff); buffer[9] = ((counter1 >> 16) & 0xff); - buffer[10] = ((counter1 >> 8) & 0xff); + buffer[10] = ((counter1 >> 8) & 0xff); buffer[11] = ((counter1) & 0xff); buffer[12] = ((counter0 >> 24) & 0xff); buffer[13] = ((counter0 >> 16) & 0xff); - buffer[14] = ((counter0 >> 8) & 0xff); + buffer[14] = ((counter0 >> 8) & 0xff); buffer[15] = ((counter0) & 0xff); /* Bump up that counter. */ if (!++counter0) @@ -372,7 +372,7 @@ x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) the result at R. R needs to be provided by the caller with a size of at least LENGTH bytes. */ static void -xor_buffer (unsigned char *r, +xor_buffer (unsigned char *r, const unsigned char *a, const unsigned char *b, size_t length) { for ( ; length; length--, a++, b++, r++) @@ -383,16 +383,16 @@ xor_buffer (unsigned char *r, /* Encrypt LENGTH bytes of INPUT to OUTPUT using KEY. LENGTH needs to be 16. */ static void -encrypt_aes (gcry_cipher_hd_t key, +encrypt_aes (gcry_cipher_hd_t key, unsigned char *output, const unsigned char *input, size_t length) { gpg_error_t err; gcry_assert (length == 16); - err = gcry_cipher_encrypt (key, output, length, input, length); + err = _gcry_cipher_encrypt (key, output, length, input, length); if (err) - log_fatal ("AES encryption in RNG failed: %s\n", gcry_strerror (err)); + log_fatal ("AES encryption in RNG failed: %s\n", _gcry_strerror (err)); } @@ -406,7 +406,7 @@ encrypt_aes (gcry_cipher_hd_t key, On return the result is stored at RESULT_R and the SEED_V is updated. May only be used while holding the lock. */ static void -x931_aes (unsigned char result_R[16], +x931_aes (unsigned char result_R[16], unsigned char datetime_DT[16], unsigned char seed_V[16], gcry_cipher_hd_t key, unsigned char intermediate_I[16], unsigned char temp_xor[16]) @@ -415,7 +415,7 @@ x931_aes (unsigned char result_R[16], Let V be a 128-bit seed value which is also kept secret, and XOR be the exclusive-or operator. Let DT be a date/time vector which - is updated on each iteration. I is a intermediate value. + is updated on each iteration. I is a intermediate value. I = ede*K(DT) */ encrypt_aes (key, intermediate_I, datetime_DT, 16); @@ -509,7 +509,7 @@ x931_aes_driver (unsigned char *output, size_t length, rng_context_t rng_ctx) } memcpy (rng_ctx->compare_value, result_buffer, 16); } - + /* Append to outbut. */ memcpy (output, result_buffer, nbytes); wipememory (result_buffer, 16); @@ -555,7 +555,7 @@ get_entropy (size_t nbytes) int rc; gcry_assert (!entropy_collect_buffer); - entropy_collect_buffer = gcry_xmalloc_secure (nbytes); + entropy_collect_buffer = xmalloc_secure (nbytes); entropy_collect_buffer_size = nbytes; entropy_collect_buffer_len = 0; @@ -564,7 +564,7 @@ get_entropy (size_t nbytes) X931_AES_KEYLEN, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDW32 - do + do { rc = _gcry_rndw32_gather_random (entropy_collect_cb, 0, X931_AES_KEYLEN, @@ -577,7 +577,7 @@ get_entropy (size_t nbytes) if (rc < 0 || entropy_collect_buffer_len != entropy_collect_buffer_size) { - gcry_free (entropy_collect_buffer); + xfree (entropy_collect_buffer); entropy_collect_buffer = NULL; log_fatal ("error getting entropy data\n"); } @@ -595,25 +595,25 @@ static gcry_cipher_hd_t x931_generate_key (int for_nonce) { gcry_cipher_hd_t hd; - gpg_error_t err; + gpg_err_code_t rc; void *buffer; gcry_assert (fips_rng_is_locked); /* Allocate a cipher context. */ - err = gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, + rc = _gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE); - if (err) + if (rc) { log_error ("error creating cipher context for RNG: %s\n", - gcry_strerror (err)); + _gcry_strerror (rc)); return NULL; } /* Get a key from the standard RNG or from the entropy source. */ if (for_nonce) { - buffer = gcry_xmalloc (X931_AES_KEYLEN); + buffer = xmalloc (X931_AES_KEYLEN); get_random (buffer, X931_AES_KEYLEN, std_rng_context); } else @@ -623,13 +623,13 @@ x931_generate_key (int for_nonce) /* Set the key and delete the buffer because the key is now part of the cipher context. */ - err = gcry_cipher_setkey (hd, buffer, X931_AES_KEYLEN); + rc = _gcry_cipher_setkey (hd, buffer, X931_AES_KEYLEN); wipememory (buffer, X931_AES_KEYLEN); - gcry_free (buffer); - if (err) + xfree (buffer); + if (rc) { - log_error ("error creating key for RNG: %s\n", gcry_strerror (err)); - gcry_cipher_close (hd); + log_error ("error creating key for RNG: %s\n", _gcry_strerror (rc)); + _gcry_cipher_close (hd); return NULL; } @@ -651,7 +651,7 @@ x931_generate_seed (unsigned char *seed_buffer, size_t length) memcpy (seed_buffer, buffer, X931_AES_KEYLEN); wipememory (buffer, X931_AES_KEYLEN); - gcry_free (buffer); + xfree (buffer); } @@ -753,17 +753,17 @@ _gcry_rngfips_initialize (int full) if (!tempvalue_for_x931_aes_driver) { tempvalue_for_x931_aes_driver - = gcry_xmalloc_secure (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE); + = xmalloc_secure (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE); /* Allocate the random contexts. Note that we do not need to use secure memory for the nonce context. */ - nonce_context = gcry_xcalloc (1, sizeof *nonce_context); + nonce_context = xcalloc (1, sizeof *nonce_context); setup_guards (nonce_context); - std_rng_context = gcry_xcalloc_secure (1, sizeof *std_rng_context); + std_rng_context = xcalloc_secure (1, sizeof *std_rng_context); setup_guards (std_rng_context); - - strong_rng_context = gcry_xcalloc_secure (1, sizeof *strong_rng_context); + + strong_rng_context = xcalloc_secure (1, sizeof *strong_rng_context); setup_guards (strong_rng_context); } else @@ -780,6 +780,19 @@ _gcry_rngfips_initialize (int full) } +/* Try to close the FDs of the random gather module. This is + currently only implemented for rndlinux. */ +void +_gcry_rngfips_close_fds (void) +{ + lock_rng (); +#if USE_RNDLINUX + _gcry_rndlinux_gather_random (NULL, 0, 0, 0); +#endif + unlock_rng (); +} + + /* Print some statistics about the RNG. */ void _gcry_rngfips_dump_stats (void) @@ -807,9 +820,9 @@ _gcry_rngfips_add_bytes (const void *buf, size_t buflen, int quality) (void)buflen; (void)quality; return 0; /* Not implemented. */ -} +} + - /* Public function to fill the buffer with LENGTH bytes of cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong @@ -820,7 +833,7 @@ _gcry_rngfips_randomize (void *buffer, size_t length, enum gcry_random_level level) { _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - + lock_rng (); if (level == GCRY_VERY_STRONG_RANDOM) get_random (buffer, length, strong_rng_context); @@ -850,7 +863,7 @@ _gcry_rngfips_create_nonce (void *buffer, size_t length) static gcry_err_code_t selftest_kat (selftest_report_func_t report) { - static struct + static struct { const unsigned char key[16]; const unsigned char dt[16]; @@ -880,7 +893,7 @@ selftest_kat (selftest_report_func_t report) 0x13, 0xd3, 0x13, 0xfa, 0x20, 0xe9, 0x8d, 0xbc }, { 0xc8, 0xd1, 0xe5, 0x11, 0x59, 0x52, 0xf7, 0xfa, 0x37, 0x38, 0xb4, 0xc5, 0xce, 0xb2, 0xb0, 0x9a }, - { 0x0d, 0x9c, 0xc5, 0x0d, 0x16, 0xe1, 0xbc, 0xed, + { 0x0d, 0x9c, 0xc5, 0x0d, 0x16, 0xe1, 0xbc, 0xed, 0xcf, 0x60, 0x62, 0x09, 0x9d, 0x20, 0x83, 0x7e } } }, { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, @@ -892,50 +905,50 @@ selftest_kat (selftest_report_func_t report) 0x63, 0x19, 0x37, 0x6f, 0x15, 0x22, 0x57, 0x56 }, { 0x7a, 0x14, 0x76, 0x77, 0x95, 0x17, 0x7e, 0xc8, 0x92, 0xe8, 0xdd, 0x15, 0xcb, 0x1f, 0xbc, 0xb1 }, - { 0x25, 0x3e, 0x2e, 0xa2, 0x41, 0x1b, 0xdd, 0xf5, + { 0x25, 0x3e, 0x2e, 0xa2, 0x41, 0x1b, 0xdd, 0xf5, 0x21, 0x48, 0x41, 0x71, 0xb3, 0x8d, 0x2f, 0x4c } } } }; int tvidx, ridx; rng_context_t test_ctx; - gpg_error_t err; + gpg_err_code_t rc; const char *errtxt = NULL; unsigned char result[16]; gcry_assert (tempvalue_for_x931_aes_driver); - test_ctx = gcry_xcalloc (1, sizeof *test_ctx); + test_ctx = xcalloc (1, sizeof *test_ctx); setup_guards (test_ctx); - + lock_rng (); for (tvidx=0; tvidx < DIM (tv); tvidx++) { /* Setup the key. */ - err = gcry_cipher_open (&test_ctx->cipher_hd, + rc = _gcry_cipher_open (&test_ctx->cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE); - if (err) + if (rc) { errtxt = "error creating cipher context for RNG"; goto leave; } - err = gcry_cipher_setkey (test_ctx->cipher_hd, tv[tvidx].key, 16); - if (err) + rc = _gcry_cipher_setkey (test_ctx->cipher_hd, tv[tvidx].key, 16); + if (rc) { errtxt = "error setting key for RNG"; goto leave; } test_ctx->key_init_pid = getpid (); - + /* Setup the seed. */ memcpy (test_ctx->seed_V, tv[tvidx].v, 16); test_ctx->is_seeded = 1; test_ctx->seed_init_pid = getpid (); - + /* Setup a DT value. */ test_ctx->test_dt_ptr = tv[tvidx].dt; - test_ctx->test_dt_counter = ( (tv[tvidx].dt[12] << 24) + test_ctx->test_dt_counter = ( (tv[tvidx].dt[12] << 24) |(tv[tvidx].dt[13] << 16) |(tv[tvidx].dt[14] << 8) |(tv[tvidx].dt[15]) ); @@ -949,7 +962,7 @@ selftest_kat (selftest_report_func_t report) errtxt = "X9.31 RNG core function failed"; goto leave; } - + /* Compare it to the known value. */ if (memcmp (result, tv[tvidx].r[ridx], 16)) { @@ -969,7 +982,7 @@ selftest_kat (selftest_report_func_t report) goto leave; } - gcry_cipher_close (test_ctx->cipher_hd); + _gcry_cipher_close (test_ctx->cipher_hd); test_ctx->cipher_hd = NULL; test_ctx->is_seeded = 0; check_guards (test_ctx); @@ -977,9 +990,9 @@ selftest_kat (selftest_report_func_t report) leave: unlock_rng (); - gcry_cipher_close (test_ctx->cipher_hd); + _gcry_cipher_close (test_ctx->cipher_hd); check_guards (test_ctx); - gcry_free (test_ctx); + xfree (test_ctx); if (report && errtxt) report ("random", 0, "KAT", errtxt); return errtxt? GPG_ERR_SELFTEST_FAILED : 0; @@ -997,10 +1010,10 @@ _gcry_rngfips_selftest (selftest_report_func_t report) char buffer[8]; /* Do a simple test using the public interface. This will also - enforce full intialization of the RNG. We need to be fully + enforce full initialization of the RNG. We need to be fully initialized due to the global requirement of the tempvalue_for_x931_aes_driver stuff. */ - gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM); + _gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM); } ec = selftest_kat (report); @@ -1022,46 +1035,46 @@ _gcry_rngfips_init_external_test (void **r_context, unsigned int flags, const void *seed, size_t seedlen, const void *dt, size_t dtlen) { - gpg_error_t err; + gpg_err_code_t rc; rng_context_t test_ctx; _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - + if (!r_context - || !key || keylen != 16 + || !key || keylen != 16 || !seed || seedlen != 16 || !dt || dtlen != 16 ) return GPG_ERR_INV_ARG; - test_ctx = gcry_calloc (1, sizeof *test_ctx + dtlen); + test_ctx = xtrycalloc (1, sizeof *test_ctx + dtlen); if (!test_ctx) return gpg_err_code_from_syserror (); setup_guards (test_ctx); - + /* Setup the key. */ - err = gcry_cipher_open (&test_ctx->cipher_hd, + rc = _gcry_cipher_open (&test_ctx->cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE); - if (err) + if (rc) goto leave; - err = gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen); - if (err) + rc = _gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen); + if (rc) goto leave; test_ctx->key_init_pid = getpid (); - + /* Setup the seed. */ memcpy (test_ctx->seed_V, seed, seedlen); test_ctx->is_seeded = 1; test_ctx->seed_init_pid = getpid (); - + /* Setup a DT value. Because our context structure only stores a pointer we copy the DT value to the extra space we allocated in the test_ctx and set the pointer to that address. */ memcpy ((unsigned char*)test_ctx + sizeof *test_ctx, dt, dtlen); - test_ctx->test_dt_ptr = (unsigned char*)test_ctx + sizeof *test_ctx; - test_ctx->test_dt_counter = ( (test_ctx->test_dt_ptr[12] << 24) + test_ctx->test_dt_ptr = (unsigned char*)test_ctx + sizeof *test_ctx; + test_ctx->test_dt_counter = ( (test_ctx->test_dt_ptr[12] << 24) |(test_ctx->test_dt_ptr[13] << 16) |(test_ctx->test_dt_ptr[14] << 8) |(test_ctx->test_dt_ptr[15]) ); @@ -1071,18 +1084,18 @@ _gcry_rngfips_init_external_test (void **r_context, unsigned int flags, check_guards (test_ctx); /* All fine. */ - err = 0; + rc = 0; leave: - if (err) + if (rc) { - gcry_cipher_close (test_ctx->cipher_hd); - gcry_free (test_ctx); + _gcry_cipher_close (test_ctx->cipher_hd); + xfree (test_ctx); *r_context = NULL; } else *r_context = test_ctx; - return gcry_err_code (err); + return rc; } @@ -1110,9 +1123,7 @@ _gcry_rngfips_deinit_external_test (void *context) if (test_ctx) { - gcry_cipher_close (test_ctx->cipher_hd); - gcry_free (test_ctx); + _gcry_cipher_close (test_ctx->cipher_hd); + xfree (test_ctx); } } - - diff --git a/plugins/MirOTR/Libgcrypt/random/random-system.c b/plugins/MirOTR/Libgcrypt/random/random-system.c new file mode 100644 index 0000000000..3962ab8816 --- /dev/null +++ b/plugins/MirOTR/Libgcrypt/random/random-system.c @@ -0,0 +1,256 @@ +/* random-system.c - wrapper around the system's RNG + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* + This RNG is merely wrapper around the system's native RNG. For + example on Unix systems it directly uses /dev/{u,}random. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> +#ifdef HAVE_GETTIMEOFDAY +#include <sys/time.h> +#endif + +#include "g10lib.h" +#include "random.h" +#include "rand-internal.h" +#include "ath.h" + +/* This is the lock we use to serialize access to this RNG. The extra + integer variable is only used to check the locking state; that is, + it is not meant to be thread-safe but merely as a failsafe feature + to assert proper locking. */ +static ath_mutex_t system_rng_lock; +static int system_rng_is_locked; + + +/* --- Local prototypes --- */ + + + + +/* --- Functions --- */ + +/* Basic initialization is required to initialize mutexes and + do a few checks on the implementation. */ +static void +basic_initialization (void) +{ + static int initialized; + int my_errno; + + if (initialized) + return; + initialized = 1; + + my_errno = ath_mutex_init (&system_rng_lock); + if (my_errno) + log_fatal ("failed to create the System RNG lock: %s\n", + strerror (my_errno)); + system_rng_is_locked = 0; + + /* Make sure that we are still using the values we traditionally + used for the random levels. */ + gcry_assert (GCRY_WEAK_RANDOM == 0 + && GCRY_STRONG_RANDOM == 1 + && GCRY_VERY_STRONG_RANDOM == 2); + +} + + +/* Acquire the system_rng_lock. */ +static void +lock_rng (void) +{ + int my_errno; + + my_errno = ath_mutex_lock (&system_rng_lock); + if (my_errno) + log_fatal ("failed to acquire the System RNG lock: %s\n", + strerror (my_errno)); + system_rng_is_locked = 1; +} + + +/* Release the system_rng_lock. */ +static void +unlock_rng (void) +{ + int my_errno; + + system_rng_is_locked = 0; + my_errno = ath_mutex_unlock (&system_rng_lock); + if (my_errno) + log_fatal ("failed to release the System RNG lock: %s\n", + strerror (my_errno)); +} + + +/* Helper variables for read_cb(). + + The _gcry_rnd*_gather_random interface does not allow to provide a + data pointer. Thus we need to use a global variable for + communication. However, the then required locking is anyway a good + idea because it does not make sense to have several readers of (say + /dev/random). It is easier to serve them one after the other. */ +static unsigned char *read_cb_buffer; /* The buffer. */ +static size_t read_cb_size; /* Size of the buffer. */ +static size_t read_cb_len; /* Used length. */ + + +/* Callback for _gcry_rnd*_gather_random. */ +static void +read_cb (const void *buffer, size_t length, enum random_origins origin) +{ + const unsigned char *p = buffer; + + (void)origin; + + gcry_assert (system_rng_is_locked); + gcry_assert (read_cb_buffer); + + /* Note that we need to protect against gatherers returning more + than the requested bytes (e.g. rndw32). */ + while (length-- && read_cb_len < read_cb_size) + { + read_cb_buffer[read_cb_len++] = *p++; + } +} + + +/* Fill BUFFER with LENGTH bytes of random at quality LEVEL. The + function either succeeds or terminates the process in case of a + fatal error. */ +static void +get_random (void *buffer, size_t length, int level) +{ + int rc; + + gcry_assert (buffer); + + read_cb_buffer = buffer; + read_cb_size = length; + read_cb_len = 0; + +#if USE_RNDLINUX + rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level); +#elif USE_RNDUNIX + rc = _gcry_rndunix_gather_random (read_cb, 0, length, level); +#elif USE_RNDW32 + do + { + rc = _gcry_rndw32_gather_random (read_cb, 0, length, level); + } + while (rc >= 0 && read_cb_len < read_cb_size); +#else + rc = -1; +#endif + + if (rc < 0 || read_cb_len != read_cb_size) + { + log_fatal ("error reading random from system RNG (rc=%d)\n", rc); + } +} + + + +/* --- Public Functions --- */ + +/* Initialize this random subsystem. If FULL is false, this function + merely calls the basic initialization of the module and does not do + anything more. Doing this is not really required but when running + in a threaded environment we might get a race condition + otherwise. */ +void +_gcry_rngsystem_initialize (int full) +{ + basic_initialization (); + if (!full) + return; + /* Nothing more to initialize. */ + return; +} + + +/* Try to close the FDs of the random gather module. This is + currently only implemented for rndlinux. */ +void +_gcry_rngsystem_close_fds (void) +{ + lock_rng (); +#if USE_RNDLINUX + _gcry_rndlinux_gather_random (NULL, 0, 0, 0); +#endif + unlock_rng (); +} + + +/* Print some statistics about the RNG. */ +void +_gcry_rngsystem_dump_stats (void) +{ + /* Not yet implemented. */ +} + + +/* This function returns true if no real RNG is available or the + quality of the RNG has been degraded for test purposes. */ +int +_gcry_rngsystem_is_faked (void) +{ + return 0; /* Faked random is not supported. */ +} + + +/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY + should be in the range of 0..100 to indicate the goodness of the + entropy added, or -1 for goodness not known. */ +gcry_error_t +_gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality) +{ + (void)buf; + (void)buflen; + (void)quality; + return 0; /* Not implemented. */ +} + + +/* Public function to fill the buffer with LENGTH bytes of + cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is + here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong + enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key + generation stuff but may be very slow. */ +void +_gcry_rngsystem_randomize (void *buffer, size_t length, + enum gcry_random_level level) +{ + _gcry_rngsystem_initialize (1); /* Auto-initialize if needed. */ + + if (level != GCRY_VERY_STRONG_RANDOM) + level = GCRY_STRONG_RANDOM; + + lock_rng (); + get_random (buffer, length, level); + unlock_rng (); +} diff --git a/plugins/MirOTR/Libgcrypt/random/random.c b/plugins/MirOTR/Libgcrypt/random/random.c index 8df87e2dfa..ff9d6d25ce 100644 --- a/plugins/MirOTR/Libgcrypt/random/random.c +++ b/plugins/MirOTR/Libgcrypt/random/random.c @@ -1,5 +1,5 @@ /* random.c - Random number switch - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2003, 2006, 2008, 2012 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -26,19 +26,35 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <time.h> +#include <sys/types.h> +#include <unistd.h> #include "g10lib.h" #include "random.h" #include "rand-internal.h" +#include "cipher.h" /* For _gcry_sha1_hash_buffer(). */ #include "ath.h" /* If not NULL a progress function called from certain places and the - opaque value passed along. Registred by + opaque value passed along. Registered by _gcry_register_random_progress (). */ static void (*progress_cb) (void *,const char*,int,int, int ); static void *progress_cb_data; +/* Flags indicating the requested RNG types. */ +static struct +{ + int standard; + int fips; + int system; +} rng_types; + + +/* This is the lock we use to protect the buffer used by the nonce + generation. */ +static ath_mutex_t nonce_buffer_lock; @@ -66,6 +82,55 @@ _gcry_random_progress (const char *what, int printchar, int current, int total) } +/* Set the preferred RNG type. This may be called at any time even + before gcry_check_version. Thus we can't assume any thread system + initialization. A type of 0 is used to indicate that any Libgcrypt + initialization has been done.*/ +void +_gcry_set_preferred_rng_type (int type) +{ + static int any_init; + + if (!type) + { + any_init = 1; + } + else if (type == GCRY_RNG_TYPE_STANDARD) + { + rng_types.standard = 1; + } + else if (any_init) + { + /* After any initialization has been done we only allow to + upgrade to the standard RNG (handled above). All other + requests are ignored. The idea is that the application needs + to declare a preference for a weaker RNG as soon as possible + and before any library sets a preference. We assume that a + library which uses Libgcrypt calls an init function very + early. This way --- even if the library gets initialized + early by the application --- it is unlikely that it can + select a lower priority RNG. + + This scheme helps to ensure that existing unmodified + applications (e.g. gpg2), which don't known about the new RNG + selection system, will continue to use the standard RNG and + not be tricked by some library to use a lower priority RNG. + There are some loopholes here but at least most GnuPG stuff + should be save because it calls src_c{gcry_control + (GCRYCTL_SUSPEND_SECMEM_WARN);} quite early and thus inhibits + switching to a low priority RNG. + */ + } + else if (type == GCRY_RNG_TYPE_FIPS) + { + rng_types.fips = 1; + } + else if (type == GCRY_RNG_TYPE_SYSTEM) + { + rng_types.system = 1; + } +} + /* Initialize this random subsystem. If FULL is false, this function merely calls the basic initialization of the module and does not do @@ -75,13 +140,74 @@ _gcry_random_progress (const char *what, int printchar, int current, int total) void _gcry_random_initialize (int full) { + static int nonce_initialized; + int err; + + if (!nonce_initialized) + { + nonce_initialized = 1; + err = ath_mutex_init (&nonce_buffer_lock); + if (err) + log_fatal ("failed to create the nonce buffer lock: %s\n", + strerror (err) ); + } + if (fips_mode ()) _gcry_rngfips_initialize (full); + else if (rng_types.standard) + _gcry_rngcsprng_initialize (full); + else if (rng_types.fips) + _gcry_rngfips_initialize (full); + else if (rng_types.system) + _gcry_rngsystem_initialize (full); else _gcry_rngcsprng_initialize (full); } +/* If possible close file descriptors used by the RNG. */ +void +_gcry_random_close_fds (void) +{ + /* Note that we can't do that directly because each random system + has its own lock functions which need to be used for accessing + the entropy gatherer. */ + + if (fips_mode ()) + _gcry_rngfips_close_fds (); + else if (rng_types.standard) + _gcry_rngcsprng_close_fds (); + else if (rng_types.fips) + _gcry_rngfips_close_fds (); + else if (rng_types.system) + _gcry_rngsystem_close_fds (); + else + _gcry_rngcsprng_close_fds (); +} + + +/* Return the current RNG type. IGNORE_FIPS_MODE is a flag used to + skip the test for FIPS. This is useful, so that we are able to + return the type of the RNG even before we have setup FIPS mode + (note that FIPS mode is enabled by default until it is switched off + by the initialization). This is mostly useful for the regression + test. */ +int +_gcry_get_rng_type (int ignore_fips_mode) +{ + if (!ignore_fips_mode && fips_mode ()) + return GCRY_RNG_TYPE_FIPS; + else if (rng_types.standard) + return GCRY_RNG_TYPE_STANDARD; + else if (rng_types.fips) + return GCRY_RNG_TYPE_FIPS; + else if (rng_types.system) + return GCRY_RNG_TYPE_SYSTEM; + else + return GCRY_RNG_TYPE_STANDARD; +} + + void _gcry_random_dump_stats (void) { @@ -92,14 +218,14 @@ _gcry_random_dump_stats (void) } -/* This function should be called during initialization and beore - intialization of this module to place the random pools into secure +/* This function should be called during initialization and before + initialization of this module to place the random pools into secure memory. */ void _gcry_secure_random_alloc (void) { if (fips_mode ()) - ; /* Not used; the fips rng is allows in secure mode. */ + ; /* Not used; the FIPS RNG is always in secure mode. */ else _gcry_rngcsprng_secure_alloc (); } @@ -154,23 +280,35 @@ _gcry_random_is_faked (void) /* Add BUFLEN bytes from BUF to the internal random pool. QUALITY should be in the range of 0..100 to indicate the goodness of the entropy added, or -1 for goodness not known. */ -gcry_error_t -gcry_random_add_bytes (const void *buf, size_t buflen, int quality) +gcry_err_code_t +_gcry_random_add_bytes (const void *buf, size_t buflen, int quality) { if (fips_mode ()) return 0; /* No need for this in fips mode. */ - else - return _gcry_rngcsprng_add_bytes (buf, buflen, quality); -} + else if (rng_types.standard) + return gpg_err_code (_gcry_rngcsprng_add_bytes (buf, buflen, quality)); + else if (rng_types.fips) + return 0; + else if (rng_types.system) + return 0; + else /* default */ + return gpg_err_code (_gcry_rngcsprng_add_bytes (buf, buflen, quality)); +} - -/* Helper function. */ + +/* Helper function. */ static void do_randomize (void *buffer, size_t length, enum gcry_random_level level) { if (fips_mode ()) _gcry_rngfips_randomize (buffer, length, level); - else + else if (rng_types.standard) + _gcry_rngcsprng_randomize (buffer, length, level); + else if (rng_types.fips) + _gcry_rngfips_randomize (buffer, length, level); + else if (rng_types.system) + _gcry_rngsystem_randomize (buffer, length, level); + else /* default */ _gcry_rngcsprng_randomize (buffer, length, level); } @@ -178,11 +316,11 @@ do_randomize (void *buffer, size_t length, enum gcry_random_level level) Returns a pointer to a newly allocated and randomized buffer of LEVEL and NBYTES length. Caller must free the buffer. */ void * -gcry_random_bytes (size_t nbytes, enum gcry_random_level level) +_gcry_random_bytes (size_t nbytes, enum gcry_random_level level) { void *buffer; - buffer = gcry_xmalloc (nbytes); + buffer = xmalloc (nbytes); do_randomize (buffer, nbytes, level); return buffer; } @@ -192,14 +330,14 @@ gcry_random_bytes (size_t nbytes, enum gcry_random_level level) this version of the function returns the random in a buffer allocated in secure memory. Caller must free the buffer. */ void * -gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) +_gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) { void *buffer; /* Historical note (1.3.0--1.4.1): The buffer was only allocated in secure memory if the pool in random-csprng.c was also set to use secure memory. */ - buffer = gcry_xmalloc_secure (nbytes); + buffer = xmalloc_secure (nbytes); do_randomize (buffer, nbytes, level); return buffer; } @@ -211,21 +349,27 @@ gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but may be very slow. */ void -gcry_randomize (void *buffer, size_t length, enum gcry_random_level level) +_gcry_randomize (void *buffer, size_t length, enum gcry_random_level level) { do_randomize (buffer, length, level); } /* This function may be used to specify the file to be used as a seed - file for the PRNG. This fucntion should be called prior to the + file for the PRNG. This function should be called prior to the initialization of the random module. NAME may not be NULL. */ void _gcry_set_random_seed_file (const char *name) { if (fips_mode ()) ; /* No need for this in fips mode. */ - else + else if (rng_types.standard) + _gcry_rngcsprng_set_seed_file (name); + else if (rng_types.fips) + ; + else if (rng_types.system) + ; + else /* default */ _gcry_rngcsprng_set_seed_file (name); } @@ -237,7 +381,13 @@ _gcry_update_random_seed_file (void) { if (fips_mode ()) ; /* No need for this in fips mode. */ - else + else if (rng_types.standard) + _gcry_rngcsprng_update_seed_file (); + else if (rng_types.fips) + ; + else if (rng_types.system) + ; + else /* default */ _gcry_rngcsprng_update_seed_file (); } @@ -245,7 +395,7 @@ _gcry_update_random_seed_file (void) /* The fast random pool function as called at some places in libgcrypt. This is merely a wrapper to make sure that this module - is initalized and to lock the pool. Note, that this function is a + is initialized and to lock the pool. Note, that this function is a NOP unless a random function has been used or _gcry_initialize (1) has been used. We use this hack so that the internal use of this function in cipher_open and md_open won't start filling up the @@ -255,7 +405,13 @@ _gcry_fast_random_poll (void) { if (fips_mode ()) ; /* No need for this in fips mode. */ - else + else if (rng_types.standard) + _gcry_rngcsprng_fast_poll (); + else if (rng_types.fips) + ; + else if (rng_types.system) + ; + else /* default */ _gcry_rngcsprng_fast_poll (); } @@ -263,12 +419,92 @@ _gcry_fast_random_poll (void) /* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ void -gcry_create_nonce (void *buffer, size_t length) +_gcry_create_nonce (void *buffer, size_t length) { + static unsigned char nonce_buffer[20+8]; + static int nonce_buffer_initialized = 0; + static volatile pid_t my_pid; /* The volatile is there to make sure the + compiler does not optimize the code away + in case the getpid function is badly + attributed. */ + volatile pid_t apid; + unsigned char *p; + size_t n; + int err; + + /* First check whether we shall use the FIPS nonce generator. This + is only done in FIPS mode, in all other modes, we use our own + nonce generator which is seeded by the RNG actual in use. */ if (fips_mode ()) - _gcry_rngfips_create_nonce (buffer, length); - else - _gcry_rngcsprng_create_nonce (buffer, length); + { + _gcry_rngfips_create_nonce (buffer, length); + return; + } + + /* This is the nonce generator, which formerly lived in + random-csprng.c. It is now used by all RNG types except when in + FIPS mode (not that this means it is also used if the FIPS RNG + has been selected but we are not in fips mode). */ + + /* Make sure we are initialized. */ + _gcry_random_initialize (1); + + /* Acquire the nonce buffer lock. */ + err = ath_mutex_lock (&nonce_buffer_lock); + if (err) + log_fatal ("failed to acquire the nonce buffer lock: %s\n", + strerror (err)); + + apid = getpid (); + /* The first time initialize our buffer. */ + if (!nonce_buffer_initialized) + { + time_t atime = time (NULL); + pid_t xpid = apid; + + my_pid = apid; + + if ((sizeof apid + sizeof atime) > sizeof nonce_buffer) + BUG (); + + /* Initialize the first 20 bytes with a reasonable value so that + a failure of gcry_randomize won't affect us too much. Don't + care about the uninitialized remaining bytes. */ + p = nonce_buffer; + memcpy (p, &xpid, sizeof xpid); + p += sizeof xpid; + memcpy (p, &atime, sizeof atime); + + /* Initialize the never changing private part of 64 bits. */ + _gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM); + + nonce_buffer_initialized = 1; + } + else if ( my_pid != apid ) + { + /* We forked. Need to reseed the buffer - doing this for the + private part should be sufficient. */ + do_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM); + /* Update the pid so that we won't run into here again and + again. */ + my_pid = apid; + } + + /* Create the nonce by hashing the entire buffer, returning the hash + and updating the first 20 bytes of the buffer with this hash. */ + for (p = buffer; length > 0; length -= n, p += n) + { + _gcry_sha1_hash_buffer (nonce_buffer, + nonce_buffer, sizeof nonce_buffer); + n = length > 20? 20 : length; + memcpy (p, nonce_buffer, n); + } + + /* Release the nonce buffer lock. */ + err = ath_mutex_unlock (&nonce_buffer_lock); + if (err) + log_fatal ("failed to release the nonce buffer lock: %s\n", + strerror (err)); } @@ -288,7 +524,7 @@ _gcry_random_selftest (selftest_report_func_t report) success the test context is stored at R_CONTEXT; on failure NULL is stored at R_CONTEXT and an error code is returned. */ gcry_err_code_t -_gcry_random_init_external_test (void **r_context, +_gcry_random_init_external_test (void **r_context, unsigned int flags, const void *key, size_t keylen, const void *seed, size_t seedlen, diff --git a/plugins/MirOTR/Libgcrypt/random/random.h b/plugins/MirOTR/Libgcrypt/random/random.h index 9075d9a3a7..2bc8cabccc 100644 --- a/plugins/MirOTR/Libgcrypt/random/random.h +++ b/plugins/MirOTR/Libgcrypt/random/random.h @@ -26,7 +26,10 @@ void _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int), void *cb_data ); +void _gcry_set_preferred_rng_type (int type); void _gcry_random_initialize (int full); +void _gcry_random_close_fds (void); +int _gcry_get_rng_type (int ignore_fips_mode); void _gcry_random_dump_stats(void); void _gcry_secure_random_alloc(void); void _gcry_enable_quick_random_gen (void); @@ -39,13 +42,13 @@ void _gcry_update_random_seed_file (void); byte *_gcry_get_random_bits( size_t nbits, int level, int secure ); void _gcry_fast_random_poll( void ); -gcry_err_code_t _gcry_random_init_external_test (void **r_context, +gcry_err_code_t _gcry_random_init_external_test (void **r_context, unsigned int flags, const void *key, size_t keylen, const void *seed, size_t seedlen, - const void *dt, + const void *dt, size_t dtlen); gcry_err_code_t _gcry_random_run_external_test (void *context, char *buffer, size_t buflen); @@ -61,12 +64,6 @@ void _gcry_daemon_initialize_basics (void); int _gcry_daemon_randomize (const char *socketname, void *buffer, size_t length, enum gcry_random_level level); -int _gcry_daemon_create_nonce (const char *socketname, - void *buffer, size_t length); #endif /*USE_RANDOM_DAEMON*/ #endif /*G10_RANDOM_H*/ - - - - diff --git a/plugins/MirOTR/Libgcrypt/random/rndegd.c b/plugins/MirOTR/Libgcrypt/random/rndegd.c index 63a5e0f162..d43fcbc14f 100644 --- a/plugins/MirOTR/Libgcrypt/random/rndegd.c +++ b/plugins/MirOTR/Libgcrypt/random/rndegd.c @@ -79,8 +79,8 @@ do_write( int fd, void *buf, size_t nbytes ) { size_t nleft = nbytes; int nwritten; - - while( nleft > 0 ) + + while( nleft > 0 ) { nwritten = write( fd, buf, nleft); if( nwritten < 0 ) @@ -105,7 +105,7 @@ do_read( int fd, void *buf, size_t nbytes ) do { n = read(fd, (char*)buf + nread, nbytes ); - } + } while( n == -1 && errno == EINTR ); if( n == -1) return nread? nread:-1; @@ -113,13 +113,13 @@ do_read( int fd, void *buf, size_t nbytes ) return -1; nread += n; nbytes -= n; - } + } while( nread < nbytes ); return nread; } -/* Note that his fucntion is not thread-safe. */ +/* Note that his function is not thread-safe. */ gpg_error_t _gcry_rndegd_set_socket_name (const char *name) { @@ -129,10 +129,10 @@ _gcry_rndegd_set_socket_name (const char *name) newname = my_make_filename (name, NULL); if (strlen (newname)+1 >= sizeof addr.sun_path) { - gcry_free (newname); + xfree (newname); return gpg_error_from_syserror (); } - gcry_free (user_socket_name); + xfree (user_socket_name); user_socket_name = newname; return 0; } @@ -177,13 +177,13 @@ _gcry_rndegd_connect_socket (int nofail) if (strlen(name)+1 >= sizeof addr.sun_path) log_fatal ("EGD socketname is too long\n"); - + memset( &addr, 0, sizeof addr ); addr.sun_family = AF_UNIX; - strcpy( addr.sun_path, name ); + strcpy( addr.sun_path, name ); addr_len = (offsetof( struct sockaddr_un, sun_path ) + strlen( addr.sun_path )); - + fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1 && !nofail) log_fatal("can't create unix domain socket: %s\n", strerror(errno) ); @@ -195,7 +195,7 @@ _gcry_rndegd_connect_socket (int nofail) close (fd); fd = -1; } - gcry_free(name); + xfree (name); if (fd != -1) egd_socket = fd; return fd; diff --git a/plugins/MirOTR/Libgcrypt/random/rndhw.c b/plugins/MirOTR/Libgcrypt/random/rndhw.c index 0961d10601..e625512d4d 100644 --- a/plugins/MirOTR/Libgcrypt/random/rndhw.c +++ b/plugins/MirOTR/Libgcrypt/random/rndhw.c @@ -1,5 +1,6 @@ /* rndhw.c - Access to the external random daemon * Copyright (C) 2007 Free Software Foundation, Inc. + * Copyright (C) 2012 Dmitry Kasatkin * * This file is part of Libgcrypt. * @@ -27,11 +28,24 @@ #undef USE_PADLOCK #ifdef ENABLE_PADLOCK_SUPPORT -# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) -# define USE_PADLOCK +# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED +# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__) +# define USE_PADLOCK 1 +# endif # endif #endif /*ENABLE_PADLOCK_SUPPORT*/ +#undef USE_DRNG +#ifdef ENABLE_DRNG_SUPPORT +# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED +# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__) +# define USE_DRNG 1 +# endif +# endif +#endif /*ENABLE_RDRAND_SUPPORT*/ + +typedef void (*add_fn_t)(const void*, size_t, enum random_origins); + /* Keep track on whether the RNG has problems. */ static volatile int rng_failed; @@ -44,7 +58,7 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), volatile char buffer[64+8] __attribute__ ((aligned (8))); volatile char *p; unsigned int nbytes, status; - + /* Peter Gutmann's cryptlib tests again whether the RNG is enabled but we don't do so. We would have to do this also for our AES implementaion and that is definitely too time consuming. There @@ -55,7 +69,17 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), nbytes = 0; while (nbytes < 64) { - asm volatile +#if defined(__x86_64__) && defined(__LP64__) + asm volatile + ("movq %1, %%rdi\n\t" /* Set buffer. */ + "xorq %%rdx, %%rdx\n\t" /* Request up to 8 bytes. */ + ".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */ + : "=a" (status) + : "g" (p) + : "%rdx", "%rdi", "cc" + ); +#else + asm volatile ("movl %1, %%edi\n\t" /* Set buffer. */ "xorl %%edx, %%edx\n\t" /* Request up to 8 bytes. */ ".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */ @@ -63,6 +87,7 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), : "g" (p) : "%edx", "%edi", "cc" ); +#endif if ((status & (1<<6)) /* RNG still enabled. */ && !(status & (1<<13)) /* von Neumann corrector is enabled. */ && !(status & (1<<14)) /* String filter is disabled. */ @@ -75,13 +100,13 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), break; /* Don't get into the loop with the fast flag set. */ p += (status & 0x1f); } - else + else { /* If there was an error we need to break the loop and record that there is something wrong with the padlock RNG. */ rng_failed = 1; - break; + break; } } @@ -95,6 +120,56 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), #endif /*USE_PADLOCK*/ +#ifdef USE_DRNG +# define RDRAND_RETRY_LOOPS 10 +# define RDRAND_INT ".byte 0x0f,0xc7,0xf0" +# if defined(__x86_64__) && defined(__LP64__) +# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0" +# else +# define RDRAND_LONG RDRAND_INT +# endif +static inline int +rdrand_long (unsigned long *v) +{ + int ok; + asm volatile ("1: " RDRAND_LONG "\n\t" + "jc 2f\n\t" + "decl %0\n\t" + "jnz 1b\n\t" + "2:" + : "=r" (ok), "=a" (*v) + : "0" (RDRAND_RETRY_LOOPS) + : "cc"); + return ok; +} + + +static inline int +rdrand_nlong (unsigned long *v, int count) +{ + while (count--) + if (!rdrand_long(v++)) + return 0; + return 1; +} + + +static size_t +poll_drng (add_fn_t add, enum random_origins origin, int fast) +{ + volatile char buffer[64] __attribute__ ((aligned (8))); + unsigned int nbytes = sizeof (buffer); + + (void)fast; + + if (!rdrand_nlong ((unsigned long *)buffer, sizeof(buffer)/sizeof(long))) + return 0; + (*add)((void *)buffer, nbytes, origin); + return nbytes; +} +#endif /*USE_DRNG*/ + + int _gcry_rndhw_failed_p (void) { @@ -111,10 +186,14 @@ _gcry_rndhw_poll_fast (void (*add)(const void*, size_t, enum random_origins), (void)add; (void)origin; +#ifdef USE_DRNG + if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND)) + poll_drng (add, origin, 1); +#endif #ifdef USE_PADLOCK if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG)) poll_padlock (add, origin, 1); -#endif +#endif } @@ -129,10 +208,14 @@ _gcry_rndhw_poll_slow (void (*add)(const void*, size_t, enum random_origins), (void)add; (void)origin; +#ifdef USE_DRNG + if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND)) + nbytes += poll_drng (add, origin, 0); +#endif #ifdef USE_PADLOCK if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG)) nbytes += poll_padlock (add, origin, 0); -#endif +#endif return nbytes; } diff --git a/plugins/MirOTR/Libgcrypt/random/rndlinux.c b/plugins/MirOTR/Libgcrypt/random/rndlinux.c index 574ef6dcc0..9eeec57465 100644 --- a/plugins/MirOTR/Libgcrypt/random/rndlinux.c +++ b/plugins/MirOTR/Libgcrypt/random/rndlinux.c @@ -1,5 +1,6 @@ /* rndlinux.c - raw random number for OSes with /dev/random - * Copyright (C) 1998, 2001, 2002, 2003, 2007 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003, 2007, + * 2009 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -35,7 +36,7 @@ #include "g10lib.h" #include "rand-internal.h" -static int open_device ( const char *name ); +static int open_device (const char *name, int retry); static int @@ -53,15 +54,30 @@ set_cloexec_flag (int fd) /* - * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists)). + * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it + * exists)). If RETRY is true, the function does not terminate with + * a fatal error but retries until it is able to reopen the device. */ static int -open_device ( const char *name ) +open_device (const char *name, int retry) { int fd; - fd = open ( name, O_RDONLY ); - if ( fd == -1 ) + if (retry) + _gcry_random_progress ("open_dev_random", 'X', 1, 0); + again: + fd = open (name, O_RDONLY); + if (fd == -1 && retry) + { + struct timeval tv; + + tv.tv_sec = 5; + tv.tv_usec = 0; + _gcry_random_progress ("wait_dev_random", 'X', 0, (int)tv.tv_sec); + select (0, NULL, NULL, NULL, &tv); + goto again; + } + if (fd == -1) log_fatal ("can't open %s: %s\n", name, strerror(errno) ); if (set_cloexec_flag (fd)) @@ -70,8 +86,8 @@ open_device ( const char *name ) /* We used to do the following check, however it turned out that this is not portable since more OSes provide a random device which is - sometimes implemented as another device type. - + sometimes implemented as another device type. + struct stat sb; if( fstat( fd, &sb ) ) @@ -83,6 +99,10 @@ open_device ( const char *name ) } +/* Note that the caller needs to make sure that this function is only + called by one thread at a time. The function returns 0 on success + or true on failure (in which case the caller will signal a fatal + error). */ int _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, enum random_origins), @@ -91,11 +111,32 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, { static int fd_urandom = -1; static int fd_random = -1; + static unsigned char ever_opened; int fd; int n; - int warn=0; byte buffer[768]; size_t n_hw; + size_t want = length; + size_t last_so_far = 0; + int any_need_entropy = 0; + int delay; + + if (!add) + { + /* Special mode to close the descriptors. */ + if (fd_random != -1) + { + close (fd_random); + fd_random = -1; + } + if (fd_urandom != -1) + { + close (fd_urandom); + fd_urandom = -1; + } + return 0; + } + /* First read from a hardware source. However let it account only for up to 50% of the requested bytes. */ @@ -105,63 +146,106 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, if (length > 1) length -= n_hw; - /* Open the requested device. */ + /* Open the requested device. The first time a device is to be + opened we fail with a fatal error if the device does not exists. + In case the device has ever been closed, further open requests + will however retry indefinitely. The rationale for this behaviour is + that we always require the device to be existent but want a more + graceful behaviour if the rarely needed close operation has been + used and the device needs to be re-opened later. */ if (level >= 2) { - if( fd_random == -1 ) - fd_random = open_device ( NAME_OF_DEV_RANDOM ); + if (fd_random == -1) + { + fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1)); + ever_opened |= 1; + } fd = fd_random; } else { - if( fd_urandom == -1 ) - fd_urandom = open_device ( NAME_OF_DEV_URANDOM ); + if (fd_urandom == -1) + { + fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2)); + ever_opened |= 2; + } fd = fd_urandom; } - /* And enter the read loop. */ + /* Enter the read loop. */ + delay = 0; /* Start with 0 seconds so that we do no block on the + first iteration and in turn call the progress function + before blocking. To give the OS a better chance to + return with something we will actually use 100ms. */ while (length) { fd_set rfds; struct timeval tv; int rc; - - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - tv.tv_sec = 3; - tv.tv_usec = 0; - if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) + + /* If we collected some bytes update the progress indicator. We + do this always and not just if the select timed out because + often just a few bytes are gathered within the timeout + period. */ + if (any_need_entropy || last_so_far != (want - length) ) + { + last_so_far = want - length; + _gcry_random_progress ("need_entropy", 'X', + (int)last_so_far, (int)want); + any_need_entropy = 1; + } + + /* If the system has no limit on the number of file descriptors + and we encounter an fd which is larger than the fd_set size, + we don't use the select at all. The select code is only used + to emit progress messages. A better solution would be to + fall back to poll() if available. */ +#ifdef FD_SETSIZE + if (fd < FD_SETSIZE) +#endif { - if( !warn ) + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + tv.tv_sec = delay; + tv.tv_usec = delay? 0 : 100000; + if ( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) { - _gcry_random_progress ("need_entropy", 'X', 0, (int)length); - warn = 1; - } - continue; - } - else if( rc == -1 ) - { - log_error ("select() error: %s\n", strerror(errno)); - continue; - } - - do - { - int nbytes = length < sizeof(buffer)? length : sizeof(buffer); - n = read(fd, buffer, nbytes ); - if( n >= 0 && n > nbytes ) - { - log_error("bogus read from random device (n=%d)\n", n ); - n = nbytes; - } - } - while( n == -1 && errno == EINTR ); - if( n == -1 ) - log_fatal("read error on random device: %s\n", strerror(errno)); - (*add)( buffer, n, origin ); - length -= n; + any_need_entropy = 1; + delay = 3; /* Use 3 seconds henceforth. */ + continue; + } + else if( rc == -1 ) + { + log_error ("select() error: %s\n", strerror(errno)); + if (!delay) + delay = 1; /* Use 1 second if we encounter an error before + we have ever blocked. */ + continue; + } + } + + do + { + size_t nbytes; + + nbytes = length < sizeof(buffer)? length : sizeof(buffer); + n = read (fd, buffer, nbytes); + if (n >= 0 && n > nbytes) + { + log_error("bogus read from random device (n=%d)\n", n ); + n = nbytes; + } + } + while (n == -1 && errno == EINTR); + if (n == -1) + log_fatal("read error on random device: %s\n", strerror(errno)); + (*add)(buffer, n, origin); + length -= n; } - memset(buffer, 0, sizeof(buffer) ); + wipememory (buffer, sizeof buffer); + + if (any_need_entropy) + _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want); return 0; /* success */ } diff --git a/plugins/MirOTR/Libgcrypt/random/rndunix.c b/plugins/MirOTR/Libgcrypt/random/rndunix.c index 1faf9abc0e..1b810d72ae 100644 --- a/plugins/MirOTR/Libgcrypt/random/rndunix.c +++ b/plugins/MirOTR/Libgcrypt/random/rndunix.c @@ -51,32 +51,32 @@ Subject: Re: LGPL for the windows entropy gatherer To: wk@gnupg.org Date: Wed, 22 Aug 2007 03:05:42 +1200 - + Hi, - + >As of now libgcrypt is GPL under Windows due to that module and some people >would really like to see it under LGPL too. Can you do such a license change >to LGPL version 2? Note that LGPL give the user the option to relicense it >under GPL, so the change would be pretty easy and backwar compatible. - + Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy code as well, but Ian asked for LGPL as an option so as of the next release I'll have LGPL in there. You can consider it to be retroactive, so your current version will be LGPLd as well. - + Peter. ========== From: pgut001 <pgut001@cs.auckland.ac.nz> Subject: Re: LGPL for the windows entropy gatherer To: wk@gnupg.org Date: Wed, 22 Aug 2007 20:50:08 +1200 - + >Would you mind to extend this also to the Unix entropy gatherer which is >still used on systems without /dev/random and when EGD is not installed? That >would be the last GPLed piece in Libgcrypt. - + Sure, it covers the entire entropy-gathering subsystem. - + Peter. ========= */ @@ -207,7 +207,7 @@ * '1024 / SC_0' */ #define SC( weight ) ( 1024 / weight ) /* Scale factor */ -#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */ +#define SC_0 16384 /* SC( SC_0 ) evaluates to 0 */ static struct RI { const char *path; /* Path to check for existence of source */ @@ -325,10 +325,10 @@ static struct RI { /* This is a complex and screwball program. Some systems have things * like rX_dmn, x = integer, for RAID systems, but the statistics are * pretty dodgy */ -#ifdef __QNXNTO__ +#ifdef __QNXNTO__ { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3), NULL, 0, 0, 0, 0 }, -#endif +#endif #if 0 /* The following aren't enabled since they're somewhat slow and not very * unpredictable, however they give an indication of the sort of sources @@ -521,7 +521,10 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) int maxFD = 0; #endif /* OS-specific brokenness */ int bufPos, i, usefulness = 0; - + int last_so_far = 0; + int any_need_entropy = 0; + int delay; + int rc; /* Fire up each randomness source */ FD_ZERO(&fds); @@ -548,7 +551,8 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) #else #error O_NONBLOCK is missing #endif - + /* FIXME: We need to make sure that the fd is less than + FD_SETSIZE. */ FD_SET(dataSources[i].pipeFD, &fds); dataSources[i].length = 0; @@ -566,21 +570,40 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) /* Suck all the data we can get from each of the sources */ bufPos = 0; moreSources = 1; + delay = 0; /* Return immediately (well, after 100ms) the first time. */ while (moreSources && bufPos <= gather_buffer_size) { /* Wait for data to become available from any of the sources, with a * timeout of 10 seconds. This adds even more randomness since data * becomes available in a nondeterministic fashion. Kudos to HP's QA * department for managing to ship a select() which breaks its own * prototype */ - tv.tv_sec = 10; - tv.tv_usec = 0; + tv.tv_sec = delay; + tv.tv_usec = delay? 0 : 100000; #if defined( __hpux ) && ( OS_VERSION == 9 ) - if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) + rc = select(maxFD + 1, (int *)&fds, NULL, NULL, &tv); #else /* */ - if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) + rc = select(maxFD + 1, &fds, NULL, NULL, &tv); #endif /* __hpux */ - break; + if (rc == -1) + break; /* Ooops; select failed. */ + + if (!rc) + { + /* FIXME: Because we run several tools at once it is + unlikely that we will see a block in select at all. */ + if (!any_need_entropy + || last_so_far != (gather_buffer_size - bufPos) ) + { + last_so_far = gather_buffer_size - bufPos; + _gcry_random_progress ("need_entropy", 'X', + last_so_far, + gather_buffer_size); + any_need_entropy = 1; + } + delay = 10; /* Use 10 seconds henceforth. */ + /* Note that the fd_set is setup again at the end of this loop. */ + } /* One of the sources has data available, read it into the buffer */ for (i = 0; dataSources[i].path != NULL; i++) { @@ -661,6 +684,11 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) } } + if (any_need_entropy) + _gcry_random_progress ("need_entropy", 'X', + gather_buffer_size, + gather_buffer_size); + if( dbgfp ) { fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); fflush(dbgfp); diff --git a/plugins/MirOTR/Libgcrypt/random/rndw32.c b/plugins/MirOTR/Libgcrypt/random/rndw32.c index 56422a4242..c495131de8 100644 --- a/plugins/MirOTR/Libgcrypt/random/rndw32.c +++ b/plugins/MirOTR/Libgcrypt/random/rndw32.c @@ -1,5 +1,6 @@ /* rndw32.c - W32 entropy gatherer - * Copyright (C) 1999, 2000, 2002, 2003, 2007 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2002, 2003, 2007, + * 2010 Free Software Foundation, Inc. * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006 * * This file is part of Libgcrypt. @@ -73,7 +74,7 @@ #include <stdlib.h> #include <errno.h> #include <string.h> -#ifdef __GNUC__ +#ifdef __GNUC__ #include <stdint.h> #endif @@ -141,22 +142,22 @@ typedef DWORD (WINAPI *NTPOWERINFORMATION) /* Type definitions for function pointers to call CryptoAPI functions. */ typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv, LPCTSTR pszContainer, - LPCTSTR pszProvider, + LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags); typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags); -/* Somewhat alternative functionality available as a direct call, for +/* Somewhat alternative functionality available as a direct call, for Windows XP and newer. This is the CryptoAPI RNG, which isn't anywhere near as good as the HW RNG, but we use it if it's present on the basis - that at least it can't make things any worse. This direct access version + that at least it can't make things any worse. This direct access version is only available under Windows XP, we don't go out of our way to access - the more general CryptoAPI one since the main purpose of using it is to - take advantage of any possible future hardware RNGs that may be added, + the more general CryptoAPI one since the main purpose of using it is to + take advantage of any possible future hardware RNGs that may be added, for example via TCPA devices. */ -typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer, +typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer, ULONG RandomBufferLength); @@ -167,13 +168,13 @@ typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer, #define SMBType char #define SensorType char -typedef struct +typedef struct { SensorType iType; /* Type of sensor. */ int Count; /* Number of sensor for that type. */ } SharedIndex; -typedef struct +typedef struct { SensorType ssType; /* Type of sensor */ unsigned char ssName[12]; /* Name of sensor */ @@ -252,33 +253,33 @@ static int system_is_w2000; /* True if running on W2000. */ /* Try and connect to the system RNG if there's one present. */ -static void +static void init_system_rng (void) { system_rng_available = 0; hRNGProv = NULL; - hAdvAPI32 = GetModuleHandleA("AdvAPI32.dll"); + hAdvAPI32 = GetModuleHandle ("AdvAPI32.dll"); if (!hAdvAPI32) return; pCryptAcquireContext = (CRYPTACQUIRECONTEXT) - GetProcAddress(hAdvAPI32, "CryptAcquireContextA"); + GetProcAddress (hAdvAPI32, "CryptAcquireContextA"); pCryptGenRandom = (CRYPTGENRANDOM) - GetProcAddress(hAdvAPI32, "CryptGenRandom"); + GetProcAddress (hAdvAPI32, "CryptGenRandom"); pCryptReleaseContext = (CRYPTRELEASECONTEXT) - GetProcAddress(hAdvAPI32, "CryptReleaseContext"); - - /* Get a pointer to the native randomness function if it's available. + GetProcAddress (hAdvAPI32, "CryptReleaseContext"); + + /* Get a pointer to the native randomness function if it's available. This isn't exported by name, so we have to get it by ordinal. */ pRtlGenRandom = (RTLGENRANDOM) GetProcAddress (hAdvAPI32, "SystemFunction036"); - /* Try and connect to the PIII RNG CSP. The AMD 768 southbridge (from - the 760 MP chipset) also has a hardware RNG, but there doesn't appear - to be any driver support for this as there is for the Intel RNG so we - can't do much with it. OTOH the Intel RNG is also effectively dead - as well, mostly due to virtually nonexistant support/marketing by + /* Try and connect to the PIII RNG CSP. The AMD 768 southbridge (from + the 760 MP chipset) also has a hardware RNG, but there doesn't appear + to be any driver support for this as there is for the Intel RNG so we + can't do much with it. OTOH the Intel RNG is also effectively dead + as well, mostly due to virtually nonexistent support/marketing by Intel, it's included here mostly for form's sake. */ if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext || !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV, @@ -293,7 +294,7 @@ init_system_rng (void) /* Read data from the system RNG if availavle. */ -static void +static void read_system_rng (void (*add)(const void*, size_t, enum random_origins), enum random_origins requester) { @@ -330,13 +331,13 @@ read_system_rng (void (*add)(const void*, size_t, enum random_origins), /* Read data from MBM. This communicates via shared memory, so all we need to do is map a file and read the data out. */ static void -read_mbm_data (void (*add)(const void*, size_t, enum random_origins), +read_mbm_data (void (*add)(const void*, size_t, enum random_origins), enum random_origins requester) { HANDLE hMBMData; SharedData *mbmDataPtr; - hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, _T("$M$B$M$5$S$D$")); + hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, "$M$B$M$5$S$D$" ); if (hMBMData) { mbmDataPtr = (SharedData*)MapViewOfFile (hMBMData, FILE_MAP_READ,0,0,0); @@ -344,7 +345,7 @@ read_mbm_data (void (*add)(const void*, size_t, enum random_origins), { if (debug_me) log_debug ("rndw32#read_mbm_data: got %d bytes\n", - sizeof (SharedData)); + (int)sizeof (SharedData)); (*add) (mbmDataPtr, sizeof (SharedData), requester); UnmapViewOfFile (mbmDataPtr); } @@ -355,7 +356,7 @@ read_mbm_data (void (*add)(const void*, size_t, enum random_origins), /* Fallback method using the registry to poll the statistics. */ static void -registry_poll (void (*add)(const void*, size_t, enum random_origins), +registry_poll (void (*add)(const void*, size_t, enum random_origins), enum random_origins requester) { static int cbPerfData = PERFORMANCE_BUFFER_SIZE; @@ -418,45 +419,58 @@ registry_poll (void (*add)(const void*, size_t, enum random_origins), this can consume tens of MB of memory and huge amounts of CPU time while it gathers its data, and even running once can still consume about 1/2MB of memory */ - pPerfData = gcry_xmalloc (cbPerfData); - for (iterations=0; iterations < 10; iterations++) + if (getenv ("GNUPG_RNDW32_NOPERF")) { - dwSize = cbPerfData; - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: get perf data\n" ); + static int shown; - status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, _T("Global"), NULL, - NULL, (LPBYTE) pPerfData, &dwSize); - if (status == ERROR_SUCCESS) + if (!shown) { - if (!memcmp (pPerfData->Signature, L"PERF", 8)) - (*add) ( pPerfData, dwSize, requester ); - else - log_debug ("rndw32: no PERF signature\n"); - break; + shown = 1; + log_info ("note: get performance data has been disabled\n"); } - else if (status == ERROR_MORE_DATA) - { - cbPerfData += PERFORMANCE_BUFFER_STEP; - pPerfData = gcry_xrealloc (pPerfData, cbPerfData); - } - else + } + else + { + pPerfData = xmalloc (cbPerfData); + for (iterations=0; iterations < 10; iterations++) { - static int been_here; + dwSize = cbPerfData; + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: get perf data\n" ); - /* Silence the error message. In particular under Wine (as - of 2008) we would get swamped with such diagnotiscs. One - such diagnotiscs should be enough. */ - if (been_here != status) + status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL, + NULL, (LPBYTE) pPerfData, &dwSize); + if (status == ERROR_SUCCESS) { - been_here = status; - log_debug ("rndw32: get performance data problem: ec=%ld\n", - status); + if (!memcmp (pPerfData->Signature, L"PERF", 8)) + (*add) ( pPerfData, dwSize, requester ); + else + log_debug ("rndw32: no PERF signature\n"); + break; + } + else if (status == ERROR_MORE_DATA) + { + cbPerfData += PERFORMANCE_BUFFER_STEP; + pPerfData = xrealloc (pPerfData, cbPerfData); + } + else + { + static int been_here; + + /* Silence the error message. In particular under Wine (as + of 2008) we would get swamped with such diagnotiscs. One + such diagnotiscs should be enough. */ + if (been_here != status) + { + been_here = status; + log_debug ("rndw32: get performance data problem: ec=%ld\n", + status); + } + break; } - break; } + xfree (pPerfData); } - gcry_free (pPerfData); /* Although this isn't documented in the Win32 API docs, it's necessary to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's @@ -468,7 +482,7 @@ registry_poll (void (*add)(const void*, size_t, enum random_origins), static void -slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), +slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), enum random_origins requester ) { static int is_initialized = 0; @@ -488,7 +502,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), log_debug ("rndw32#slow_gatherer: init toolkit\n" ); /* Find out whether this is an NT server or workstation if necessary */ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - _T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), + "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { BYTE szValue[32 + 8]; @@ -497,9 +511,9 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), if ( debug_me ) log_debug ("rndw32#slow_gatherer: check product options\n" ); - status = RegQueryValueEx (hKey, _T("ProductType"), 0, NULL, + status = RegQueryValueEx (hKey, "ProductType", 0, NULL, szValue, &dwSize); - if (status == ERROR_SUCCESS && _stricmp (szValue, "WinNT")) + if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) { /* Note: There are (at least) three cases for ProductType: WinNT = NT Workstation, ServerNT = NT Server, LanmanNT = @@ -516,7 +530,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), /* readPnPData (); - we have not implemented that. */ /* Initialize the NetAPI32 function pointers if necessary */ - hNetAPI32 = LoadLibraryA("NETAPI32.DLL"); + hNetAPI32 = LoadLibrary ("NETAPI32.DLL"); if (hNetAPI32) { if (debug_me) @@ -537,7 +551,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), } /* Initialize the NT kernel native API function pointers if necessary */ - hNTAPI = GetModuleHandleA("NTDll.dll"); + hNTAPI = GetModuleHandle ("NTDll.dll"); if (hNTAPI) { /* Get a pointer to the NT native information query functions */ @@ -555,10 +569,10 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), is_initialized = 1; } - + read_system_rng ( add, requester ); read_mbm_data ( add, requester ); - + /* Get network statistics. Note: Both NT Workstation and NT Server by default will be running both the workstation and server services. The heuristic below is probably useful though on the assumption that the @@ -566,7 +580,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), In any case the network statistics return almost no randomness. */ { LPBYTE lpBuffer; - + if (hNetAPI32 && !pNetStatisticsGet (NULL, is_workstation ? L"LanmanWorkstation" : @@ -586,15 +600,15 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), { char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8]; char szDevice[50]; - + /* Check whether we can access this device. */ snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d", drive_no); - hDevice = CreateFileA(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, + hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) break; /* No more drives. */ - + /* Note: This only works if you have turned on the disk performance counters with 'diskperf -y'. These counters are off by default. */ dwSize = sizeof diskPerformance; @@ -641,7 +655,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), This scan typically yields around 20 pieces of data, there's nothing in the range 65...128 so chances are there won't be anything above there either. */ - buffer = gcry_xmalloc (PERFORMANCE_BUFFER_SIZE); + buffer = xmalloc (PERFORMANCE_BUFFER_SIZE); for (dwType = 0; dwType < 64; dwType++) { switch (dwType) @@ -745,7 +759,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), } gcry_assert (i < 100); } - gcry_free (buffer); + xfree (buffer); /* We couldn't get enough results from the kernel, fall back to the somewhat troublesome registry poll. */ @@ -775,7 +789,7 @@ _gcry_rndw32_gather_random (void (*add)(const void*, size_t, OSVERSIONINFO osvi = { sizeof( osvi ) }; GetVersionEx( &osvi ); - if ( osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) + if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) log_fatal ("can only run on a Windows NT platform\n" ); system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0); init_system_rng (); @@ -874,7 +888,7 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, { HANDLE handle; FILETIME creationTime, exitTime, kernelTime, userTime; - SIZE_T minimumWorkingSetSize, maximumWorkingSetSize; + DWORD minimumWorkingSetSize, maximumWorkingSetSize; handle = GetCurrentThread (); GetThreadTimes (handle, &creationTime, &exitTime, @@ -936,7 +950,7 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, shouldn't really be a problem. Under WinCE it's completely platform- dependant, if there's no hardware performance counter available, it uses the 1ms system timer. - + Another feature of the TSC (although it doesn't really affect us here) is that mobile CPUs will turn off the TSC when they idle, Pentiums will change the rate of the counter when they clock-throttle (to @@ -944,11 +958,11 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, it off when both threads are idle (this more or less makes sense, since the CPU will be in the halted state and not executing any instructions to count). - + To make things unambiguous, we detect a CPU new enough to call RDTSC directly by checking for CPUID capabilities, and fall back to QPC if this isn't present. */ -#ifdef __GNUC__ +#ifdef __GNUC__ /* FIXME: We would need to implement the CPU feature tests first. */ /* if (cpu_has_feature_rdtsc) */ /* { */ @@ -962,7 +976,7 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, #endif /*!__GNUC__*/ { LARGE_INTEGER performanceCount; - + if (QueryPerformanceCounter (&performanceCount)) { if ( debug_me ) diff --git a/plugins/MirOTR/Libgcrypt/random/rndw32ce.c b/plugins/MirOTR/Libgcrypt/random/rndw32ce.c new file mode 100644 index 0000000000..b485eef2f5 --- /dev/null +++ b/plugins/MirOTR/Libgcrypt/random/rndw32ce.c @@ -0,0 +1,199 @@ +/* rndw32ce.c - W32CE entropy gatherer + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <stdint.h> + +#include <windows.h> +#include <wincrypt.h> + +#include "types.h" +#include "g10lib.h" +#include "rand-internal.h" + + +/* The Microsoft docs say that it is suggested to see the buffer with + some extra random. We do this, despite that it is a questionable + suggestion as the OS as better means of collecting entropy than an + application. */ +static size_t filler_used; +static size_t filler_length; +static unsigned char *filler_buffer; + +static void +filler (const void *data, size_t datalen, enum random_origins dummy) +{ + (void)dummy; + if (filler_used + datalen > filler_length) + datalen = filler_length - filler_used; + memcpy (filler_buffer + filler_used, data, datalen); + filler_used += datalen; +} + + +static void +fillup_buffer (unsigned char *buffer, size_t length) +{ + filler_used = 0; + filler_length = length; + filler_buffer = buffer; + + while (filler_used < length) + _gcry_rndw32ce_gather_random_fast (filler, 0); +} + + +int +_gcry_rndw32ce_gather_random (void (*add)(const void*, size_t, + enum random_origins), + enum random_origins origin, + size_t length, int level ) +{ + HCRYPTPROV prov; + unsigned char buffer [256]; + DWORD buflen; + + if (!level) + return 0; + + /* Note that LENGTH is not really important because the caller + checks the returned lengths and calls this function until it + feels that enough entropy has been gathered. */ + + buflen = sizeof buffer; + if (length+8 < buflen) + buflen = length+8; /* Return a bit more than requested. */ + + if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) ) + log_debug ("CryptAcquireContext failed: rc=%d\n", (int)GetLastError ()); + else + { + fillup_buffer (buffer, buflen); + if (!CryptGenRandom (prov, buflen, buffer)) + log_debug ("CryptGenRandom(%d) failed: rc=%d\n", + (int)buflen, (int)GetLastError ()); + else + (*add) (buffer, buflen, origin); + CryptReleaseContext (prov, 0); + wipememory (buffer, sizeof buffer); + } + + return 0; +} + + + +void +_gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t, + enum random_origins), + enum random_origins origin) +{ + + /* Add word sized values. */ + { +# define ADD(t,f) do { \ + t along = (f); \ + memcpy (bufptr, &along, sizeof (along)); \ + bufptr += sizeof (along); \ + } while (0) + unsigned char buffer[20*sizeof(ulong)], *bufptr; + + bufptr = buffer; + ADD (HWND, GetActiveWindow ()); + ADD (HWND, GetCapture ()); + ADD (HWND, GetClipboardOwner ()); + ADD (HANDLE, GetCurrentProcess ()); + ADD (DWORD, GetCurrentProcessId ()); + ADD (HANDLE, GetCurrentThread ()); + ADD (DWORD, GetCurrentThreadId ()); + ADD (HWND, GetDesktopWindow ()); + ADD (HWND, GetFocus ()); + ADD (DWORD, GetMessagePos ()); + ADD (HWND, GetOpenClipboardWindow ()); + ADD (HWND, GetProcessHeap ()); + ADD (DWORD, GetQueueStatus (QS_ALLEVENTS)); + ADD (DWORD, GetTickCount ()); + + gcry_assert ( bufptr-buffer < sizeof (buffer) ); + (*add) ( buffer, bufptr-buffer, origin ); +# undef ADD + } + + /* Get multiword system information: Current caret position, current + mouse cursor position. */ + { + POINT point; + + GetCaretPos (&point); + (*add) ( &point, sizeof (point), origin ); + GetCursorPos (&point); + (*add) ( &point, sizeof (point), origin ); + } + + /* Get percent of memory in use, bytes of physical memory, bytes of + free physical memory, bytes in paging file, free bytes in paging + file, user bytes of address space, and free user bytes. */ + { + MEMORYSTATUS memoryStatus; + + memoryStatus.dwLength = sizeof (MEMORYSTATUS); + GlobalMemoryStatus (&memoryStatus); + (*add) ( &memoryStatus, sizeof (memoryStatus), origin ); + } + + + /* Get thread and process creation time, exit time, time in kernel + mode, and time in user mode in 100ns intervals. */ + { + HANDLE handle; + FILETIME creationTime, exitTime, kernelTime, userTime; + + handle = GetCurrentThread (); + GetThreadTimes (handle, &creationTime, &exitTime, + &kernelTime, &userTime); + (*add) ( &creationTime, sizeof (creationTime), origin ); + (*add) ( &exitTime, sizeof (exitTime), origin ); + (*add) ( &kernelTime, sizeof (kernelTime), origin ); + (*add) ( &userTime, sizeof (userTime), origin ); + + handle = GetCurrentThread (); + GetThreadTimes (handle, &creationTime, &exitTime, + &kernelTime, &userTime); + (*add) ( &creationTime, sizeof (creationTime), origin ); + (*add) ( &exitTime, sizeof (exitTime), origin ); + (*add) ( &kernelTime, sizeof (kernelTime), origin ); + (*add) ( &userTime, sizeof (userTime), origin ); + + } + + + /* In case the OEM provides a high precision timer get this. If + none is available the default implementation returns the + GetTickCount. */ + { + LARGE_INTEGER performanceCount; + + if (QueryPerformanceCounter (&performanceCount)) + (*add) (&performanceCount, sizeof (performanceCount), origin); + } + +} |