diff options
| author | René Schümann <white06tiger@gmail.com> | 2015-03-14 19:56:55 +0000 |
|---|---|---|
| committer | René Schümann <white06tiger@gmail.com> | 2015-03-14 19:56:55 +0000 |
| commit | c60aed5432e9cda277b9351de51e82dfb8e02475 (patch) | |
| tree | 97ccd1ea8e2544f6a9673ee7d04c18b714877a35 /plugins/MirOTR/libgcrypt-1.4.6/random | |
| parent | d2b26b1f86326362f56540b5185fa09ab5f2779c (diff) | |
MirOTR: part one of many file/folder structure changes
git-svn-id: http://svn.miranda-ng.org/main/trunk@12402 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirOTR/libgcrypt-1.4.6/random')
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/rand-internal.h | 137 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/random-csprng.c | 1397 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/random-daemon.c | 360 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/random-fips.c | 1118 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/random.c | 323 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/random.h | 72 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/rndegd.c | 290 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/rndhw.c | 138 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/rndlinux.c | 167 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/rndunix.c | 883 | ||||
| -rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/random/rndw32.c | 981 |
11 files changed, 0 insertions, 5866 deletions
diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/rand-internal.h b/plugins/MirOTR/libgcrypt-1.4.6/random/rand-internal.h deleted file mode 100644 index 534d8284e5..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/rand-internal.h +++ /dev/null @@ -1,137 +0,0 @@ -/* rand-internal.h - header to glue the random functions - * Copyright (C) 1998, 2002 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/>. - */ - -#ifndef G10_RAND_INTERNAL_H -#define G10_RAND_INTERNAL_H - -#include "../src/cipher-proto.h" - -/* 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 - { - RANDOM_ORIGIN_INIT = 0, /* Used only for initialization. */ - RANDOM_ORIGIN_EXTERNAL = 1, /* Added from an external source. */ - RANDOM_ORIGIN_FASTPOLL = 2, /* Fast random poll function. */ - RANDOM_ORIGIN_SLOWPOLL = 3, /* Slow poll function. */ - RANDOM_ORIGIN_EXTRAPOLL = 4 /* Used to mark an extra pool seed - due to a GCRY_VERY_STRONG_RANDOM - random request. */ - }; - - - -/*-- random.c --*/ -void _gcry_random_progress (const char *what, int printchar, - int current, int total); - - -/*-- random-csprng.c --*/ -void _gcry_rngcsprng_initialize (int full); -void _gcry_rngcsprng_dump_stats (void); -void _gcry_rngcsprng_secure_alloc (void); -void _gcry_rngcsprng_enable_quick_gen (void); -void _gcry_rngcsprng_set_daemon_socket (const char *socketname); -int _gcry_rngcsprng_use_daemon (int onoff); -int _gcry_rngcsprng_is_faked (void); -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, - 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 --*/ -void _gcry_rngfips_initialize (int full); -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); - -gcry_error_t _gcry_rngfips_selftest (selftest_report_func_t report); - -gcry_err_code_t _gcry_rngfips_init_external_test (void **r_context, - unsigned int flags, - const void *key, - size_t keylen, - const void *seed, - size_t seedlen, - const void *dt, - size_t dtlen); -gcry_err_code_t _gcry_rngfips_run_external_test (void *context, - char *buffer, size_t buflen); -void _gcry_rngfips_deinit_external_test (void *context); - - - - - -/*-- rndlinux.c --*/ -int _gcry_rndlinux_gather_random (void (*add) (const void *, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level); - -/*-- rndunix.c --*/ -int _gcry_rndunix_gather_random (void (*add) (const void *, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level); - -/*-- rndelg.c --*/ -int _gcry_rndegd_gather_random (void (*add) (const void *, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level); -int _gcry_rndegd_connect_socket (int nofail); - -/*-- rndw32.c --*/ -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, - 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, - enum random_origins), - enum random_origins origin); -size_t _gcry_rndhw_poll_slow (void (*add)(const void*, size_t, - enum random_origins), - enum random_origins origin); - - - -#endif /*G10_RAND_INTERNAL_H*/ diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/random-csprng.c b/plugins/MirOTR/libgcrypt-1.4.6/random/random-csprng.c deleted file mode 100644 index ccb90ee863..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/random-csprng.c +++ /dev/null @@ -1,1397 +0,0 @@ -/* 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. - * - * 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 random number generator is modelled after the one described in - Peter Gutmann's 1998 Usenix Security Symposium paper: "Software - Generation of Practically Strong Random Numbers". See also chapter - 6 in his book "Cryptographic Security Architecture", New York, - 2004, ISBN 0-387-95387-6. - - Note that the acronym CSPRNG stands for "Continuously Seeded - PseudoRandom Number Generator" as used in Peter's implementation of - the paper and not only for "Cryptographically Secure PseudoRandom - Number Generator". - */ - - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <time.h> -#ifdef HAVE_GETHRTIME -#include <sys/times.h> -#endif -#ifdef HAVE_GETTIMEOFDAY -#include <sys/time.h> -#endif -#ifdef HAVE_GETRUSAGE -#include <sys/resource.h> -#endif -#ifdef __MINGW32__ -#include <process.h> -#endif -#include "g10lib.h" -#include "../cipher/rmd.h" -#include "random.h" -#include "rand-internal.h" -#include "cipher.h" /* Required for the rmd160_hash_buffer() prototype. */ -#include "ath.h" - -#ifndef RAND_MAX /* For SunOS. */ -#define RAND_MAX 32767 -#endif - -/* Check whether we can lock the seed file read write. */ -#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM) -#define LOCK_SEED_FILE 1 -#else -#define LOCK_SEED_FILE 0 -#endif - -/* Define the constant we use for transforming the pool at read-out. */ -#if SIZEOF_UNSIGNED_LONG == 8 -#define ADD_VALUE 0xa5a5a5a5a5a5a5a5 -#elif SIZEOF_UNSIGNED_LONG == 4 -#define ADD_VALUE 0xa5a5a5a5 -#else -#error weird size for an unsigned long -#endif - -/* Contstants pertaining to the hash pool. */ -#define BLOCKLEN 64 /* Hash this amount of bytes... */ -#define DIGESTLEN 20 /* ... into a digest of this length (rmd160). */ -/* POOLBLOCKS is the number of digests which make up the pool. */ -#define POOLBLOCKS 30 -/* POOLSIZE must be a multiple of the digest length to make the AND - operations faster, the size should also be a multiple of unsigned - long. */ -#define POOLSIZE (POOLBLOCKS*DIGESTLEN) -#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) -#error Please make sure that poolsize is a multiple of unsigned long -#endif -#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) - - -/* RNDPOOL is the pool we use to collect the entropy and to stir it - 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; - -/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL. - Its allocated size is also POOLSIZE+BLOCKLEN. */ -static unsigned char *keypool; - -/* This is the offset into RNDPOOL where the next random bytes are to - be mixed in. */ -static size_t pool_writepos; - -/* When reading data out of KEYPOOL, we start the read at different - positions. This variable keeps track on where to read next. */ -static size_t pool_readpos; - -/* This flag is set to true as soon as the pool has been completely - filled the first time. This may happen either by rereading a seed - file or by adding enough entropy. */ -static int pool_filled; - -/* This counter is used to track whether the initial seeding has been - done with enough bytes from a reliable entropy source. */ -static size_t pool_filled_counter; - -/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we - have stricter requirements on what kind of entropy is in the pool. - In particular POOL_FILLED is not sufficient. Thus we add some - extra seeding and set this flag to true if the extra seeding has - been done. */ -static int did_initial_extra_seeding; - -/* This variable is used to estimated the amount of fresh entropy - available in RNDPOOL. */ -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. */ -static int just_mixed; - -/* The name of the seed file or NULL if no seed file has been defined. - The seed file needs to be regsitered at initialiation time. We - keep a malloced copy here. */ -static char *seed_file_name; - -/* If a seed file has been registered and maybe updated on exit this - flag set. */ -static int allow_seed_file_update; - -/* Option flag set at initialiation time to force allocation of the - pool in secure memory. */ -static int secure_alloc; - -/* This function pointer is set to the actual entropy gathering - function during initailization. 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); - -/* This function is set to the actual fast entropy gathering fucntion - 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); - - -/* Option flag useful for debugging and the test suite. If set - requests for very strong random are degraded to strong random. Not - used by regular applications. */ -static int quick_test; - -/* On systems without entropy gathering modules, this flag is set to - indicate that the random generator is not working properly. A - warning message is issued as well. This is useful only for - debugging and during development. */ -static int faked_rng; - -/* This is the lock we use to protect all pool operations. */ -static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER; - -/* 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 - thread-safe but as a method to get aware of missing locks in the - 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. */ -static struct -{ - unsigned long mixrnd; - unsigned long mixkey; - unsigned long slowpolls; - unsigned long fastpolls; - unsigned long getbytes1; - unsigned long ngetbytes1; - unsigned long getbytes2; - unsigned long ngetbytes2; - unsigned long addbytes; - unsigned long naddbytes; -} rndstats; - - - -/* --- Stuff pertaining to the random daemon support. --- */ -#ifdef USE_RANDOM_DAEMON - -/* If ALLOW_DAEMON is true, the module will try to use the random - daemon first. If the daemon has failed, this variable is set to - back to false and the code continues as normal. Note, we don't - 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; - -/* During initialization, the user may set a non-default socket name - for accessing the random daemon. If this value is NULL, the - default name will be used. */ -static char *daemon_socket_name; - -#endif /*USE_RANDOM_DAEMON*/ - - - -/* --- 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 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 void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t, - enum random_origins), - enum random_origins); -static void read_random_source (enum random_origins origin, - 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 ); - - - -/* --- Functions --- */ - - -/* Basic initialization which is required to initialize mutexes and - such. It does not run a full initialization so that the filling of - the random pool can be delayed until it is actually needed. We - assume that this function is used before any concurrent access - happens. */ -static void -initialize_basics(void) -{ - static int initialized; - 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) ); - -#ifdef USE_RANDOM_DAEMON - _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); - } -} - -/* Take the pool lock. */ -static void -lock_pool (void) -{ - int err; - - err = ath_mutex_lock (&pool_lock); - if (err) - log_fatal ("failed to acquire the pool lock: %s\n", strerror (err)); - pool_is_locked = 1; -} - -/* Release the pool lock. */ -static void -unlock_pool (void) -{ - 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)); -} - - -/* Full initialization of this module. */ -static void -initialize(void) -{ - /* Although the basic initialization should have happened already, - 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. */ - 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; - } - - /* Setup the fast entropy gathering function. */ - fast_gather_fnc = getfnc_fast_random_poll (); - - } - unlock_pool (); -} - - - - -/* Initialize this random subsystem. If FULL is false, this function - merely calls the initialize 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_rngcsprng_initialize (int full) -{ - if (!full) - initialize_basics (); - else - initialize (); -} - - -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. */ - - 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)":""); -} - - -/* This function should be called during initialization and before - intialization of this module to place the random pools into secure - memory. */ -void -_gcry_rngcsprng_secure_alloc (void) -{ - secure_alloc = 1; -} - - -/* This may be called before full initialization to degrade the - quality of the RNG for the sake of a faster running test suite. */ -void -_gcry_rngcsprng_enable_quick_gen (void) -{ - quick_test = 1; -} - - -void -_gcry_rngcsprng_set_daemon_socket (const char *socketname) -{ -#ifdef USE_RANDOM_DAEMON - if (daemon_socket_name) - BUG (); - - daemon_socket_name = gcry_xstrdup (socketname); -#else /*!USE_RANDOM_DAEMON*/ - (void)socketname; -#endif /*!USE_RANDOM_DAEMON*/ -} - -/* With ONOFF set to 1, enable the use of the daemon. With ONOFF set - to 0, disable the use of the daemon. With ONOF set to -1, return - whether the daemon has been enabled. */ -int -_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. */ - last = allow_daemon; - if (onoff != -1) - allow_daemon = onoff; - - return last; -#else /*!USE_RANDOM_DAEMON*/ - (void)onoff; - return 0; -#endif /*!USE_RANDOM_DAEMON*/ -} - - -/* This function returns true if no real RNG is available or the - quality of the RNG has been degraded for test purposes. */ -int -_gcry_rngcsprng_is_faked (void) -{ - /* We need to initialize due to the runtime determination of - available entropy gather modules. */ - initialize(); - return (faked_rng || quick_test); -} - - -/* 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_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality) -{ - size_t nbytes; - const char *bufptr; - - if (quality == -1) - quality = 35; - else if (quality > 100) - quality = 100; - else if (quality < 0) - quality = 0; - - if (!buf) - return gpg_error (GPG_ERR_INV_ARG); - - if (!buflen || quality < 10) - 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. */ - 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; - } - 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 - usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but - may be very slow. */ -void -_gcry_rngcsprng_randomize (void *buffer, size_t length, - enum gcry_random_level level) -{ - unsigned char *p; - - /* Make sure we are initialized. */ - initialize (); - - /* Handle our hack used for regression tests of Libgcrypt. */ - if ( quick_test && 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. */ - allow_daemon = 0; /* Daemon failed - switch off. */ -#endif /*USE_RANDOM_DAEMON*/ - - /* Acquire the pool lock. */ - lock_pool (); - - /* Update the statistics. */ - if (level >= GCRY_VERY_STRONG_RANDOM) - { - rndstats.getbytes2 += length; - rndstats.ngetbytes2++; - } - else - { - rndstats.getbytes1 += length; - rndstats.ngetbytes1++; - } - - /* Read the random into the provided buffer. */ - for (p = buffer; length > 0;) - { - size_t n; - - n = length > POOLSIZE? POOLSIZE : length; - read_pool (p, n, level); - length -= n; - p += n; - } - - /* Release the pool lock. */ - unlock_pool (); -} - - - - -/* - Mix the pool: - - |........blocks*20byte........|20byte|..44byte..| - <..44byte..> <20byte> - | | - | +------+ - +---------------------------|----------+ - v v - |........blocks*20byte........|20byte|..44byte..| - <.....64bytes.....> - | - +----------------------------------+ - Hash - v - |.............................|20byte|..44byte..| - <20byte><20byte><..44byte..> - | | - | +---------------------+ - +-----------------------------+ | - v v - |.............................|20byte|..44byte..| - <.....64byte......> - | - +-------------------------+ - Hash - v - |.............................|20byte|..44byte..| - <20byte><20byte><..44byte..> - - 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. - - Note: this function must only be called with a locked pool. - */ -static void -mix_pool(unsigned char *pool) -{ - static unsigned char failsafe_digest[DIGESTLEN]; - static int failsafe_digest_valid; - - unsigned char *hashbuf = pool + POOLSIZE; - unsigned char *p, *pend; - int i, n; - RMD160_CONTEXT md; - -#if DIGESTLEN != 20 -#error must have a digest length of 20 for ripe-md-160 -#endif - - gcry_assert (pool_is_locked); - _gcry_rmd160_init( &md ); - - /* Loop over the pool. */ - pend = pool + POOLSIZE; - memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); - memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); - _gcry_rmd160_mixblock( &md, hashbuf); - memcpy(pool, hashbuf, 20 ); - - if (failsafe_digest_valid && pool == rndpool) - { - 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 ); - } - - /* 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 */ -} - - -void -_gcry_rngcsprng_set_seed_file (const char *name) -{ - if (seed_file_name) - BUG (); - seed_file_name = gcry_xstrdup (name); -} - - -/* Lock an open file identified by file descriptor FD and wait a - reasonable time to succeed. With FOR_WRITE set to true a write - lock will be taken. FNAME is used only for diagnostics. Returns 0 - on success or -1 on error. */ -static int -lock_seed_file (int fd, const char *fname, int for_write) -{ -#if LOCK_SEED_FILE - struct flock lck; - struct timeval tv; - int backoff=0; - - /* We take a lock on the entire file. */ - memset (&lck, 0, sizeof lck); - lck.l_type = for_write? F_WRLCK : F_RDLCK; - 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*/ - return 0; -} - - -/* Read in a seed from the random_seed file and return true if this - was successful. - - Note: Multiple instances of applications sharing the same random - seed file can be started in parallel, in which case they will read - out the same pool and then race for updating it (the last update - overwrites earlier updates). They will differentiate only by the - weak entropy that is added in read_seed_file based on the PID and - clock, and up to 16 bytes of weak random non-blockingly. The - consequence is that the output of these different instances is - 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 - states of the pools are completely known. */ -static int -read_seed_file (void) -{ - int fd; - struct stat sb; - unsigned char buffer[POOLSIZE]; - int n; - - gcry_assert (pool_is_locked); - - if (!seed_file_name) - return 0; - -#ifdef HAVE_DOSISH_SYSTEM - fd = _open( seed_file_name, O_RDONLY | O_BINARY ); -#else - fd = _open( seed_file_name, O_RDONLY ); -#endif - if( fd == -1 && errno == ENOENT) - { - 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; - } - if (lock_seed_file (fd, seed_file_name, 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; - } - if (!S_ISREG(sb.st_mode) ) - { - 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; - } - - do - { - 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); - - 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 ); - } - { - 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 ); - } - - /* And read a few bytes from our entropy source. By using a level - * of 0 this will not block and might not return anything with some - * entropy drivers, however the rndlinux driver will use - * /dev/urandom and return some stuff - Do not read too much as we - * want to be friendly to the scare system entropy resource. */ - read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM ); - - allow_seed_file_update = 1; - return 1; -} - - -void -_gcry_rngcsprng_update_seed_file (void) -{ - unsigned long *sp, *dp; - 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. */ - initialize_basics (); - lock_pool (); - - if ( !seed_file_name || !rndpool || !pool_filled ) - { - unlock_pool (); - return; - } - if ( !allow_seed_file_update ) - { - 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. */ - - - /* 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; - } - 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 ); -#else -# if LOCK_SEED_FILE - 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 ); -# endif -#endif - - if (fd == -1 ) - 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); - } -#if LOCK_SEED_FILE - else if (ftruncate (fd, 0)) - { - 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)); - } - - unlock_pool (); -} - - -/* Read random out of the pool. This function is the core of the - public random functions. Note that Level GCRY_WEAK_RANDOM is not - anymore handled special and in fact is an alias in the API for - level GCRY_STRONG_RANDOM. Must be called with the pool already - locked. */ -static void -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); - volatile pid_t my_pid2; - - gcry_assert (pool_is_locked); - - 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 != 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. */ - } - - gcry_assert (pool_is_locked); - - /* Our code does not allow to extract more than POOLSIZE. Better - check it here. */ - if (length > POOLSIZE) - { - log_bug("too many random bits requested\n"); - } - - if (!pool_filled) - { - 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. */ - 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; - } - - /* 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; - } - - /* Make sure the pool is filled. */ - while (!pool_filled) - 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. */ - { - 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++; - } - - /* Create a new pool. */ - for(i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool; - 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. */ - while (length--) - { - *buffer++ = keypool[pool_readpos++]; - if (pool_readpos >= POOLSIZE) - pool_readpos = 0; - pool_balance--; - } - - if (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. */ - 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; - } -} - - - -/* Add LENGTH bytes of randomness from buffer to the pool. ORIGIN is - used to specify the randomness origin. This is one of the - RANDOM_ORIGIN_* values. */ -static void -add_randomness (const void *buffer, size_t length, enum random_origins origin) -{ - const unsigned char *p = buffer; - size_t count = 0; - - gcry_assert (pool_is_locked); - - 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; - } - } -} - - - -static void -random_poll() -{ - rndstats.slowpolls++; - read_random_source (RANDOM_ORIGIN_SLOWPOLL, POOLSIZE/5, GCRY_STRONG_RANDOM); -} - - -/* 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) -{ - 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; - } -#endif - -#if USE_RNDEGD - if ( _gcry_rndegd_connect_socket (1) != -1 ) - { - fnc = _gcry_rndegd_gather_random; - return fnc; - } -#endif - -#if USE_RNDUNIX - fnc = _gcry_rndunix_gather_random; - return fnc; -#endif - -#if USE_RNDW32 - fnc = _gcry_rndw32_gather_random; - return fnc; -#endif - - log_fatal (_("no entropy gathering module detected\n")); - - return NULL; /*NOTREACHED*/ -} - -/* Runtime determination of the fast entropy gathering function. - (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) -{ -#if USE_RNDW32 - return _gcry_rndw32_gather_random_fast; -#endif - return NULL; -} - - - -static void -do_fast_random_poll (void) -{ - gcry_assert (pool_is_locked); - - rndstats.fastpolls++; - - if (fast_gather_fnc) - 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 ); - } -#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 ); - } -#elif HAVE_CLOCK_GETTIME - { struct timespec tv; - if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) - 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 ); - } -#else /* use times */ -# ifndef HAVE_DOSISH_SYSTEM - { struct tms buf; - times( &buf ); - add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL ); - } -# endif -#endif - -#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 ); - } -# else /*!RUSAGE_SELF*/ -# ifdef __GCC__ -# warning There is no RUSAGE_SELF on this system -# endif -# endif /*!RUSAGE_SELF*/ -#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. */ - { - 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 ); - } - - /* If the system features a fast hardware RNG, read some bytes from - 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 - 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 - random pool, even if no random will be required by the process. */ -void -_gcry_rngcsprng_fast_poll (void) -{ - initialize_basics (); - - lock_pool (); - if (rndpool) - { - /* Yes, we are fully initialized. */ - do_fast_random_poll (); - } - unlock_pool (); -} - - - -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"); - - if ( slow_gather_fnc (add_randomness, orgin, length, level) < 0) - 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 ) -{ - 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; -#ifdef HAVE_RAND - srand( time(NULL)*getpid()); -#else - srandom( time(NULL)*getpid()); -#endif - } - - p = buffer = gcry_xmalloc( length ); - n = length; -#ifdef HAVE_RAND - while ( n-- ) - *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); -#endif - add_randomness ( buffer, length, origin ); - gcry_free (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-1.4.6/random/random-daemon.c b/plugins/MirOTR/libgcrypt-1.4.6/random/random-daemon.c deleted file mode 100644 index 2e03ba00e5..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/random-daemon.c +++ /dev/null @@ -1,360 +0,0 @@ -/* random-daemon.c - Access to the external random daemon - * Copyright (C) 2006 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/* - The functions here are used by random.c to divert calls to an - external random number daemon. The actual daemon we use is - gcryptrnd. Such a daemon is useful to keep a persistent pool in - memory over invocations of a single application and to allow - prioritizing access to the actual entropy sources. The drawback is - that we need to use IPC (i.e. unix domain socket) to convey - sensitive data. - */ - - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <errno.h> -#include <unistd.h> - -#include "g10lib.h" -#include "random.h" -#include "ath.h" - - - -/* This is default socket name we use in case the provided socket name - is NULL. */ -#define RANDOM_DAEMON_SOCKET "/var/run/libgcrypt/S.gcryptrnd" - -/* The lock serializing access to the daemon. */ -static ath_mutex_t daemon_lock = ATH_MUTEX_INITIALIZER; - -/* The socket connected to the daemon. */ -static int daemon_socket = -1; - -/* Creates a socket connected to the daemon. On success, store the - socket fd in *SOCK. Returns error code. */ -static gcry_error_t -connect_to_socket (const char *socketname, int *sock) -{ - struct sockaddr_un *srvr_addr; - socklen_t addrlen; - gcry_error_t err; - int fd; - int rc; - - srvr_addr = NULL; - - /* Create a socket. */ - fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror (errno)); - err = gcry_error_from_errno (errno); - goto out; - } - - /* Set up address. */ - srvr_addr = gcry_malloc (sizeof *srvr_addr); - if (! srvr_addr) - { - log_error ("malloc failed: %s\n", strerror (errno)); - err = gcry_error_from_errno (errno); - goto out; - } - memset (srvr_addr, 0, sizeof *srvr_addr); - srvr_addr->sun_family = AF_UNIX; - if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path)) - { - log_error ("socket name `%s' too long\n", socketname); - err = gcry_error (GPG_ERR_ENAMETOOLONG); - goto out; - } - strcpy (srvr_addr->sun_path, socketname); - addrlen = (offsetof (struct sockaddr_un, sun_path) - + strlen (srvr_addr->sun_path) + 1); - - /* Connect socket. */ - rc = connect (fd, (struct sockaddr *) srvr_addr, addrlen); - if (rc == -1) - { - log_error ("error connecting socket `%s': %s\n", - srvr_addr->sun_path, strerror (errno)); - err = gcry_error_from_errno (errno); - goto out; - } - - err = 0; - - out: - - gcry_free (srvr_addr); - if (err) - { - close (fd); - fd = -1; - } - *sock = fd; - - return err; -} - - -/* Initialize basics of this module. This should be viewed as a - constructor to prepare locking. */ -void -_gcry_daemon_initialize_basics (void) -{ - static int initialized; - int err; - - if (!initialized) - { - initialized = 1; - err = ath_mutex_init (&daemon_lock); - if (err) - log_fatal ("failed to create the daemon lock: %s\n", strerror (err) ); - } -} - - - -/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on - success or another value on write error. */ -static int -writen (int fd, const void *buffer, size_t length) -{ - ssize_t n; - - while (length) - { - do - n = ath_write (fd, buffer, length); - while (n < 0 && errno == EINTR); - if (n < 0) - { - log_error ("write error: %s\n", strerror (errno)); - return -1; /* write error */ - } - length -= n; - buffer = (const char*)buffer + n; - } - return 0; /* Okay */ -} - -static int -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) - { - nread = ath_read (fd, buf, nleft); - if (nread < 0) - { - if (nread == EINTR) - nread = 0; - else - return -1; - } - else if (!nread) - break; /* EOF */ - nleft -= nread; - buf = (char*)buf + nread; - } - if (ret_nread) - *ret_nread = buflen - nleft; - return 0; -} - -/* This functions requests REQ_NBYTES from the daemon. If NONCE is - true, the data should be suited for a nonce. If NONCE is FALSE, - data of random level LEVEL will be generated. The retrieved random - data will be stored in BUFFER. Returns error code. */ -static gcry_error_t -call_daemon (const char *socketname, - void *buffer, size_t req_nbytes, int nonce, - enum gcry_random_level level) -{ - static int initialized; - unsigned char buf[255]; - gcry_error_t err = 0; - size_t nbytes; - size_t nread; - int rc; - - if (!req_nbytes) - return 0; - - ath_mutex_lock (&daemon_lock); - - /* Open the socket if that has not been done. */ - if (!initialized) - { - initialized = 1; - err = connect_to_socket (socketname ? socketname : RANDOM_DAEMON_SOCKET, - &daemon_socket); - if (err) - { - daemon_socket = -1; - log_info ("not using random daemon\n"); - ath_mutex_unlock (&daemon_lock); - return err; - } - } - - /* Check that we have a valid socket descriptor. */ - if ( daemon_socket == -1 ) - { - ath_mutex_unlock (&daemon_lock); - return gcry_error (GPG_ERR_INTERNAL); - } - - - /* Do the real work. */ - - do - { - /* Process in chunks. */ - nbytes = req_nbytes > sizeof (buf) ? sizeof (buf) : req_nbytes; - req_nbytes -= nbytes; - - /* Construct request. */ - buf[0] = 3; - if (nonce) - buf[1] = 10; - else if (level == GCRY_VERY_STRONG_RANDOM) - buf[1] = 12; - else if (level == GCRY_STRONG_RANDOM) - buf[1] = 11; - buf[2] = nbytes; - - /* Send request. */ - rc = writen (daemon_socket, buf, 3); - if (rc == -1) - { - 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)); - break; - } - if (nread && buf[0]) - { - log_error ("random daemon returned error code %d\n", buf[0]); - err = gcry_error (GPG_ERR_INTERNAL); /* ? */ - break; - } - if (nread != 2) - { - log_error ("response too small\n"); - err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */ - break; - } - - /* if (1)*/ /* Do this in verbose mode? */ - /* log_info ("received response with %d bytes of data\n", buf[1]);*/ - - if (buf[1] < nbytes) - { - log_error ("error: server returned less bytes than requested\n"); - err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */ - break; - } - else if (buf[1] > nbytes) - { - log_error ("warning: server returned more bytes than requested\n"); - err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */ - break; - } - - assert (nbytes <= sizeof (buf)); - - rc = readn (daemon_socket, buf, nbytes, &nread); - if (rc == -1) - { - err = gcry_error_from_errno (errno); - log_error ("read error: %s\n", gcry_strerror (err)); - break; - } - - if (nread != nbytes) - { - log_error ("too little random data read\n"); - err = gcry_error (GPG_ERR_INTERNAL); - break; - } - - /* Successfuly read another chunk of data. */ - memcpy (buffer, buf, nbytes); - buffer = ((char *) buffer) + nbytes; - } - while (req_nbytes); - - ath_mutex_unlock (&daemon_lock); - - return err; -} - -/* Internal function to fill BUFFER with LENGTH bytes of random. We - support GCRY_STRONG_RANDOM and GCRY_VERY_STRONG_RANDOM here. - Return 0 on success. */ -int -_gcry_daemon_randomize (const char *socketname, - void *buffer, size_t length, - enum gcry_random_level level) -{ - gcry_error_t err; - - err = call_daemon (socketname, buffer, length, 0, level); - - 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-1.4.6/random/random-fips.c b/plugins/MirOTR/libgcrypt-1.4.6/random/random-fips.c deleted file mode 100644 index 2667e71fd8..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/random-fips.c +++ /dev/null @@ -1,1118 +0,0 @@ -/* random-fips.c - FIPS style random number generator - * Copyright (C) 2008 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/>. - */ - -/* - The core of this deterministic random number generator is - implemented according to the document "NIST-Recommended Random - Number Generator Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key - Triple DES and AES Algorithms" (2005-01-31). This implementation - uses the AES variant. - - There are 3 random context which map to the different levels of - random quality: - - Generator Seed and Key Kernel entropy (init/reseed) - ------------------------------------------------------------ - GCRY_VERY_STRONG_RANDOM /dev/random 256/128 bits - GCRY_STRONG_RANDOM /dev/random 256/128 bits - gcry_create_nonce GCRY_STRONG_RANDOM n/a - - All random generators return their data in 128 bit blocks. If the - caller requested less bits, the extra bits are not used. The key - for each generator is only set once at the first time a generator - is used. The seed value is set with the key and again after 1000 - (SEED_TTL) output blocks; the re-seeding is disabled in test mode. - - The GCRY_VERY_STRONG_RANDOM and GCRY_STRONG_RANDOM generators are - keyed and seeded from the /dev/random device. Thus these - generators may block until the kernel has collected enough entropy. - - The gcry_create_nonce generator is keyed and seeded from the - GCRY_STRONG_RANDOM generator. It may also block if the - GCRY_STRONG_RANDOM generator has not yet been used before and thus - gets initialized on the first use by gcry_create_nonce. This - special treatment is justified by the weaker requirements for a - nonce generator and to save precious kernel entropy for use by the - real random generators. - - */ - -#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 fips_rng_lock = ATH_MUTEX_INITIALIZER; -static int fips_rng_is_locked; - - -/* The required size for the temporary buffer of the x931_aes_driver - function and the buffer itself which will be allocated in secure - memory. This needs to be global variable for proper initialization - and to allow shutting down the RNG without leaking memory. May - only be used while holding the FIPS_RNG_LOCK. - - This variable is also used to avoid duplicate initialization. */ -#define TEMPVALUE_FOR_X931_AES_DRIVER_SIZE 48 -static unsigned char *tempvalue_for_x931_aes_driver; - - -/* After having retrieved this number of blocks from the RNG, we want - to do a reseeding. */ -#define SEED_TTL 1000 - - -/* The length of the key we use: 16 bytes (128 bit) for AES128. */ -#define X931_AES_KEYLEN 16 -/* A global buffer used to communicate between the x931_generate_key - and x931_generate_seed functions and the entropy_collect_cb - function. It may only be used by these functions. */ -static unsigned char *entropy_collect_buffer; /* Buffer. */ -static size_t entropy_collect_buffer_len; /* Used length. */ -static size_t entropy_collect_buffer_size; /* Allocated length. */ - - -/* This random context type is used to track properties of one random - generator. Thee context are usually allocated in secure memory so - that the seed value is well protected. There are a couble of guard - fields to help detecting applications accidently overwriting parts - of the memory. */ -struct rng_context -{ - unsigned char guard_0[1]; - - /* The handle of the cipher used by the RNG. If this one is not - NULL a cipher handle along with a random key has been - established. */ - gcry_cipher_hd_t cipher_hd; - - /* If this flag is true, the SEED_V buffer below carries a valid - seed. */ - int is_seeded:1; - - /* The very first block generated is used to compare the result - against the last result. This flag indicates that such a block - is available. */ - int compare_value_valid:1; - - /* A counter used to trigger re-seeding. */ - unsigned int use_counter; - - unsigned char guard_1[1]; - - /* The buffer containing the seed value V. */ - unsigned char seed_V[16]; - - unsigned char guard_2[1]; - - /* The last result from the x931_aes fucntion. Only valid if - compare_value_valid is set. */ - unsigned char compare_value[16]; - - unsigned char guard_3[1]; - - /* The external test may want to suppress the duplicate bock check. - This is done if the this flag is set. */ - unsigned char test_no_dup_check; - /* To implement a KAT we need to provide a know DT value. To - accomplish this the x931_get_dt function checks whether this - field is not NULL and then uses the 16 bytes at this address for - the DT value. However the last 4 bytes are replaced by the - value of field TEST_DT_COUNTER which will be incremented after - each invocation of x931_get_dt. We use a pointer and not a buffer - because there is no need to put this value into secure memory. */ - const unsigned char *test_dt_ptr; - u32 test_dt_counter; - - /* 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. */ - pid_t key_init_pid; - pid_t seed_init_pid; -}; -typedef struct rng_context *rng_context_t; - - -/* The random context used for the nonce generator. May only be used - while holding the FIPS_RNG_LOCK. */ -static rng_context_t nonce_context; -/* The random context used for the standard random generator. May - only be used while holding the FIPS_RNG_LOCK. */ -static rng_context_t std_rng_context; -/* The random context used for the very strong random generator. May - only be used while holding the FIPS_RNG_LOCK. */ -static rng_context_t strong_rng_context; - - -/* --- Local prototypes --- */ -static void x931_reseed (rng_context_t rng_ctx); -static void get_random (void *buffer, size_t length, rng_context_t rng_ctx); - - - - -/* --- 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 (&fips_rng_lock); - 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_STRONG_RANDOM == 1 - && GCRY_VERY_STRONG_RANDOM == 2); - -} - - -/* Acquire the fips_rng_lock. */ -static void -lock_rng (void) -{ - int my_errno; - - my_errno = ath_mutex_lock (&fips_rng_lock); - if (my_errno) - log_fatal ("failed to acquire the RNG lock: %s\n", strerror (my_errno)); - fips_rng_is_locked = 1; -} - - -/* Release the fips_rng_lock. */ -static void -unlock_rng (void) -{ - int my_errno; - - fips_rng_is_locked = 0; - my_errno = ath_mutex_unlock (&fips_rng_lock); - if (my_errno) - log_fatal ("failed to release the RNG lock: %s\n", strerror (my_errno)); -} - -static void -setup_guards (rng_context_t rng_ctx) -{ - /* Set the guards to some arbitrary values. */ - rng_ctx->guard_0[0] = 17; - rng_ctx->guard_1[0] = 42; - rng_ctx->guard_2[0] = 137; - rng_ctx->guard_3[0] = 252; -} - -static void -check_guards (rng_context_t rng_ctx) -{ - if ( rng_ctx->guard_0[0] != 17 - || rng_ctx->guard_1[0] != 42 - || rng_ctx->guard_2[0] != 137 - || rng_ctx->guard_3[0] != 252 ) - log_fatal ("memory corruption detected in RNG context %p\n", rng_ctx); -} - - -/* Get the DT vector for use with the core PRNG function. Buffer - needs to be provided by the caller with a size of at least LENGTH - bytes. RNG_CTX needs to be passed to allow for a KAT. The 16 byte - timestamp we construct is made up the real time and three counters: - - Buffer: 00112233445566778899AABBCCDDEEFF - !--+---!!-+-!!+!!--+---!!--+---! - seconds ---------/ | | | | - microseconds -----------/ | | | - counter2 -------------------/ | | - counter1 ------------------------/ | - counter0 --------------------------------/ - - 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 -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. */ - gcry_assert (fips_rng_is_locked); - - /* 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 - && rng_ctx != nonce_context - && rng_ctx != std_rng_context - && rng_ctx != strong_rng_context) - { - memcpy (buffer, rng_ctx->test_dt_ptr, 16); - buffer[12] = (rng_ctx->test_dt_counter >> 24); - buffer[13] = (rng_ctx->test_dt_counter >> 16); - buffer[14] = (rng_ctx->test_dt_counter >> 8); - buffer[15] = rng_ctx->test_dt_counter; - rng_ctx->test_dt_counter++; - return; - } - - -#if HAVE_GETTIMEOFDAY - { - static u32 last_sec, last_usec; - static u32 counter1, counter0; - static u16 counter2; - - unsigned int usec; - struct timeval tv; - - if (!last_sec) - { - /* This is the very first time we are called: Set the counters - to an not so easy predictable value to avoid always - starting at 0. Not really needed but it doesn't harm. */ - counter1 = (u32)getpid (); -#ifndef HAVE_W32_SYSTEM - counter0 = (u32)getppid (); -#endif - } - - - if (gettimeofday (&tv, NULL)) - log_fatal ("gettimeofday() failed: %s\n", strerror (errno)); - - /* The microseconds part is always less than 1 millon (0x0f4240). - Thus we don't care about the MSB and in addition shift it to - the left by 4 bits. */ - usec = tv.tv_usec; - usec <<= 4; - /* If we got the same time as by the last invocation, bump up - counter2 and save the time for the next invocation. */ - if (tv.tv_sec == last_sec && usec == last_usec) - { - counter2++; - counter2 &= 0x0fff; - } - else - { - counter2 = 0; - last_sec = tv.tv_sec; - last_usec = usec; - } - /* Fill the buffer with the timestamp. */ - buffer[0] = ((tv.tv_sec >> 24) & 0xff); - buffer[1] = ((tv.tv_sec >> 16) & 0xff); - buffer[2] = ((tv.tv_sec >> 8) & 0xff); - buffer[3] = (tv.tv_sec & 0xff); - buffer[4] = ((usec >> 16) & 0xff); - buffer[5] = ((usec >> 8) & 0xff); - buffer[6] = ((usec & 0xf0) | ((counter2 >> 8) & 0x0f)); - buffer[7] = (counter2 & 0xff); - /* Add the free running counter. */ - buffer[8] = ((counter1 >> 24) & 0xff); - buffer[9] = ((counter1 >> 16) & 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[15] = ((counter0) & 0xff); - /* Bump up that counter. */ - if (!++counter0) - ++counter1; - } -#else - log_fatal ("gettimeofday() not available on this system\n"); -#endif - - /* log_printhex ("x931_get_dt: ", buffer, 16); */ -} - - -/* XOR the buffers A and B which are each of LENGTH bytes and store - 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, - const unsigned char *a, const unsigned char *b, size_t length) -{ - for ( ; length; length--, a++, b++, r++) - *r = (*a ^ *b); -} - - -/* Encrypt LENGTH bytes of INPUT to OUTPUT using KEY. LENGTH - needs to be 16. */ -static void -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); - if (err) - log_fatal ("AES encryption in RNG failed: %s\n", gcry_strerror (err)); -} - - -/* The core ANSI X9.31, Appendix A.2.4 function using AES. The caller - needs to pass a 16 byte buffer for the result, the 16 byte - datetime_DT value and the 16 byte seed value V. The caller also - needs to pass an appropriate KEY and make sure to pass a valid - seed_V. The caller also needs to provide two 16 bytes buffer for - intermediate results, they may be reused by the caller later. - - 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], - 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]) -{ - /* Let ede*X(Y) represent the AES encryption of Y under the key *X. - - 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. - - I = ede*K(DT) */ - encrypt_aes (key, intermediate_I, datetime_DT, 16); - - /* R = ede*K(I XOR V) */ - xor_buffer (temp_xor, intermediate_I, seed_V, 16); - encrypt_aes (key, result_R, temp_xor, 16); - - /* V = ede*K(R XOR I). */ - xor_buffer (temp_xor, result_R, intermediate_I, 16); - encrypt_aes (key, seed_V, temp_xor, 16); - - /* Zero out temporary values. */ - wipememory (intermediate_I, 16); - wipememory (temp_xor, 16); -} - - -/* The high level driver to x931_aes. This one does the required - tests and calls the core function until the entire buffer has been - filled. OUTPUT is a caller provided buffer of LENGTH bytes to - receive the random, RNG_CTX is the context of the RNG. The context - must be properly initialized. Returns 0 on success. */ -static int -x931_aes_driver (unsigned char *output, size_t length, rng_context_t rng_ctx) -{ - unsigned char datetime_DT[16]; - unsigned char *intermediate_I, *temp_buffer, *result_buffer; - size_t nbytes; - - gcry_assert (fips_rng_is_locked); - gcry_assert (rng_ctx->cipher_hd); - gcry_assert (rng_ctx->is_seeded); - - gcry_assert (tempvalue_for_x931_aes_driver); - gcry_assert (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE == 48); - intermediate_I = tempvalue_for_x931_aes_driver; - temp_buffer = tempvalue_for_x931_aes_driver + 16; - result_buffer = tempvalue_for_x931_aes_driver + 32; - - while (length) - { - /* Unless we are running with a test context, we require a new - seed after some time. */ - if (!rng_ctx->test_dt_ptr && rng_ctx->use_counter > SEED_TTL) - { - x931_reseed (rng_ctx); - rng_ctx->use_counter = 0; - } - - /* Due to the design of the RNG, we always receive 16 bytes (128 - bit) of random even if we require less. The extra bytes - returned are not used. Intheory we could save them for the - next invocation, but that would make the control flow harder - to read. */ - nbytes = length < 16? length : 16; - - x931_get_dt (datetime_DT, 16, rng_ctx); - x931_aes (result_buffer, - datetime_DT, rng_ctx->seed_V, rng_ctx->cipher_hd, - intermediate_I, temp_buffer); - rng_ctx->use_counter++; - - if (rng_ctx->test_no_dup_check - && rng_ctx->test_dt_ptr - && rng_ctx != nonce_context - && rng_ctx != std_rng_context - && rng_ctx != strong_rng_context) - { - /* This is a test context which does not want the duplicate - block check. */ - } - else - { - /* Do a basic check on the output to avoid a stuck generator. */ - if (!rng_ctx->compare_value_valid) - { - /* First time used, only save the result. */ - memcpy (rng_ctx->compare_value, result_buffer, 16); - rng_ctx->compare_value_valid = 1; - continue; - } - if (!memcmp (rng_ctx->compare_value, result_buffer, 16)) - { - /* Ooops, we received the same 128 bit block - that should - in theory never happen. The FIPS requirement says that - we need to put ourself into the error state in such - case. */ - fips_signal_error ("duplicate 128 bit block returned by RNG"); - return -1; - } - memcpy (rng_ctx->compare_value, result_buffer, 16); - } - - /* Append to outbut. */ - memcpy (output, result_buffer, nbytes); - wipememory (result_buffer, 16); - output += nbytes; - length -= nbytes; - } - - return 0; -} - - -/* Callback for x931_generate_key. Note that this callback uses the - global ENTROPY_COLLECT_BUFFER which has been setup by get_entropy. - ORIGIN is not used but required due to the design of entropy - gathering module. */ -static void -entropy_collect_cb (const void *buffer, size_t length, - enum random_origins origin) -{ - const unsigned char *p = buffer; - - (void)origin; - - gcry_assert (fips_rng_is_locked); - gcry_assert (entropy_collect_buffer); - - /* Note that we need to protect against gatherers returning more - than the requested bytes (e.g. rndw32). */ - while (length-- && entropy_collect_buffer_len < entropy_collect_buffer_size) - { - entropy_collect_buffer[entropy_collect_buffer_len++] ^= *p++; - } -} - - -/* Get NBYTES of entropy from the kernel device. The callers needs to - free the returned buffer. The function either succeeds or - terminates the process in case of a fatal error. */ -static void * -get_entropy (size_t nbytes) -{ - void *result; - int rc; - - gcry_assert (!entropy_collect_buffer); - entropy_collect_buffer = gcry_xmalloc_secure (nbytes); - entropy_collect_buffer_size = nbytes; - entropy_collect_buffer_len = 0; - -#if USE_RNDLINUX - rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0, - X931_AES_KEYLEN, - GCRY_VERY_STRONG_RANDOM); -#elif USE_RNDW32 - do - { - rc = _gcry_rndw32_gather_random (entropy_collect_cb, 0, - X931_AES_KEYLEN, - GCRY_VERY_STRONG_RANDOM); - } - while (rc >= 0 && entropy_collect_buffer_len < entropy_collect_buffer_size); -#else - rc = -1; -#endif - - if (rc < 0 || entropy_collect_buffer_len != entropy_collect_buffer_size) - { - gcry_free (entropy_collect_buffer); - entropy_collect_buffer = NULL; - log_fatal ("error getting entropy data\n"); - } - result = entropy_collect_buffer; - entropy_collect_buffer = NULL; - return result; -} - - -/* Generate a key for use with x931_aes. The function returns a - handle to the cipher context readily prepared for ECB encryption. - If FOR_NONCE is true, the key is retrieved by readong random from - the standard generator. On error NULL is returned. */ -static gcry_cipher_hd_t -x931_generate_key (int for_nonce) -{ - gcry_cipher_hd_t hd; - gpg_error_t err; - void *buffer; - - gcry_assert (fips_rng_is_locked); - - /* Allocate a cipher context. */ - err = gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, - GCRY_CIPHER_SECURE); - if (err) - { - log_error ("error creating cipher context for RNG: %s\n", - gcry_strerror (err)); - return NULL; - } - - /* Get a key from the standard RNG or from the entropy source. */ - if (for_nonce) - { - buffer = gcry_xmalloc (X931_AES_KEYLEN); - get_random (buffer, X931_AES_KEYLEN, std_rng_context); - } - else - { - buffer = get_entropy (X931_AES_KEYLEN); - } - - /* 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); - wipememory (buffer, X931_AES_KEYLEN); - gcry_free (buffer); - if (err) - { - log_error ("error creating key for RNG: %s\n", gcry_strerror (err)); - gcry_cipher_close (hd); - return NULL; - } - - return hd; -} - - -/* Generate a key for use with x931_aes. The function copies a seed - of LENGTH bytes into SEED_BUFFER. LENGTH needs to by given as 16. */ -static void -x931_generate_seed (unsigned char *seed_buffer, size_t length) -{ - void *buffer; - - gcry_assert (fips_rng_is_locked); - gcry_assert (length == 16); - - buffer = get_entropy (X931_AES_KEYLEN); - - memcpy (seed_buffer, buffer, X931_AES_KEYLEN); - wipememory (buffer, X931_AES_KEYLEN); - gcry_free (buffer); -} - - - -/* Reseed a generator. This is also used for the initial seeding. */ -static void -x931_reseed (rng_context_t rng_ctx) -{ - gcry_assert (fips_rng_is_locked); - - if (rng_ctx == nonce_context) - { - /* The nonce context is special. It will be seeded using the - standard random generator. */ - get_random (rng_ctx->seed_V, 16, std_rng_context); - rng_ctx->is_seeded = 1; - rng_ctx->seed_init_pid = getpid (); - } - else - { - /* The other two generators are seeded from /dev/random. */ - x931_generate_seed (rng_ctx->seed_V, 16); - rng_ctx->is_seeded = 1; - rng_ctx->seed_init_pid = getpid (); - } -} - - -/* Core random function. This is used for both nonce and random - generator. The actual RNG to be used depends on the random context - RNG_CTX passed. Note that this function is called with the RNG not - yet locked. */ -static void -get_random (void *buffer, size_t length, rng_context_t rng_ctx) -{ - gcry_assert (buffer); - gcry_assert (rng_ctx); - - check_guards (rng_ctx); - - /* Initialize the cipher handle and thus setup the key if needed. */ - if (!rng_ctx->cipher_hd) - { - if (rng_ctx == nonce_context) - rng_ctx->cipher_hd = x931_generate_key (1); - else - rng_ctx->cipher_hd = x931_generate_key (0); - if (!rng_ctx->cipher_hd) - goto bailout; - rng_ctx->key_init_pid = getpid (); - } - - /* Initialize the seed value if needed. */ - if (!rng_ctx->is_seeded) - x931_reseed (rng_ctx); - - if (rng_ctx->key_init_pid != getpid () - || rng_ctx->seed_init_pid != getpid ()) - { - /* We are in a child of us. Because we have no way yet to do - proper re-initialization (including self-checks etc), the - only chance we have is to bail out. Obviusly a fork/exec - won't harm because the exec overwrites the old image. */ - fips_signal_error ("fork without proper re-initialization " - "detected in RNG"); - goto bailout; - } - - if (x931_aes_driver (buffer, length, rng_ctx)) - goto bailout; - - check_guards (rng_ctx); - return; - - bailout: - log_fatal ("severe error getting random\n"); - /*NOTREACHED*/ -} - - - -/* --- 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_rngfips_initialize (int full) -{ - basic_initialization (); - if (!full) - return; - - /* Allocate temporary buffers. If that buffer already exists we - know that we are already initialized. */ - lock_rng (); - if (!tempvalue_for_x931_aes_driver) - { - tempvalue_for_x931_aes_driver - = gcry_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); - setup_guards (nonce_context); - - std_rng_context = gcry_xcalloc_secure (1, sizeof *std_rng_context); - setup_guards (std_rng_context); - - strong_rng_context = gcry_xcalloc_secure (1, sizeof *strong_rng_context); - setup_guards (strong_rng_context); - } - else - { - /* Already initialized. Do some sanity checks. */ - gcry_assert (!nonce_context->test_dt_ptr); - gcry_assert (!std_rng_context->test_dt_ptr); - gcry_assert (!strong_rng_context->test_dt_ptr); - check_guards (nonce_context); - check_guards (std_rng_context); - check_guards (strong_rng_context); - } - unlock_rng (); -} - - -/* Print some statistics about the RNG. */ -void -_gcry_rngfips_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_rngfips_is_faked (void) -{ - return 0; /* Faked random is not allowed. */ -} - - -/* 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_rngfips_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_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); - else - get_random (buffer, length, std_rng_context); - unlock_rng (); -} - - -/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ -void -_gcry_rngfips_create_nonce (void *buffer, size_t length) -{ - _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - - lock_rng (); - get_random (buffer, length, nonce_context); - unlock_rng (); -} - - -/* Run a Know-Answer-Test using a dedicated test context. Note that - we can't use the samples from the NISR RNGVS document because they - don't take the requirement to throw away the first block and use - that for duplicate check in account. Thus we made up our own test - vectors. */ -static gcry_err_code_t -selftest_kat (selftest_report_func_t report) -{ - static struct - { - const unsigned char key[16]; - const unsigned char dt[16]; - const unsigned char v[16]; - const unsigned char r[3][16]; - } tv[] = - { - { { 0xb9, 0xca, 0x7f, 0xd6, 0xa0, 0xf5, 0xd3, 0x42, - 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe }, - { 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00, - 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x25, 0x00 }, - { 0x52, 0x17, 0x8d, 0x29, 0xa2, 0xd5, 0x84, 0x12, - 0x9d, 0x89, 0x9a, 0x45, 0x82, 0x02, 0xf7, 0x77 }, - { { 0x42, 0x9c, 0x08, 0x3d, 0x82, 0xf4, 0x8a, 0x40, - 0x66, 0xb5, 0x49, 0x27, 0xab, 0x42, 0xc7, 0xc3 }, - { 0x0e, 0xb7, 0x61, 0x3c, 0xfe, 0xb0, 0xbe, 0x73, - 0xf7, 0x6e, 0x6d, 0x6f, 0x1d, 0xa3, 0x14, 0xfa }, - { 0xbb, 0x4b, 0xc1, 0x0e, 0xc5, 0xfb, 0xcd, 0x46, - 0xbe, 0x28, 0x61, 0xe7, 0x03, 0x2b, 0x37, 0x7d } } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { { 0xf7, 0x95, 0xbd, 0x4a, 0x52, 0xe2, 0x9e, 0xd7, - 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, - 0xcf, 0x60, 0x62, 0x09, 0x9d, 0x20, 0x83, 0x7e } } }, - { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x80, 0x00, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, - 0xa0, 0x20, 0xa1, 0x21, 0xa2, 0x22, 0xa3, 0x23 }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { { 0x96, 0xed, 0xcc, 0xc3, 0xdd, 0x04, 0x7f, 0x75, - 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, - 0x21, 0x48, 0x41, 0x71, 0xb3, 0x8d, 0x2f, 0x4c } } } - }; - int tvidx, ridx; - rng_context_t test_ctx; - gpg_error_t err; - const char *errtxt = NULL; - unsigned char result[16]; - - gcry_assert (tempvalue_for_x931_aes_driver); - - test_ctx = gcry_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, - GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, - GCRY_CIPHER_SECURE); - if (err) - { - errtxt = "error creating cipher context for RNG"; - goto leave; - } - - err = gcry_cipher_setkey (test_ctx->cipher_hd, tv[tvidx].key, 16); - if (err) - { - 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) - |(tv[tvidx].dt[13] << 16) - |(tv[tvidx].dt[14] << 8) - |(tv[tvidx].dt[15]) ); - - /* Get and compare the first three results. */ - for (ridx=0; ridx < 3; ridx++) - { - /* Compute the next value. */ - if (x931_aes_driver (result, 16, test_ctx)) - { - errtxt = "X9.31 RNG core function failed"; - goto leave; - } - - /* Compare it to the known value. */ - if (memcmp (result, tv[tvidx].r[ridx], 16)) - { - /* log_printhex ("x931_aes got: ", result, 16); */ - /* log_printhex ("x931_aes exp: ", tv[tvidx].r[ridx], 16); */ - errtxt = "RNG output does not match known value"; - goto leave; - } - } - - /* This test is actual pretty pointless because we use a local test - context. */ - if (test_ctx->key_init_pid != getpid () - || test_ctx->seed_init_pid != getpid ()) - { - errtxt = "fork detection failed"; - goto leave; - } - - gcry_cipher_close (test_ctx->cipher_hd); - test_ctx->cipher_hd = NULL; - test_ctx->is_seeded = 0; - check_guards (test_ctx); - } - - leave: - unlock_rng (); - gcry_cipher_close (test_ctx->cipher_hd); - check_guards (test_ctx); - gcry_free (test_ctx); - if (report && errtxt) - report ("random", 0, "KAT", errtxt); - return errtxt? GPG_ERR_SELFTEST_FAILED : 0; -} - - -/* Run the self-tests. */ -gcry_error_t -_gcry_rngfips_selftest (selftest_report_func_t report) -{ - gcry_err_code_t ec; - -#if defined(USE_RNDLINUX) || defined(USE_RNDW32) - { - 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 - initialized due to the global requirement of the - tempvalue_for_x931_aes_driver stuff. */ - gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM); - } - - ec = selftest_kat (report); - -#else /*!(USE_RNDLINUX||USE_RNDW32)*/ - report ("random", 0, "setup", "no entropy gathering module"); - ec = GPG_ERR_SELFTEST_FAILED; -#endif - return gpg_error (ec); -} - - -/* Create a new test context for an external RNG test driver. On - 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_rngfips_init_external_test (void **r_context, unsigned int flags, - const void *key, size_t keylen, - const void *seed, size_t seedlen, - const void *dt, size_t dtlen) -{ - gpg_error_t err; - rng_context_t test_ctx; - - _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - - if (!r_context - || !key || keylen != 16 - || !seed || seedlen != 16 - || !dt || dtlen != 16 ) - return GPG_ERR_INV_ARG; - - test_ctx = gcry_calloc (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, - GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, - GCRY_CIPHER_SECURE); - if (err) - goto leave; - - err = gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen); - if (err) - 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[13] << 16) - |(test_ctx->test_dt_ptr[14] << 8) - |(test_ctx->test_dt_ptr[15]) ); - - if ( (flags & 1) ) - test_ctx->test_no_dup_check = 1; - - check_guards (test_ctx); - /* All fine. */ - err = 0; - - leave: - if (err) - { - gcry_cipher_close (test_ctx->cipher_hd); - gcry_free (test_ctx); - *r_context = NULL; - } - else - *r_context = test_ctx; - return gcry_err_code (err); -} - - -/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them - at BUFFER. Return 0 on success or an error code. */ -gcry_err_code_t -_gcry_rngfips_run_external_test (void *context, char *buffer, size_t buflen) -{ - rng_context_t test_ctx = context; - - if (!test_ctx || !buffer || buflen != 16) - return GPG_ERR_INV_ARG; - - lock_rng (); - get_random (buffer, buflen, test_ctx); - unlock_rng (); - return 0; -} - -/* Release the test CONTEXT. */ -void -_gcry_rngfips_deinit_external_test (void *context) -{ - rng_context_t test_ctx = context; - - if (test_ctx) - { - gcry_cipher_close (test_ctx->cipher_hd); - gcry_free (test_ctx); - } -} - - diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/random.c b/plugins/MirOTR/libgcrypt-1.4.6/random/random.c deleted file mode 100644 index 8df87e2dfa..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/random.c +++ /dev/null @@ -1,323 +0,0 @@ -/* random.c - Random number switch - * Copyright (C) 2008 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 module switches between different implementations of random - number generators and provides a few help functions. - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> - -#include "g10lib.h" -#include "random.h" -#include "rand-internal.h" -#include "ath.h" - - -/* If not NULL a progress function called from certain places and the - opaque value passed along. Registred by - _gcry_register_random_progress (). */ -static void (*progress_cb) (void *,const char*,int,int, int ); -static void *progress_cb_data; - - - - -/* --- Functions --- */ - - -/* Used to register a progress callback. This needs to be called - before any threads are created. */ -void -_gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int), - void *cb_data ) -{ - progress_cb = cb; - progress_cb_data = cb_data; -} - - -/* This progress function is currently used by the random modules to - give hints on how much more entropy is required. */ -void -_gcry_random_progress (const char *what, int printchar, int current, int total) -{ - if (progress_cb) - progress_cb (progress_cb_data, what, printchar, current, total); -} - - - -/* 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_random_initialize (int full) -{ - if (fips_mode ()) - _gcry_rngfips_initialize (full); - else - _gcry_rngcsprng_initialize (full); -} - - -void -_gcry_random_dump_stats (void) -{ - if (fips_mode ()) - _gcry_rngfips_dump_stats (); - else - _gcry_rngcsprng_dump_stats (); -} - - -/* This function should be called during initialization and beore - intialization 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. */ - else - _gcry_rngcsprng_secure_alloc (); -} - - -/* This may be called before full initialization to degrade the - quality of the RNG for the sake of a faster running test suite. */ -void -_gcry_enable_quick_random_gen (void) -{ - if (fips_mode ()) - ; /* Not used. */ - else - _gcry_rngcsprng_enable_quick_gen (); -} - - -void -_gcry_set_random_daemon_socket (const char *socketname) -{ - if (fips_mode ()) - ; /* Not used. */ - else - _gcry_rngcsprng_set_daemon_socket (socketname); -} - -/* With ONOFF set to 1, enable the use of the daemon. With ONOFF set - to 0, disable the use of the daemon. With ONOF set to -1, return - whether the daemon has been enabled. */ -int -_gcry_use_random_daemon (int onoff) -{ - if (fips_mode ()) - return 0; /* Never enabled in fips mode. */ - else - return _gcry_rngcsprng_use_daemon (onoff); -} - - -/* This function returns true if no real RNG is available or the - quality of the RNG has been degraded for test purposes. */ -int -_gcry_random_is_faked (void) -{ - if (fips_mode ()) - return _gcry_rngfips_is_faked (); - else - return _gcry_rngcsprng_is_faked (); -} - - -/* 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) -{ - if (fips_mode ()) - return 0; /* No need for this in fips mode. */ - else - return _gcry_rngcsprng_add_bytes (buf, buflen, quality); -} - - -/* 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 - _gcry_rngcsprng_randomize (buffer, length, level); -} - -/* The public function to return random data of the quality 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) -{ - void *buffer; - - buffer = gcry_xmalloc (nbytes); - do_randomize (buffer, nbytes, level); - return buffer; -} - - -/* The public function to return random data of the quality 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) -{ - 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); - do_randomize (buffer, nbytes, level); - return buffer; -} - - -/* 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 - 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) -{ - 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 - 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 - _gcry_rngcsprng_set_seed_file (name); -} - - -/* If a seed file has been setup, this function may be used to write - back the random numbers entropy pool. */ -void -_gcry_update_random_seed_file (void) -{ - if (fips_mode ()) - ; /* No need for this in fips mode. */ - else - _gcry_rngcsprng_update_seed_file (); -} - - - -/* 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 - 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 - random pool, even if no random will be required by the process. */ -void -_gcry_fast_random_poll (void) -{ - if (fips_mode ()) - ; /* No need for this in fips mode. */ - else - _gcry_rngcsprng_fast_poll (); -} - - - -/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ -void -gcry_create_nonce (void *buffer, size_t length) -{ - if (fips_mode ()) - _gcry_rngfips_create_nonce (buffer, length); - else - _gcry_rngcsprng_create_nonce (buffer, length); -} - - -/* Run the self-tests for the RNG. This is currently only implemented - for the FIPS generator. */ -gpg_error_t -_gcry_random_selftest (selftest_report_func_t report) -{ - if (fips_mode ()) - return _gcry_rngfips_selftest (report); - else - return 0; /* No selftests yet. */ -} - - -/* Create a new test context for an external RNG test driver. On - 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, - unsigned int flags, - const void *key, size_t keylen, - const void *seed, size_t seedlen, - const void *dt, size_t dtlen) -{ - (void)flags; - if (fips_mode ()) - return _gcry_rngfips_init_external_test (r_context, flags, key, keylen, - seed, seedlen, - dt, dtlen); - else - return GPG_ERR_NOT_SUPPORTED; -} - -/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them - at BUFFER. Return 0 on success or an error code. */ -gcry_err_code_t -_gcry_random_run_external_test (void *context, char *buffer, size_t buflen) -{ - if (fips_mode ()) - return _gcry_rngfips_run_external_test (context, buffer, buflen); - else - return GPG_ERR_NOT_SUPPORTED; -} - -/* Release the test CONTEXT. */ -void -_gcry_random_deinit_external_test (void *context) -{ - if (fips_mode ()) - _gcry_rngfips_deinit_external_test (context); -} diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/random.h b/plugins/MirOTR/libgcrypt-1.4.6/random/random.h deleted file mode 100644 index 9075d9a3a7..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/random.h +++ /dev/null @@ -1,72 +0,0 @@ -/* random.h - random functions - * Copyright (C) 1998, 2002, 2006 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_RANDOM_H -#define G10_RANDOM_H - -#include "types.h" - -/*-- random.c --*/ -void _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int), - void *cb_data ); - -void _gcry_random_initialize (int full); -void _gcry_random_dump_stats(void); -void _gcry_secure_random_alloc(void); -void _gcry_enable_quick_random_gen (void); -int _gcry_random_is_faked(void); -void _gcry_set_random_daemon_socket (const char *socketname); -int _gcry_use_random_daemon (int onoff); -void _gcry_set_random_seed_file (const char *name); -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, - unsigned int flags, - const void *key, - size_t keylen, - const void *seed, - size_t seedlen, - const void *dt, - size_t dtlen); -gcry_err_code_t _gcry_random_run_external_test (void *context, - char *buffer, size_t buflen); -void _gcry_random_deinit_external_test (void *context); - - -/*-- rndegd.c --*/ -gpg_error_t _gcry_rndegd_set_socket_name (const char *name); - -/*-- random-daemon.c (only used from random.c) --*/ -#ifdef USE_RANDOM_DAEMON -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-1.4.6/random/rndegd.c b/plugins/MirOTR/libgcrypt-1.4.6/random/rndegd.c deleted file mode 100644 index 63a5e0f162..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/rndegd.c +++ /dev/null @@ -1,290 +0,0 @@ -/* rndegd.c - interface to the EGD - * Copyright (C) 1999, 2000, 2002, 2003 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include "types.h" -#include "g10lib.h" -#include "cipher.h" -#include "rand-internal.h" - -#ifndef offsetof -#define offsetof(type, member) ((size_t) &((type *)0)->member) -#endif - -static int egd_socket = -1; - -/* Allocated name of the socket if supplied at runtime. */ -static char *user_socket_name; - - -/* Allocate a new filename from FIRST_PART and SECOND_PART and to - tilde expansion for first_part. SECOND_PART might be NULL. - */ -static char * -my_make_filename (const char *first_part, const char *second_part) -{ - size_t n; - char *name, *home, *p; - - n = strlen(first_part)+1; - if (second_part) - n += strlen (second_part) + 1; - - home = NULL; - if( *first_part == '~' && first_part[1] == '/' - && (home = getenv("HOME")) && *home ) - n += strlen(home); - - name = gcry_xmalloc(n); - p = (home - ? stpcpy (stpcpy (name, home), first_part+1 ) - : stpcpy (name, first_part) ); - - if (second_part) - strcpy (stpcpy(p,"/"), second_part); - - return name; -} - - -static int -do_write( int fd, void *buf, size_t nbytes ) -{ - size_t nleft = nbytes; - int nwritten; - - while( nleft > 0 ) - { - nwritten = write( fd, buf, nleft); - if( nwritten < 0 ) - { - if( errno == EINTR ) - continue; - return -1; - } - nleft -= nwritten; - buf = (char*)buf + nwritten; - } - return 0; -} - -static int -do_read( int fd, void *buf, size_t nbytes ) -{ - int n, nread = 0; - - do - { - do - { - n = read(fd, (char*)buf + nread, nbytes ); - } - while( n == -1 && errno == EINTR ); - if( n == -1) - return nread? nread:-1; - if( n == 0) - return -1; - nread += n; - nbytes -= n; - } - while( nread < nbytes ); - return nread; -} - - -/* Note that his fucntion is not thread-safe. */ -gpg_error_t -_gcry_rndegd_set_socket_name (const char *name) -{ - char *newname; - struct sockaddr_un addr; - - newname = my_make_filename (name, NULL); - if (strlen (newname)+1 >= sizeof addr.sun_path) - { - gcry_free (newname); - return gpg_error_from_syserror (); - } - gcry_free (user_socket_name); - user_socket_name = newname; - return 0; -} - - -/* Connect to the EGD and return the file descriptor. Return -1 on - error. With NOFAIL set to true, silently fail and return the - error, otherwise print an error message and die. */ -int -_gcry_rndegd_connect_socket (int nofail) -{ - int fd; - const char *bname = NULL; - char *name; - struct sockaddr_un addr; - int addr_len; - - if (egd_socket != -1) - { - close (egd_socket); - egd_socket = -1; - } - -#ifdef EGD_SOCKET_NAME - bname = EGD_SOCKET_NAME; -#endif - if (user_socket_name) - { - name = gcry_strdup (user_socket_name); - if (!name) - { - if (!nofail) - log_fatal ("error allocating memory in rndegd: %s\n", - strerror(errno) ); - return -1; - } - } - else if ( !bname || !*bname ) - name = my_make_filename ("~/.gnupg", "entropy"); - else - name = my_make_filename (bname, NULL); - - 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 ); - 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) ); - else if (connect (fd, (struct sockaddr*)&addr, addr_len) == -1) - { - if (!nofail) - log_fatal("can't connect to EGD socket `%s': %s\n", - name, strerror(errno) ); - close (fd); - fd = -1; - } - gcry_free(name); - if (fd != -1) - egd_socket = fd; - return fd; -} - -/**************** - * Note: We always use the highest level. - * To boost the performance we may want to add some - * additional code for level 1 - * - * Using a level of 0 should never block and better add nothing - * to the pool. So this is just a dummy for EGD. - */ -int -_gcry_rndegd_gather_random (void (*add)(const void*, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level ) -{ - int fd = egd_socket; - int n; - byte buffer[256+2]; - int nbytes; - int do_restart = 0; - - if( !length ) - return 0; - if( !level ) - return 0; - - restart: - if (fd == -1 || do_restart) - fd = _gcry_rndegd_connect_socket (0); - - do_restart = 0; - - nbytes = length < 255? length : 255; - /* First time we do it with a non blocking request */ - buffer[0] = 1; /* non blocking */ - buffer[1] = nbytes; - if( do_write( fd, buffer, 2 ) == -1 ) - log_fatal("can't write to the EGD: %s\n", strerror(errno) ); - n = do_read( fd, buffer, 1 ); - if( n == -1 ) - { - log_error("read error on EGD: %s\n", strerror(errno)); - do_restart = 1; - goto restart; - } - n = buffer[0]; - if( n ) - { - n = do_read( fd, buffer, n ); - if( n == -1 ) - { - log_error("read error on EGD: %s\n", strerror(errno)); - do_restart = 1; - goto restart; - } - (*add)( buffer, n, origin ); - length -= n; - } - - if( length ) - { - log_info ( - _("Please wait, entropy is being gathered. Do some work if it would\n" - "keep you from getting bored, because it will improve the quality\n" - "of the entropy.\n") ); - } - while( length ) - { - nbytes = length < 255? length : 255; - - buffer[0] = 2; /* blocking */ - buffer[1] = nbytes; - if( do_write( fd, buffer, 2 ) == -1 ) - log_fatal("can't write to the EGD: %s\n", strerror(errno) ); - n = do_read( fd, buffer, nbytes ); - if( n == -1 ) - { - log_error("read error on EGD: %s\n", strerror(errno)); - do_restart = 1; - goto restart; - } - (*add)( buffer, n, origin ); - length -= n; - } - memset(buffer, 0, sizeof(buffer) ); - - return 0; /* success */ -} diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/rndhw.c b/plugins/MirOTR/libgcrypt-1.4.6/random/rndhw.c deleted file mode 100644 index 0961d10601..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/rndhw.c +++ /dev/null @@ -1,138 +0,0 @@ -/* rndhw.c - Access to the external random daemon - * Copyright (C) 2007 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/>. - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> - -#include "types.h" -#include "g10lib.h" -#include "rand-internal.h" - -#undef USE_PADLOCK -#ifdef ENABLE_PADLOCK_SUPPORT -# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) -# define USE_PADLOCK -# endif -#endif /*ENABLE_PADLOCK_SUPPORT*/ - -/* Keep track on whether the RNG has problems. */ -static volatile int rng_failed; - - -#ifdef USE_PADLOCK -static size_t -poll_padlock (void (*add)(const void*, size_t, enum random_origins), - enum random_origins origin, int fast) -{ - 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 - would be a race condition anyway. Thus we assume that the OS - does not change the Padlock initialization while a user process - is running. */ - p = buffer; - nbytes = 0; - while (nbytes < 64) - { - 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. */ - : "=a" (status) - : "g" (p) - : "%edx", "%edi", "cc" - ); - if ((status & (1<<6)) /* RNG still enabled. */ - && !(status & (1<<13)) /* von Neumann corrector is enabled. */ - && !(status & (1<<14)) /* String filter is disabled. */ - && !(status & 0x1c00) /* BIAS voltage at default. */ - && (!(status & 0x1f) || (status & 0x1f) == 8) /* Sanity check. */ - ) - { - nbytes += (status & 0x1f); - if (fast) - break; /* Don't get into the loop with the fast flag set. */ - p += (status & 0x1f); - } - 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; - } - } - - if (nbytes) - { - (*add) ((void*)buffer, nbytes, origin); - wipememory (buffer, nbytes); - } - return nbytes; -} -#endif /*USE_PADLOCK*/ - - -int -_gcry_rndhw_failed_p (void) -{ - return rng_failed; -} - - -/* Try to read random from a hardware RNG if a fast one is - available. */ -void -_gcry_rndhw_poll_fast (void (*add)(const void*, size_t, enum random_origins), - enum random_origins origin) -{ - (void)add; - (void)origin; - -#ifdef USE_PADLOCK - if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG)) - poll_padlock (add, origin, 1); -#endif -} - - -/* Read 64 bytes from a hardware RNG and return the number of bytes - actually read. */ -size_t -_gcry_rndhw_poll_slow (void (*add)(const void*, size_t, enum random_origins), - enum random_origins origin) -{ - size_t nbytes = 0; - - (void)add; - (void)origin; - -#ifdef USE_PADLOCK - if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG)) - nbytes += poll_padlock (add, origin, 0); -#endif - - return nbytes; -} diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/rndlinux.c b/plugins/MirOTR/libgcrypt-1.4.6/random/rndlinux.c deleted file mode 100644 index 574ef6dcc0..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/rndlinux.c +++ /dev/null @@ -1,167 +0,0 @@ -/* rndlinux.c - raw random number for OSes with /dev/random - * Copyright (C) 1998, 2001, 2002, 2003, 2007 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/>. - */ - - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_GETTIMEOFDAY -# include <sys/times.h> -#endif -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include "types.h" -#include "g10lib.h" -#include "rand-internal.h" - -static int open_device ( const char *name ); - - -static int -set_cloexec_flag (int fd) -{ - int oldflags; - - oldflags= fcntl (fd, F_GETFD, 0); - if (oldflags < 0) - return oldflags; - oldflags |= FD_CLOEXEC; - return fcntl (fd, F_SETFD, oldflags); -} - - - -/* - * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists)). - */ -static int -open_device ( const char *name ) -{ - int fd; - - fd = open ( name, O_RDONLY ); - if ( fd == -1 ) - log_fatal ("can't open %s: %s\n", name, strerror(errno) ); - - if (set_cloexec_flag (fd)) - log_error ("error setting FD_CLOEXEC on fd %d: %s\n", - fd, strerror (errno)); - - /* 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. - - struct stat sb; - - if( fstat( fd, &sb ) ) - log_fatal("stat() off %s failed: %s\n", name, strerror(errno) ); - if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) ) - log_fatal("invalid random device!\n" ); - */ - return fd; -} - - -int -_gcry_rndlinux_gather_random (void (*add)(const void*, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level ) -{ - static int fd_urandom = -1; - static int fd_random = -1; - int fd; - int n; - int warn=0; - byte buffer[768]; - size_t n_hw; - - /* First read from a hardware source. However let it account only - for up to 50% of the requested bytes. */ - n_hw = _gcry_rndhw_poll_slow (add, origin); - if (n_hw > length/2) - n_hw = length/2; - if (length > 1) - length -= n_hw; - - /* Open the requested device. */ - if (level >= 2) - { - if( fd_random == -1 ) - fd_random = open_device ( NAME_OF_DEV_RANDOM ); - fd = fd_random; - } - else - { - if( fd_urandom == -1 ) - fd_urandom = open_device ( NAME_OF_DEV_URANDOM ); - fd = fd_urandom; - } - - /* And enter the read loop. */ - 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( !warn ) - { - _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; - } - memset(buffer, 0, sizeof(buffer) ); - - return 0; /* success */ -} diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/rndunix.c b/plugins/MirOTR/libgcrypt-1.4.6/random/rndunix.c deleted file mode 100644 index 1faf9abc0e..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/rndunix.c +++ /dev/null @@ -1,883 +0,0 @@ -/**************************************************************************** - * * - * * - * Unix Randomness-Gathering Code * - * * - * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. * - * Heavily modified for GnuPG by Werner Koch * - * * - * * - ****************************************************************************/ - -/* This module is part of the cryptlib continuously seeded pseudorandom - number generator. For usage conditions, see lib_rand.c - - [Here is the notice from lib_rand.c:] - - This module and the misc/rnd*.c modules represent the cryptlib - continuously seeded pseudorandom number generator (CSPRNG) as described in - my 1998 Usenix Security Symposium paper "The generation of random numbers - for cryptographic purposes". - - The CSPRNG code is copyright Peter Gutmann (and various others) 1996, - 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG - modules and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice - and this permission notice in its entirety. - - 2. Redistributions in binary form must reproduce the copyright notice in - the documentation and/or other materials provided with the distribution. - - 3. A copy of any bugfixes or enhancements made must be provided to the - author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the - baseline version of the code. - - ALTERNATIVELY, the code may be distributed under the terms of the - GNU Lesser General Public License, version 2.1 or any later version - published by the Free Software Foundation, in which case the - provisions of the GNU LGPL are required INSTEAD OF the above - restrictions. - - Although not required under the terms of the LGPL, it would still be - nice if you could make any changes available to the author to allow - a consistent code base to be maintained. */ -/************************************************************************* - The above alternative was changed from GPL to LGPL on 2007-08-22 with - permission from Peter Gutmann: - ========== - From: pgut001 <pgut001@cs.auckland.ac.nz> - 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. - ========= -*/ - -/* General includes */ - -#include <config.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -/* OS-specific includes */ - -#ifdef __osf__ - /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in - * via the following includes are various endianness defines, so we - * undefine the cryptlib ones, which aren't really needed for this module - * anyway */ -#undef BIG_ENDIAN -#undef LITTLE_ENDIAN -#endif /* __osf__ */ - -#include <unistd.h> -#include <fcntl.h> -#include <pwd.h> -#ifndef __QNX__ -#include <sys/errno.h> -#include <sys/ipc.h> -#endif /* __QNX__ */ -#include <sys/time.h> /* SCO and SunOS need this before resource.h */ -#ifndef __QNX__ -#include <sys/resource.h> -#endif /* __QNX__ */ -#if defined( _AIX ) || defined( __QNX__ ) -#include <sys/select.h> -#endif /* _AIX */ -#ifndef __QNX__ -#include <sys/shm.h> -#include <signal.h> -#include <sys/signal.h> -#endif /* __QNX__ */ -#include <sys/stat.h> -#include <sys/types.h> /* Verschiedene komische Typen */ -#if defined( __hpux ) && ( OS_VERSION == 9 ) -#include <vfork.h> -#endif /* __hpux 9.x, after that it's in unistd.h */ -#include <sys/wait.h> -/* #include <kitchensink.h> */ -#ifdef __QNX__ -#include <signal.h> -#include <process.h> -#endif /* __QNX__ */ -#include <errno.h> - -#include "types.h" /* for byte and u32 typedefs */ -#include "g10lib.h" -#include "rand-internal.h" - -#ifndef EAGAIN -#define EAGAIN EWOULDBLOCK -#endif -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */ - -/* The structure containing information on random-data sources. Each - * record contains the source and a relative estimate of its usefulness - * (weighting) which is used to scale the number of kB of output from the - * source (total = data_bytes / usefulness). Usually the weighting is in the - * range 1-3 (or 0 for especially useless sources), resulting in a usefulness - * rating of 1...3 for each kB of source output (or 0 for the useless - * sources). - * - * If the source is constantly changing (certain types of network statistics - * have this characteristic) but the amount of output is small, the weighting - * is given as a negative value to indicate that the output should be treated - * as if a minimum of 1K of output had been obtained. If the source produces - * a lot of output then the scale factor is fractional, resulting in a - * usefulness rating of < 1 for each kB of source output. - * - * In order to provide enough randomness to satisfy the requirements for a - * slow poll, we need to accumulate at least 20 points of usefulness (a - * typical system should get about 30 points). - * - * Some potential options are missed out because of special considerations. - * pstat -i and pstat -f can produce amazing amounts of output (the record - * is 600K on an Oracle server) which floods the buffer and doesn't yield - * anything useful (apart from perhaps increasing the entropy of the vmstat - * output a bit), so we don't bother with this. pstat in general produces - * quite a bit of output, but it doesn't change much over time, so it gets - * very low weightings. netstat -s produces constantly-changing output but - * also produces quite a bit of it, so it only gets a weighting of 2 rather - * than 3. The same holds for netstat -in, which gets 1 rather than 2. - * - * Some binaries are stored in different locations on different systems so - * alternative paths are given for them. The code sorts out which one to - * run by itself, once it finds an exectable somewhere it moves on to the - * next source. The sources are arranged roughly in their order of - * usefulness, occasionally sources which provide a tiny amount of - * relatively useless data are placed ahead of ones which provide a large - * amount of possibly useful data because another 100 bytes can't hurt, and - * it means the buffer won't be swamped by one or two high-output sources. - * All the high-output sources are clustered towards the end of the list - * for this reason. Some binaries are checked for in a certain order, for - * example under Slowaris /usr/ucb/ps understands aux as an arg, but the - * others don't. Some systems have conditional defines enabling alternatives - * to commands which don't understand the usual options but will provide - * enough output (in the form of error messages) to look like they're the - * real thing, causing alternative options to be skipped (we can't check the - * return either because some commands return peculiar, non-zero status even - * when they're working correctly). - * - * In order to maximise use of the buffer, the code performs a form of run- - * length compression on its input where a repeated sequence of bytes is - * replaced by the occurrence count mod 256. Some commands output an awful - * lot of whitespace, this measure greatly increases the amount of data we - * can fit in the buffer. - * - * When we scale the weighting using the SC() macro, some preprocessors may - * give a division by zero warning for the most obvious expression - * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero - * trap), so we define a value SC_0 which evaluates to zero when fed to - * '1024 / SC_0' */ - -#define SC( weight ) ( 1024 / weight ) /* Scale factor */ -#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */ - -static struct RI { - const char *path; /* Path to check for existence of source */ - const char *arg; /* Args for source */ - const int usefulness; /* Usefulness of source */ - FILE *pipe; /* Pipe to source as FILE * */ - int pipeFD; /* Pipe to source as FD */ - pid_t pid; /* pid of child for waitpid() */ - int length; /* Quantity of output produced */ - const int hasAlternative; /* Whether source has alt.location */ -} dataSources[] = { - - { "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0}, - { "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0}, - { "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0}, - { "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0}, - { "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1}, - { "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0}, - { "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0}, - { "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 }, - { "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1}, - { "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0}, - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ - { "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 }, - { "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 }, - { "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, - { "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 }, -#if defined( __sgi ) || defined( __hpux ) - { "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 }, -#endif /* __sgi || __hpux */ - { "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, - { "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, - { "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 }, - { "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/ - { "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 }, - /* Unreliable source, depends on system usage */ - { "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, - /* pstat is your friend */ - { "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 }, -#ifdef __sgi - { "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, -#endif /* __sgi */ -#ifdef __hpux - { "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, -#endif /* __hpux */ - { "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 }, - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0", - SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0", - SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ - { "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 }, - { "/usr/sbin/ripquery", "-nw 1 127.0.0.1", - SC(0.1), NULL, 0, 0, 0, 0 }, - { "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 }, - /* This is very environment-dependant. If network traffic is low, it'll - * probably time out before delivering 5 packets, which is OK because - * it'll probably be fixed stuff like ARP anyway */ - { "/usr/sbin/advfsstat", "-b usr_domain", - SC(SC_0), NULL, 0, 0, 0, 0}, - { "/usr/sbin/advfsstat", "-l 2 usr_domain", - SC(0.5), NULL, 0, 0, 0, 0}, - { "/usr/sbin/advfsstat", "-p usr_domain", - SC(SC_0), NULL, 0, 0, 0, 0}, - /* 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__ - { "/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 -#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 - * you can use (for example the finger might be more useful on a - * firewalled internal network) */ - { "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 }, - { "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html", - SC(0.9), NULL, 0, 0, 0, 0 }, - { "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 }, -#endif /* 0 */ - { NULL, NULL, 0, NULL, 0, 0, 0, 0 } -}; - -static byte *gather_buffer; /* buffer for gathering random noise */ -static int gather_buffer_size; /* size of the memory buffer */ -static uid_t gatherer_uid; - -/* The message structure used to communicate with the parent */ -typedef struct { - int usefulness; /* usefulness of data */ - int ndata; /* valid bytes in data */ - char data[500]; /* gathered data */ -} GATHER_MSG; - -#ifndef HAVE_WAITPID -static pid_t -waitpid(pid_t pid, int *statptr, int options) -{ -#ifdef HAVE_WAIT4 - return wait4(pid, statptr, options, NULL); -#else - /* If wait4 is also not available, try wait3 for SVR3 variants */ - /* Less ideal because can't actually request a specific pid */ - /* For that reason, first check to see if pid is for an */ - /* existing process. */ - int tmp_pid, dummystat;; - if (kill(pid, 0) == -1) { - errno = ECHILD; - return -1; - } - if (statptr == NULL) - statptr = &dummystat; - while (((tmp_pid = wait3(statptr, options, 0)) != pid) && - (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) - ; - return tmp_pid; -#endif -} -#endif - -/* Under SunOS popen() doesn't record the pid of the child process. When - * pclose() is called, instead of calling waitpid() for the correct child, it - * calls wait() repeatedly until the right child is reaped. The problem is - * that this reaps any other children that happen to have died at that - * moment, and when their pclose() comes along, the process hangs forever. - * The fix is to use a wrapper for popen()/pclose() which saves the pid in - * the dataSources structure (code adapted from GNU-libc's popen() call). - * - * Aut viam inveniam aut faciam */ - -static FILE * -my_popen(struct RI *entry) -{ - int pipedes[2]; - FILE *stream; - - /* Create the pipe */ - if (pipe(pipedes) < 0) - return (NULL); - - /* Fork off the child ("vfork() is like an OS orgasm. All OS's want to - * do it, but most just end up faking it" - Chris Wedgwood). If your OS - * supports it, you should try to use vfork() here because it's somewhat - * more efficient */ -#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \ - defined(__hpux) - entry->pid = vfork(); -#else /* */ - entry->pid = fork(); -#endif /* Unixen which have vfork() */ - if (entry->pid == (pid_t) - 1) { - /* The fork failed */ - close(pipedes[0]); - close(pipedes[1]); - return (NULL); - } - - if (entry->pid == (pid_t) 0) { - struct passwd *passwd; - - /* We are the child. Make the read side of the pipe be stdout */ - if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) - exit(127); - - /* Now that everything is set up, give up our permissions to make - * sure we don't read anything sensitive. If the getpwnam() fails, - * we default to -1, which is usually nobody */ - if (gatherer_uid == (uid_t)-1 && \ - (passwd = getpwnam("nobody")) != NULL) - gatherer_uid = passwd->pw_uid; - - setuid(gatherer_uid); - - /* Close the pipe descriptors */ - close(pipedes[STDIN_FILENO]); - close(pipedes[STDOUT_FILENO]); - - /* Try and exec the program */ - execl(entry->path, entry->path, entry->arg, NULL); - - /* Die if the exec failed */ - exit(127); - } - - /* We are the parent. Close the irrelevant side of the pipe and open - * the relevant side as a new stream. Mark our side of the pipe to - * close on exec, so new children won't see it */ - close(pipedes[STDOUT_FILENO]); - -#ifdef FD_CLOEXEC - fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); -#endif - - stream = fdopen(pipedes[STDIN_FILENO], "r"); - - if (stream == NULL) { - int savedErrno = errno; - - /* The stream couldn't be opened or the child structure couldn't be - * allocated. Kill the child and close the other side of the pipe */ - kill(entry->pid, SIGKILL); - if (stream == NULL) - close(pipedes[STDOUT_FILENO]); - else - fclose(stream); - - waitpid(entry->pid, NULL, 0); - - entry->pid = 0; - errno = savedErrno; - return (NULL); - } - - return (stream); -} - -static int -my_pclose(struct RI *entry) -{ - int status = 0; - - if (fclose(entry->pipe)) - return (-1); - - /* We ignore the return value from the process because some - programs return funny values which would result in the input - being discarded even if they executed successfully. This isn't - a problem because the result data size threshold will filter - out any programs which exit with a usage message without - producing useful output. */ - if (waitpid(entry->pid, NULL, 0) != entry->pid) - status = -1; - - entry->pipe = NULL; - entry->pid = 0; - return (status); -} - - -/* Unix slow poll (without special support for Linux) - * - * If a few of the randomness sources create a large amount of output then - * the slowPoll() stops once the buffer has been filled (but before all the - * randomness sources have been sucked dry) so that the 'usefulness' factor - * remains below the threshold. For this reason the gatherer buffer has to - * be fairly sizeable on moderately loaded systems. This is something of a - * bug since the usefulness should be influenced by the amount of output as - * well as the source type */ - - -static int -slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) -{ - int moreSources; - struct timeval tv; - fd_set fds; -#if defined( __hpux ) - size_t maxFD = 0; -#else - int maxFD = 0; -#endif /* OS-specific brokenness */ - int bufPos, i, usefulness = 0; - - - /* Fire up each randomness source */ - FD_ZERO(&fds); - for (i = 0; dataSources[i].path != NULL; i++) { - /* Since popen() is a fairly heavy function, we check to see whether - * the executable exists before we try to run it */ - if (access(dataSources[i].path, X_OK)) { - if( dbgfp && dbgall ) - fprintf(dbgfp, "%s not present%s\n", dataSources[i].path, - dataSources[i].hasAlternative ? - ", has alternatives" : ""); - dataSources[i].pipe = NULL; - } - else - dataSources[i].pipe = my_popen(&dataSources[i]); - - if (dataSources[i].pipe != NULL) { - dataSources[i].pipeFD = fileno(dataSources[i].pipe); - if (dataSources[i].pipeFD > maxFD) - maxFD = dataSources[i].pipeFD; - -#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */ - fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK); -#else -#error O_NONBLOCK is missing -#endif - - FD_SET(dataSources[i].pipeFD, &fds); - dataSources[i].length = 0; - - /* If there are alternatives for this command, don't try and - * execute them */ - while (dataSources[i].hasAlternative) { - if( dbgfp && dbgall ) - fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path); - i++; - } - } - } - - - /* Suck all the data we can get from each of the sources */ - bufPos = 0; - moreSources = 1; - 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; - -#if defined( __hpux ) && ( OS_VERSION == 9 ) - if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) -#else /* */ - if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) -#endif /* __hpux */ - break; - - /* One of the sources has data available, read it into the buffer */ - for (i = 0; dataSources[i].path != NULL; i++) { - if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) { - size_t noBytes; - - if ((noBytes = fread(gather_buffer + bufPos, 1, - gather_buffer_size - bufPos, - dataSources[i].pipe)) == 0) { - if (my_pclose(&dataSources[i]) == 0) { - int total = 0; - - /* Try and estimate how much entropy we're getting - * from a data source */ - if (dataSources[i].usefulness) { - if (dataSources[i].usefulness < 0) - total = (dataSources[i].length + 999) - / -dataSources[i].usefulness; - else - total = dataSources[i].length - / dataSources[i].usefulness; - } - if( dbgfp ) - fprintf(dbgfp, - "%s %s contributed %d bytes, " - "usefulness = %d\n", dataSources[i].path, - (dataSources[i].arg != NULL) ? - dataSources[i].arg : "", - dataSources[i].length, total); - if( dataSources[i].length ) - usefulness += total; - } - dataSources[i].pipe = NULL; - } - else { - int currPos = bufPos; - int endPos = bufPos + noBytes; - - /* Run-length compress the input byte sequence */ - while (currPos < endPos) { - int ch = gather_buffer[currPos]; - - /* If it's a single byte, just copy it over */ - if (ch != gather_buffer[currPos + 1]) { - gather_buffer[bufPos++] = ch; - currPos++; - } - else { - int count = 0; - - /* It's a run of repeated bytes, replace them - * with the byte count mod 256 */ - while ((ch == gather_buffer[currPos]) - && currPos < endPos) { - count++; - currPos++; - } - gather_buffer[bufPos++] = count; - noBytes -= count - 1; - } - } - - /* Remember the number of (compressed) bytes of input we - * obtained */ - dataSources[i].length += noBytes; - } - } - } - - /* Check if there is more input available on any of the sources */ - moreSources = 0; - FD_ZERO(&fds); - for (i = 0; dataSources[i].path != NULL; i++) { - if (dataSources[i].pipe != NULL) { - FD_SET(dataSources[i].pipeFD, &fds); - moreSources = 1; - } - } - } - - if( dbgfp ) { - fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); - fflush(dbgfp); - } - *nbytes = bufPos; - return usefulness; -} - -/**************** - * Start the gatherer process which writes messages of - * type GATHERER_MSG to pipedes - */ -static void -start_gatherer( int pipefd ) -{ - FILE *dbgfp = NULL; - int dbgall; - - { - const char *s = getenv("GNUPG_RNDUNIX_DBG"); - if( s ) { - dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a"); - if( !dbgfp ) - log_info("can't open debug file `%s': %s\n", - s, strerror(errno) ); - else - fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid()); - } - dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL"); - } - /* close all files but the ones we need */ - { int nmax, n1, n2, i; -#ifdef _SC_OPEN_MAX - if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) { -#ifdef _POSIX_OPEN_MAX - nmax = _POSIX_OPEN_MAX; -#else - nmax = 20; /* assume a reasonable value */ -#endif - } -#else /*!_SC_OPEN_MAX*/ - nmax = 20; /* assume a reasonable value */ -#endif /*!_SC_OPEN_MAX*/ - n1 = fileno( stderr ); - n2 = dbgfp? fileno( dbgfp ) : -1; - for(i=0; i < nmax; i++ ) { - if( i != n1 && i != n2 && i != pipefd ) - close(i); - } - errno = 0; - } - - - /* Set up the buffer. Not ethat we use a plain standard malloc here. */ - gather_buffer_size = GATHER_BUFSIZE; - gather_buffer = malloc( gather_buffer_size ); - if( !gather_buffer ) { - log_error("out of core while allocating the gatherer buffer\n"); - exit(2); - } - - /* Reset the SIGC(H)LD handler to the system default. This is necessary - * because if the program which cryptlib is a part of installs its own - * SIGC(H)LD handler, it will end up reaping the cryptlib children before - * cryptlib can. As a result, my_pclose() will call waitpid() on a - * process which has already been reaped by the installed handler and - * return an error, so the read data won't be added to the randomness - * pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and - * the BSD/Posix SIGCHLD, so we need to handle either possibility */ -#ifdef SIGCLD - signal(SIGCLD, SIG_DFL); -#else - signal(SIGCHLD, SIG_DFL); -#endif - - fclose(stderr); /* Arrghh!! It's Stuart code!! */ - - for(;;) { - GATHER_MSG msg; - size_t nbytes; - const char *p; - - msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes ); - p = gather_buffer; - while( nbytes ) { - msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes; - memcpy( msg.data, p, msg.ndata ); - nbytes -= msg.ndata; - p += msg.ndata; - - while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) { - if( errno == EINTR ) - continue; - if( errno == EAGAIN ) { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 50000; - select(0, NULL, NULL, NULL, &tv); - continue; - } - if( errno == EPIPE ) /* parent has exited, so give up */ - exit(0); - - /* we can't do very much here because stderr is closed */ - if( dbgfp ) - fprintf(dbgfp, "gatherer can't write to pipe: %s\n", - strerror(errno) ); - /* we start a new poll to give the system some time */ - nbytes = 0; - break; - } - } - } - /* we are killed when the parent dies */ -} - - -static int -read_a_msg( int fd, GATHER_MSG *msg ) -{ - char *buffer = (char*)msg; - size_t length = sizeof( *msg ); - int n; - - do { - do { - n = read(fd, buffer, length ); - } while( n == -1 && errno == EINTR ); - if( n == -1 ) - return -1; - buffer += n; - length -= n; - } while( length ); - return 0; -} - - -/**************** - * Using a level of 0 should never block and better add nothing - * to the pool. So this is just a dummy for this gatherer. - */ -int -_gcry_rndunix_gather_random (void (*add)(const void*, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level ) -{ - static pid_t gatherer_pid = 0; - static int pipedes[2]; - GATHER_MSG msg; - size_t n; - - if( !level ) - return 0; - - if( !gatherer_pid ) { - /* Make sure we are not setuid. */ - if ( getuid() != geteuid() ) - BUG(); - /* time to start the gatherer process */ - if( pipe( pipedes ) ) { - log_error("pipe() failed: %s\n", strerror(errno)); - return -1; - } - gatherer_pid = fork(); - if( gatherer_pid == -1 ) { - log_error("can't for gatherer process: %s\n", strerror(errno)); - return -1; - } - if( !gatherer_pid ) { - start_gatherer( pipedes[1] ); - /* oops, can't happen */ - return -1; - } - } - - /* now read from the gatherer */ - while( length ) { - int goodness; - ulong subtract; - - if( read_a_msg( pipedes[0], &msg ) ) { - log_error("reading from gatherer pipe failed: %s\n", - strerror(errno)); - return -1; - } - - - if( level > 1 ) { - if( msg.usefulness > 30 ) - goodness = 100; - else if ( msg.usefulness ) - goodness = msg.usefulness * 100 / 30; - else - goodness = 0; - } - else if( level ) { - if( msg.usefulness > 15 ) - goodness = 100; - else if ( msg.usefulness ) - goodness = msg.usefulness * 100 / 15; - else - goodness = 0; - } - else - goodness = 100; /* goodness of level 0 is always 100 % */ - - n = msg.ndata; - if( n > length ) - n = length; - (*add)( msg.data, n, origin ); - - /* this is the trick how we cope with the goodness */ - subtract = (ulong)n * goodness / 100; - /* subtract at least 1 byte to avoid infinite loops */ - length -= subtract ? subtract : 1; - } - - return 0; -} diff --git a/plugins/MirOTR/libgcrypt-1.4.6/random/rndw32.c b/plugins/MirOTR/libgcrypt-1.4.6/random/rndw32.c deleted file mode 100644 index 56422a4242..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/random/rndw32.c +++ /dev/null @@ -1,981 +0,0 @@ -/* rndw32.c - W32 entropy gatherer - * Copyright (C) 1999, 2000, 2002, 2003, 2007 Free Software Foundation, Inc. - * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006 - * - * This file is part of Libgcrypt. - * - ************************************************************************* - * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann. - * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this - * copyright notice: - * - * This module is part of the cryptlib continuously seeded pseudorandom - * number generator. For usage conditions, see lib_rand.c - * - * [Here is the notice from lib_rand.c, which is now called dev_sys.c] - * - * This module and the misc/rnd*.c modules represent the cryptlib - * continuously seeded pseudorandom number generator (CSPRNG) as described in - * my 1998 Usenix Security Symposium paper "The generation of random numbers - * for cryptographic purposes". - * - * The CSPRNG code is copyright Peter Gutmann (and various others) 1996, - * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG - * modules and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice - * and this permission notice in its entirety. - * - * 2. Redistributions in binary form must reproduce the copyright notice in - * the documentation and/or other materials provided with the distribution. - * - * 3. A copy of any bugfixes or enhancements made must be provided to the - * author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the - * baseline version of the code. - * - * ALTERNATIVELY, the code may be distributed under the terms of the - * GNU Lesser General Public License, version 2.1 or any later version - * published by the Free Software Foundation, in which case the - * provisions of the GNU LGPL are required INSTEAD OF the above - * restrictions. - * - * Although not required under the terms of the LGPL, it would still - * be nice if you could make any changes available to the author to - * allow a consistent code base to be maintained. - ************************************************************************* - * The above alternative was changed from GPL to LGPL on 2007-08-22 with - * permission from Peter Gutmann: - *========== - From: pgut001 <pgut001@cs.auckland.ac.nz> - 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. - *========== - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#ifdef __GNUC__ -#include <stdint.h> -#endif - -#include <winsock2.h> -#include <windows.h> - - -#include "types.h" -#include "g10lib.h" -#include "rand-internal.h" - - -/* Definitions which are missing from the current GNU Windows32Api. */ -#ifndef IOCTL_DISK_PERFORMANCE -#define IOCTL_DISK_PERFORMANCE 0x00070020 -#endif - -/* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger - value in a newer release. So we use a far larger value. */ -#define SIZEOF_DISK_PERFORMANCE_STRUCT 256 - -/* We don't include wincrypt.h so define it here. */ -#define HCRYPTPROV HANDLE - - -/* When we query the performance counters, we allocate an initial buffer and - * then reallocate it as required until RegQueryValueEx() stops returning - * ERROR_MORE_DATA. The following values define the initial buffer size and - * step size by which the buffer is increased - */ -#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */ -#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */ - - -/* The number of bytes to read from the system RNG on each slow poll. */ -#define SYSTEMRNG_BYTES 64 - -/* Intel Chipset CSP type and name */ -#define PROV_INTEL_SEC 22 -#define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider" - - - - -/* Type definitions for function pointers to call NetAPI32 functions. */ -typedef DWORD (WINAPI *NETSTATISTICSGET)(LPWSTR szServer, LPWSTR szService, - DWORD dwLevel, DWORD dwOptions, - LPBYTE *lpBuffer); -typedef DWORD (WINAPI *NETAPIBUFFERSIZE)(LPVOID lpBuffer, LPDWORD cbBuffer); -typedef DWORD (WINAPI *NETAPIBUFFERFREE)(LPVOID lpBuffer); - -/* Type definitions for function pointers to call native NT functions. */ -typedef DWORD (WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD systemInformationClass, - PVOID systemInformation, - ULONG systemInformationLength, - PULONG returnLength); -typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS) - (HANDLE processHandle, DWORD processInformationClass, - PVOID processInformation, ULONG processInformationLength, - PULONG returnLength); -typedef DWORD (WINAPI *NTPOWERINFORMATION) - (DWORD powerInformationClass, PVOID inputBuffer, - ULONG inputBufferLength, PVOID outputBuffer, ULONG outputBufferLength ); - -/* Type definitions for function pointers to call CryptoAPI functions. */ -typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv, - LPCTSTR pszContainer, - 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 - 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 - 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, - for example via TCPA devices. */ -typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer, - ULONG RandomBufferLength); - - - -/* MBM data structures, originally by Alexander van Kaam, converted to C by - Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu> */ -#define BusType char -#define SMBType char -#define SensorType char - -typedef struct -{ - SensorType iType; /* Type of sensor. */ - int Count; /* Number of sensor for that type. */ -} SharedIndex; - -typedef struct -{ - SensorType ssType; /* Type of sensor */ - unsigned char ssName[12]; /* Name of sensor */ - char sspadding1[3]; /* Padding of 3 bytes */ - double ssCurrent; /* Current value */ - double ssLow; /* Lowest readout */ - double ssHigh; /* Highest readout */ - long ssCount; /* Total number of readout */ - char sspadding2[4]; /* Padding of 4 bytes */ - long double ssTotal; /* Total amout of all readouts */ - char sspadding3[6]; /* Padding of 6 bytes */ - double ssAlarm1; /* Temp & fan: high alarm; voltage: % off */ - double ssAlarm2; /* Temp: low alarm */ -} SharedSensor; - -typedef struct -{ - short siSMB_Base; /* SMBus base address */ - BusType siSMB_Type; /* SMBus/Isa bus used to access chip */ - SMBType siSMB_Code; /* SMBus sub type, Intel, AMD or ALi */ - char siSMB_Addr; /* Address of sensor chip on SMBus */ - unsigned char siSMB_Name[41]; /* Nice name for SMBus */ - short siISA_Base; /* ISA base address of sensor chip on ISA */ - int siChipType; /* Chip nr, connects with Chipinfo.ini */ - char siVoltageSubType; /* Subvoltage option selected */ -} SharedInfo; - -typedef struct -{ - double sdVersion; /* Version number (example: 51090) */ - SharedIndex sdIndex[10]; /* Sensor index */ - SharedSensor sdSensor[100]; /* Sensor info */ - SharedInfo sdInfo; /* Misc.info */ - unsigned char sdStart[41]; /* Start time */ - - /* We don't use the next two fields both because they're not random - and because it provides a nice safety margin in case of data size - mis- estimates (we always under-estimate the buffer size). */ -#if 0 - unsigned char sdCurrent[41]; /* Current time */ - unsigned char sdPath[256]; /* MBM path */ -#endif /*0*/ -} SharedData; - - - -/* One time intialized handles and function pointers. We use dynamic - loading of the DLLs to do without them in case libgcrypt does not - need any random. */ -static HANDLE hNetAPI32; -static NETSTATISTICSGET pNetStatisticsGet; -static NETAPIBUFFERSIZE pNetApiBufferSize; -static NETAPIBUFFERFREE pNetApiBufferFree; - -static HANDLE hNTAPI; -static NTQUERYSYSTEMINFORMATION pNtQuerySystemInformation; -static NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess; -static NTPOWERINFORMATION pNtPowerInformation; - -static HANDLE hAdvAPI32; -static CRYPTACQUIRECONTEXT pCryptAcquireContext; -static CRYPTGENRANDOM pCryptGenRandom; -static CRYPTRELEASECONTEXT pCryptReleaseContext; -static RTLGENRANDOM pRtlGenRandom; - - -/* Other module global variables. */ -static int system_rng_available; /* Whether a system RNG is available. */ -static HCRYPTPROV hRNGProv; /* Handle to Intel RNG CSP. */ - -static int debug_me; /* Debug flag. */ - -static int system_is_w2000; /* True if running on W2000. */ - - - - -/* Try and connect to the system RNG if there's one present. */ -static void -init_system_rng (void) -{ - system_rng_available = 0; - hRNGProv = NULL; - - hAdvAPI32 = GetModuleHandleA("AdvAPI32.dll"); - if (!hAdvAPI32) - return; - - pCryptAcquireContext = (CRYPTACQUIRECONTEXT) - GetProcAddress(hAdvAPI32, "CryptAcquireContextA"); - pCryptGenRandom = (CRYPTGENRANDOM) - GetProcAddress(hAdvAPI32, "CryptGenRandom"); - pCryptReleaseContext = (CRYPTRELEASECONTEXT) - 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 - Intel, it's included here mostly for form's sake. */ - if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext - || !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV, - PROV_INTEL_SEC, 0) ) - && !pRtlGenRandom) - { - hAdvAPI32 = NULL; - } - else - system_rng_available = 1; -} - - -/* Read data from the system RNG if availavle. */ -static void -read_system_rng (void (*add)(const void*, size_t, enum random_origins), - enum random_origins requester) -{ - BYTE buffer[ SYSTEMRNG_BYTES + 8 ]; - int quality = 0; - - if (!system_rng_available) - return; - - /* Read SYSTEMRNG_BYTES bytes from the system RNG. We don't rely on - this for all our randomness requirements (particularly the - software RNG) in case it's broken in some way. */ - if (hRNGProv) - { - if (pCryptGenRandom (hRNGProv, SYSTEMRNG_BYTES, buffer)) - quality = 80; - } - else if (pRtlGenRandom) - { - if ( pRtlGenRandom (buffer, SYSTEMRNG_BYTES)) - quality = 50; - } - if (quality > 0) - { - if (debug_me) - log_debug ("rndw32#read_system_rng: got %d bytes of quality %d\n", - SYSTEMRNG_BYTES, quality); - (*add) (buffer, SYSTEMRNG_BYTES, requester); - wipememory (buffer, SYSTEMRNG_BYTES); - } -} - - -/* 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), - enum random_origins requester) -{ - HANDLE hMBMData; - SharedData *mbmDataPtr; - - hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, _T("$M$B$M$5$S$D$")); - if (hMBMData) - { - mbmDataPtr = (SharedData*)MapViewOfFile (hMBMData, FILE_MAP_READ,0,0,0); - if (mbmDataPtr) - { - if (debug_me) - log_debug ("rndw32#read_mbm_data: got %d bytes\n", - sizeof (SharedData)); - (*add) (mbmDataPtr, sizeof (SharedData), requester); - UnmapViewOfFile (mbmDataPtr); - } - CloseHandle (hMBMData); - } -} - - -/* Fallback method using the registry to poll the statistics. */ -static void -registry_poll (void (*add)(const void*, size_t, enum random_origins), - enum random_origins requester) -{ - static int cbPerfData = PERFORMANCE_BUFFER_SIZE; - int iterations; - DWORD dwSize, status; - PERF_DATA_BLOCK *pPerfData; - - /* Get information from the system performance counters. This can take a - few seconds to do. In some environments the call to RegQueryValueEx() - can produce an access violation at some random time in the future, in - some cases adding a short delay after the following code block makes - the problem go away. This problem is extremely difficult to - reproduce, I haven't been able to get it to occur despite running it - on a number of machines. MS knowledge base article Q178887 covers - this type of problem, it's typically caused by an external driver or - other program that adds its own values under the - HKEY_PERFORMANCE_DATA key. The NT kernel, via Advapi32.dll, calls the - required external module to map in the data inside an SEH try/except - block, so problems in the module's collect function don't pop up until - after it has finished, so the fault appears to occur in Advapi32.dll. - There may be problems in the NT kernel as well though, a low-level - memory checker indicated that ExpandEnvironmentStrings() in - Kernel32.dll, called an interminable number of calls down inside - RegQueryValueEx(), was overwriting memory (it wrote twice the - allocated size of a buffer to a buffer allocated by the NT kernel). - OTOH this could be coming from the external module calling back into - the kernel, which eventually causes the problem described above. - - Possibly as an extension of the problem that the krnlWaitSemaphore() - call above works around, running two instances of cryptlib (e.g. two - applications that use it) under NT4 can result in one of them hanging - in the RegQueryValueEx() call. This happens only under NT4 and is - hard to reproduce in any consistent manner. - - One workaround that helps a bit is to read the registry as a remote - (rather than local) registry, it's possible that the use of a network - RPC call isolates the calling app from the problem in that whatever - service handles the RPC is taking the hit and not affecting the - calling app. Since this would require another round of extensive - testing to verify and the NT native API call is working fine, we'll - stick with the native API call for now. - - Some versions of NT4 had a problem where the amount of data returned - was mis-reported and would never settle down, because of this the code - below includes a safety-catch that bails out after 10 attempts have - been made, this results in no data being returned but at does ensure - that the thread will terminate. - - In addition to these problems the code in RegQueryValueEx() that - estimates the amount of memory required to return the performance - counter information isn't very accurate (it's much worse than the - "slightly-inaccurate" level that the MS docs warn about, it's usually - wildly off) since it always returns a worst-case estimate which is - usually nowhere near the actual amount required. For example it may - report that 128K of memory is required, but only return 64K of data. - - Even worse than the registry-based performance counters is the - performance data helper (PDH) shim that tries to make the counters - look like the old Win16 API (which is also used by Win95). Under NT - 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++) - { - dwSize = cbPerfData; - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: get perf data\n" ); - - status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, _T("Global"), NULL, - NULL, (LPBYTE) pPerfData, &dwSize); - if (status == ERROR_SUCCESS) - { - 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 = gcry_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; - } - } - 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 - implicitly opened on the first call to RegQueryValueEx()). If this - isn't done then any system components which provide performance data - can't be removed or changed while the handle remains active. */ - RegCloseKey (HKEY_PERFORMANCE_DATA); -} - - -static void -slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), - enum random_origins requester ) -{ - static int is_initialized = 0; - static int is_workstation = 1; - HANDLE hDevice; - DWORD dwType, dwSize, dwResult; - ULONG ulSize; - int drive_no, status; - int no_results = 0; - void *buffer; - - if ( !is_initialized ) - { - HKEY hKey; - - if ( debug_me ) - 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"), - 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - BYTE szValue[32 + 8]; - dwSize = 32; - - if ( debug_me ) - log_debug ("rndw32#slow_gatherer: check product options\n" ); - - status = RegQueryValueEx (hKey, _T("ProductType"), 0, NULL, - szValue, &dwSize); - if (status == ERROR_SUCCESS && _stricmp (szValue, "WinNT")) - { - /* Note: There are (at least) three cases for ProductType: - WinNT = NT Workstation, ServerNT = NT Server, LanmanNT = - NT Server acting as a Domain Controller. */ - is_workstation = 0; - if ( debug_me ) - log_debug ("rndw32: this is a NT server\n"); - } - RegCloseKey (hKey); - } - - /* The following are fixed for the lifetime of the process so we - only add them once */ - /* readPnPData (); - we have not implemented that. */ - - /* Initialize the NetAPI32 function pointers if necessary */ - hNetAPI32 = LoadLibraryA("NETAPI32.DLL"); - if (hNetAPI32) - { - if (debug_me) - log_debug ("rndw32#slow_gatherer: netapi32 loaded\n" ); - pNetStatisticsGet = (NETSTATISTICSGET) - GetProcAddress (hNetAPI32, "NetStatisticsGet"); - pNetApiBufferSize = (NETAPIBUFFERSIZE) - GetProcAddress (hNetAPI32, "NetApiBufferSize"); - pNetApiBufferFree = (NETAPIBUFFERFREE) - GetProcAddress (hNetAPI32, "NetApiBufferFree"); - - if (!pNetStatisticsGet || !pNetApiBufferSize || !pNetApiBufferFree) - { - FreeLibrary (hNetAPI32); - hNetAPI32 = NULL; - log_debug ("rndw32: No NETAPI found\n" ); - } - } - - /* Initialize the NT kernel native API function pointers if necessary */ - hNTAPI = GetModuleHandleA("NTDll.dll"); - if (hNTAPI) - { - /* Get a pointer to the NT native information query functions */ - pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION) - GetProcAddress (hNTAPI, "NtQuerySystemInformation"); - pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS) - GetProcAddress (hNTAPI, "NtQueryInformationProcess"); - pNtPowerInformation = (NTPOWERINFORMATION) - GetProcAddress(hNTAPI, "NtPowerInformation"); - - if (!pNtQuerySystemInformation || !pNtQueryInformationProcess) - hNTAPI = NULL; - } - - - 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 - majority of the network traffic will be via the appropriate service. - In any case the network statistics return almost no randomness. */ - { - LPBYTE lpBuffer; - - if (hNetAPI32 - && !pNetStatisticsGet (NULL, - is_workstation ? L"LanmanWorkstation" : - L"LanmanServer", 0, 0, &lpBuffer)) - { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer: get netstats\n" ); - pNetApiBufferSize (lpBuffer, &dwSize); - (*add) ( lpBuffer, dwSize, requester ); - pNetApiBufferFree (lpBuffer); - } - } - - /* Get disk I/O statistics for all the hard drives. 100 is an - arbitrary failsafe limit. */ - for (drive_no = 0; drive_no < 100 ; drive_no++) - { - 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, - 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; - if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, - diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT, - &dwSize, NULL)) - { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer: iostat drive %d\n", - drive_no); - (*add) (diskPerformance, dwSize, requester); - } - else - { - log_info ("NOTE: you should run 'diskperf -y' " - "to enable the disk statistics\n"); - } - CloseHandle (hDevice); - } - - /* In theory we should be using the Win32 performance query API to obtain - unpredictable data from the system, however this is so unreliable (see - the multiple sets of comments in registryPoll()) that it's too risky - to rely on it except as a fallback in emergencies. Instead, we rely - mostly on the NT native API function NtQuerySystemInformation(), which - has the dual advantages that it doesn't have as many (known) problems - as the Win32 equivalent and that it doesn't access the data indirectly - via pseudo-registry keys, which means that it's much faster. Note - that the Win32 equivalent actually works almost all of the time, the - problem is that on one or two systems it can fail in strange ways that - are never the same and can't be reproduced on any other system, which - is why we use the native API here. Microsoft officially documented - this function in early 2003, so it'll be fairly safe to use. */ - if ( !hNTAPI ) - { - registry_poll (add, requester); - return; - } - - - /* Scan the first 64 possible information types (we don't bother with - increasing the buffer size as we do with the Win32 version of the - performance data read, we may miss a few classes but it's no big deal). - 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); - for (dwType = 0; dwType < 64; dwType++) - { - switch (dwType) - { - /* ID 17 = SystemObjectInformation hangs on some win2k systems. */ - case 17: - if (system_is_w2000) - continue; - break; - - /* Some information types are write-only (the IDs are shared with - a set-information call), we skip these. */ - case 26: case 27: case 38: case 46: case 47: case 48: case 52: - continue; - - /* ID 53 = SystemSessionProcessInformation reads input from the - output buffer, which has to contain a session ID and pointer - to the actual buffer in which to store the session information. - Because this isn't a standard query, we skip this. */ - case 53: - continue; - } - - /* Query the info for this ID. Some results (for example for - ID = 6, SystemCallCounts) are only available in checked builds - of the kernel. A smaller subcless of results require that - certain system config flags be set, for example - SystemObjectInformation requires that the - FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags. To avoid - having to special-case all of these, we try reading each one and - only use those for which we get a success status. */ - dwResult = pNtQuerySystemInformation (dwType, buffer, - PERFORMANCE_BUFFER_SIZE - 2048, - &ulSize); - if (dwResult != ERROR_SUCCESS) - continue; - - /* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24, - SystemDpcInformation) incorrectly return a length of zero, so we - manually adjust the length to the correct value. */ - if ( !ulSize ) - { - if (dwType == 23) - ulSize = 6 * sizeof (ULONG); - else if (dwType == 24) - ulSize = 5 * sizeof (ULONG); - } - - /* If we got some data back, add it to the entropy pool. */ - if (ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048) - { - if (debug_me) - log_debug ("rndw32#slow_gatherer: %lu bytes from sysinfo %ld\n", - ulSize, dwType); - (*add) (buffer, ulSize, requester); - no_results++; - } - } - - /* Now we would do the same for the process information. This - call would rather ugly in that it requires an exact length - match for the data returned, failing with a - STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if the - length isn't an exact match. It requires a compiler to handle - complex nested structs, alignment issues, and so on, and - without the headers in which the entries are declared it's - almost impossible to do. Thus we don't. */ - - - /* Finally, do the same for the system power status information. There - are only a limited number of useful information types available so we - restrict ourselves to the useful types. In addition since this - function doesn't return length information, we have to hardcode in - length data. */ - if (pNtPowerInformation) - { - static const struct { int type; int size; } powerInfo[] = { - { 0, 128 }, /* SystemPowerPolicyAc */ - { 1, 128 }, /* SystemPowerPolicyDc */ - { 4, 64 }, /* SystemPowerCapabilities */ - { 5, 48 }, /* SystemBatteryState */ - { 11, 48 }, /* ProcessorInformation */ - { 12, 24 }, /* SystemPowerInformation */ - { -1, -1 } - }; - int i; - - /* The 100 is a failsafe limit. */ - for (i = 0; powerInfo[i].type != -1 && i < 100; i++ ) - { - /* Query the info for this ID */ - dwResult = pNtPowerInformation (powerInfo[i].type, NULL, 0, buffer, - PERFORMANCE_BUFFER_SIZE - 2048); - if (dwResult != ERROR_SUCCESS) - continue; - if (debug_me) - log_debug ("rndw32#slow_gatherer: %u bytes from powerinfo %d\n", - powerInfo[i].size, i); - (*add) (buffer, powerInfo[i].size, requester); - no_results++; - } - gcry_assert (i < 100); - } - gcry_free (buffer); - - /* We couldn't get enough results from the kernel, fall back to the - somewhat troublesome registry poll. */ - if (no_results < 15) - registry_poll (add, requester); -} - - -int -_gcry_rndw32_gather_random (void (*add)(const void*, size_t, - enum random_origins), - enum random_origins origin, - size_t length, int level ) -{ - static int is_initialized; - - if (!level) - return 0; - - /* We don't differentiate between level 1 and 2 here because there - is no internal entropy pool as a scary resource. It may all work - slower, but because our entropy source will never block but - deliver some not easy to measure entropy, we assume level 2. */ - - if (!is_initialized) - { - OSVERSIONINFO osvi = { sizeof( osvi ) }; - - GetVersionEx( &osvi ); - 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 (); - is_initialized = 1; - } - - if (debug_me) - log_debug ("rndw32#gather_random: ori=%d len=%u lvl=%d\n", - origin, (unsigned int)length, level ); - - slow_gatherer (add, origin); - - return 0; -} - - - -void -_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, - enum random_origins), - enum random_origins origin) -{ - static int addedFixedItems = 0; - - if ( debug_me ) - log_debug ("rndw32#gather_random_fast: ori=%d\n", origin ); - - /* Get various basic pieces of system information: Handle of active - window, handle of window with mouse capture, handle of clipboard - owner handle of start of clpboard viewer list, pseudohandle of - current process, current process ID, pseudohandle of current - thread, current thread ID, handle of desktop window, handle of - window with keyboard focus, whether system queue has any events, - cursor position for last message, 1 ms time for last message, - handle of window with clipboard open, handle of process heap, - handle of procs window station, types of events in input queue, - and milliseconds since Windows was started. */ - - { - byte buffer[20*sizeof(ulong)], *bufptr; - - bufptr = buffer; -#define ADD(f) do { ulong along = (ulong)(f); \ - memcpy (bufptr, &along, sizeof (along) ); \ - bufptr += sizeof (along); \ - } while (0) - - ADD ( GetActiveWindow ()); - ADD ( GetCapture ()); - ADD ( GetClipboardOwner ()); - ADD ( GetClipboardViewer ()); - ADD ( GetCurrentProcess ()); - ADD ( GetCurrentProcessId ()); - ADD ( GetCurrentThread ()); - ADD ( GetCurrentThreadId ()); - ADD ( GetDesktopWindow ()); - ADD ( GetFocus ()); - ADD ( GetInputState ()); - ADD ( GetMessagePos ()); - ADD ( GetMessageTime ()); - ADD ( GetOpenClipboardWindow ()); - ADD ( GetProcessHeap ()); - ADD ( GetProcessWindowStation ()); - ADD ( GetQueueStatus (QS_ALLEVENTS)); - ADD ( 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; - SIZE_T minimumWorkingSetSize, maximumWorkingSetSize; - - 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 = GetCurrentProcess (); - GetProcessTimes (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 ); - - /* Get the minimum and maximum working set size for the current - process. */ - GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, - &maximumWorkingSetSize); - (*add) ( &minimumWorkingSetSize, - sizeof (minimumWorkingSetSize), origin ); - (*add) ( &maximumWorkingSetSize, - sizeof (maximumWorkingSetSize), origin ); - } - - - /* The following are fixed for the lifetime of the process so we only - * add them once */ - if (!addedFixedItems) - { - STARTUPINFO startupInfo; - - /* Get name of desktop, console window title, new window - position and size, window flags, and handles for stdin, - stdout, and stderr. */ - startupInfo.cb = sizeof (STARTUPINFO); - GetStartupInfo (&startupInfo); - (*add) ( &startupInfo, sizeof (STARTUPINFO), origin ); - addedFixedItems = 1; - } - - /* The performance of QPC varies depending on the architecture it's - running on and on the OS, the MS documentation is vague about the - details because it varies so much. Under Win9x/ME it reads the - 1.193180 MHz PIC timer. Under NT/Win2K/XP it may or may not read the - 64-bit TSC depending on the HAL and assorted other circumstances, - generally on machines with a uniprocessor HAL - KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines - with a multiprocessor or APIC HAL it uses the TSC (the exact time - source is controlled by the HalpUse8254 flag in the kernel). That - choice of time sources is somewhat peculiar because on a - multiprocessor machine it's theoretically possible to get completely - different TSC readings depending on which CPU you're currently - running on, while for uniprocessor machines it's not a problem. - However, the kernel appears to synchronise the TSCs across CPUs at - boot time (it resets the TSC as part of its system init), so this - 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 - match the current CPU speed), and hyperthreading Pentiums will turn - 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__ -/* FIXME: We would need to implement the CPU feature tests first. */ -/* if (cpu_has_feature_rdtsc) */ -/* { */ -/* uint32_t lo, hi; */ - /* We cannot use "=A", since this would use %rax on x86_64. */ -/* __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */ - /* Ignore high 32 bits, hwich are >1s res. */ -/* (*add) (&lo, 4, origin ); */ -/* } */ -/* else */ -#endif /*!__GNUC__*/ - { - LARGE_INTEGER performanceCount; - - if (QueryPerformanceCounter (&performanceCount)) - { - if ( debug_me ) - log_debug ("rndw32#gather_random_fast: perf data\n"); - (*add) (&performanceCount, sizeof (performanceCount), origin); - } - else - { - /* Millisecond accuracy at best... */ - DWORD aword = GetTickCount (); - (*add) (&aword, sizeof (aword), origin ); - } - } - - -} |
