summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/libgcrypt-1.4.6/random
diff options
context:
space:
mode:
authorRené Schümann <white06tiger@gmail.com>2015-03-14 19:56:55 +0000
committerRené Schümann <white06tiger@gmail.com>2015-03-14 19:56:55 +0000
commitc60aed5432e9cda277b9351de51e82dfb8e02475 (patch)
tree97ccd1ea8e2544f6a9673ee7d04c18b714877a35 /plugins/MirOTR/libgcrypt-1.4.6/random
parentd2b26b1f86326362f56540b5185fa09ab5f2779c (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.h137
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/random-csprng.c1397
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/random-daemon.c360
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/random-fips.c1118
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/random.c323
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/random.h72
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/rndegd.c290
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/rndhw.c138
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/rndlinux.c167
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/rndunix.c883
-rw-r--r--plugins/MirOTR/libgcrypt-1.4.6/random/rndw32.c981
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 );
- }
- }
-
-
-}