diff --git a/random/random-csprng.c b/random/random-csprng.c index 1664b708..6d6c082e 100644 --- a/random/random-csprng.c +++ b/random/random-csprng.c @@ -1,1377 +1,1378 @@ /* random-csprng.c - CSPRNG style random number generator (libgcrypt classic) * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, * 2007, 2008, 2010, 2012 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* 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 #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GETHRTIME #include #endif #ifdef HAVE_GETTIMEOFDAY #include #endif #ifdef HAVE_GETRUSAGE #include #endif #ifdef __MINGW32__ #include #endif #ifdef HAVE_W32_SYSTEM #include #endif #include "g10lib.h" #include "random.h" #include "rand-internal.h" #include "cipher.h" /* _gcry_sha1_hash_buffer */ #include "../cipher/sha1.h" /* _gcry_sha1_mixblock */ #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 (sha-1). */ /* 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 reading 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 other 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 registered at initialization 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 initialization. After initialization it is guaranteed to point to function. (On systems without a random gatherer module a dummy function is used).*/ static int (*slow_gather_fnc)(void (*)(const void*, size_t, enum random_origins), enum random_origins, size_t, int); /* This function is set to the actual fast entropy gathering function during initialization. If it is NULL, no such function is available. */ static void (*fast_gather_fnc)(void (*)(const void*, size_t, enum random_origins), enum random_origins); /* 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; /* This is the lock we use to protect all pool operations. */ GPGRT_LOCK_DEFINE (pool_lock); /* This is a helper for assert calls. These calls are used to assert that functions are called in a locked state. It is not meant to be thread-safe but as a method to get aware of missing locks in the test suite. */ static int pool_is_locked; /* 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); /* --- 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; if (!initialized) { initialized = 1; #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 = gpgrt_lock_lock (&pool_lock); if (err) log_fatal ("failed to acquire the pool lock: %s\n", gpg_strerror (err)); pool_is_locked = 1; } /* Release the pool lock. */ static void unlock_pool (void) { int err; pool_is_locked = 0; err = gpgrt_lock_unlock (&pool_lock); if (err) log_fatal ("failed to release the pool lock: %s\n", gpg_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 ? xcalloc_secure (1, POOLSIZE + BLOCKLEN) : xcalloc (1, POOLSIZE + BLOCKLEN)); keypool = (secure_alloc ? xcalloc_secure (1, POOLSIZE + BLOCKLEN) : xcalloc (1, POOLSIZE + BLOCKLEN)); /* Setup the slow entropy gathering function. The code requires that this function exists. */ slow_gather_fnc = getfnc_gather_random (); /* 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 (); } /* Try to close the FDs of the random gather module. This is currently only implemented for rndlinux. */ void _gcry_rngcsprng_close_fds (void) { lock_pool (); #if USE_RNDGETENTROPY _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0); -#elif USE_RNDLINUX +#endif +#if USE_RNDLINUX _gcry_rndlinux_gather_random (NULL, 0, 0, 0); #endif pool_filled = 0; /* Force re-open on next use. */ unlock_pool (); } 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 initialization 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 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 600 byte pool. Note that the 64 byte scratch area directly * follows the pool. The numbers in the diagram give the number of * bytes. * <................600...............> <.64.> * pool |------------------------------------| |------| * <20><.24.> <20> * | | +-----+ * +-----|-------------------------------|-+ * +-------------------------------|-|-+ * v v v * |------| * * +---------------------------------------+ * v * <20> * pool' |------------------------------------| * <20><20><.24.> * +---|-----|---------------------------+ * +-----|---------------------------|-+ * +---------------------------|-|-+ * v v v * |------| * * | * +-----------------------------------+ * v * <20> * pool'' |------------------------------------| * <20><20><20><.24.> * +---|-----|-----------------------+ * +-----|-----------------------|-+ * +-----------------------|-|-+ * v v v * * and so on until we did this for all 30 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; SHA1_CONTEXT md; unsigned int nburn; #if DIGESTLEN != 20 #error must have a digest length of 20 for SHA-1 #endif gcry_assert (pool_is_locked); _gcry_sha1_mixblock_init (&md); /* pool_0 -> pool'. */ pend = pool + POOLSIZE; memcpy (hashbuf, pend - DIGESTLEN, DIGESTLEN); memcpy (hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); nburn = _gcry_sha1_mixblock (&md, hashbuf); memcpy (pool, hashbuf, DIGESTLEN); if (failsafe_digest_valid && pool == rndpool) { for (i=0; i < DIGESTLEN; i++) pool[i] ^= failsafe_digest[i]; } /* Loop for the remaining iterations. */ p = pool; for (n=1; n < POOLBLOCKS; n++) { if (p + BLOCKLEN < pend) memcpy (hashbuf, p, BLOCKLEN); else { unsigned char *pp = p; for (i=0; i < BLOCKLEN; i++ ) { if ( pp >= pend ) pp = pool; hashbuf[i] = *pp++; } } _gcry_sha1_mixblock (&md, hashbuf); p += DIGESTLEN; memcpy (p, hashbuf, DIGESTLEN); } /* 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_sha1_hash_buffer (failsafe_digest, pool, POOLSIZE); failsafe_digest_valid = 1; } _gcry_burn_stack (nburn); } void _gcry_rngcsprng_set_seed_file (const char *name) { if (seed_file_name) BUG (); seed_file_name = xstrdup (name); } /* Helper for my_open. * Return a malloced wide char string from an UTF-8 encoded input * string STRING. Caller must free this value. Returns NULL and sets * ERRNO on failure. Calling this function with STRING set to NULL is * not defined. */ #ifdef HAVE_W32_SYSTEM static wchar_t * utf8_to_wchar (const char *string) { int n; size_t nbytes; wchar_t *result; n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); if (n < 0) { gpg_err_set_errno (EINVAL); return NULL; } nbytes = (size_t)(n+1) * sizeof(*result); if (nbytes / sizeof(*result) != (n+1)) { gpg_err_set_errno (ENOMEM); return NULL; } result = xtrymalloc (nbytes); if (!result) return NULL; n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); if (n < 0) { xfree (result); gpg_err_set_errno (EINVAL); result = NULL; } return result; } #endif /*HAVE_W32_SYSTEM*/ /* Helper for my_open. */ #ifdef HAVE_W32_SYSTEM static int any8bitchar (const char *string) { if (string) for ( ; *string; string++) if ((*string & 0x80)) return 1; return 0; } #endif /*HAVE_W32_SYSTEM*/ /* A wrapper around open to handle Unicode file names under Windows. */ static int my_open (const char *name, int flags, unsigned int mode) { #ifdef HAVE_W32_SYSTEM if (any8bitchar (name)) { wchar_t *wname; int ret; wname = utf8_to_wchar (name); if (!wname) return -1; ret = _wopen (wname, flags, mode); xfree (wname); return ret; } else return open (name, flags, mode); #else return open (name, flags, mode); #endif } /* 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) { #ifdef __GCC__ #warning Check whether we can lock on Windows. #endif #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++ ; } #else (void)fd; (void)fname; (void)for_write; #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 32 bytes from a non-blocking entropy source. 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 32 bytes" above to 0. Then the dependencies of the initial 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 = my_open (seed_file_name, O_RDONLY | O_BINARY, 0); #else fd = my_open (seed_file_name, O_RDONLY, 0); #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. If we have the * Jitter RNG we can fast get a lot of entropy. Thus we read 1024 * bits from that source. * * Without the Jitter RNG we keep the old method of reading only a * few bytes usually from /dev/urandom which won't block. */ if (_gcry_rndjent_get_version (NULL)) read_random_source (RANDOM_ORIGIN_INIT, 128, GCRY_STRONG_RANDOM); else read_random_source (RANDOM_ORIGIN_INIT, 32, GCRY_STRONG_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*)(void*)keypool, sp=(unsigned long*)(void*)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 = my_open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR ); #else # if LOCK_SEED_FILE fd = my_open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR ); # else fd = my_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 < 16) /* At least 128 bits. */ needed = 16; 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*)(void*)keypool, sp=(unsigned long*)(void*)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_RNDGETENTROPY fnc = _gcry_rndgetentropy_gather_random; return fnc; #endif #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 #if USE_RNDW32CE fnc = _gcry_rndw32ce_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 #if USE_RNDW32CE return _gcry_rndw32ce_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 available 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 initialized and to lock the pool. Note, that this function is a NOP unless a random function has been used or _gcry_initialize (1) has been used. We use this hack so that the internal use of this function in cipher_open and md_open won't start filling up the 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 origin, 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, origin, length, level) < 0) log_fatal ("No way to gather entropy for the RNG\n"); } diff --git a/random/random-drbg.c b/random/random-drbg.c index dc8c7044..d44d11db 100644 --- a/random/random-drbg.c +++ b/random/random-drbg.c @@ -1,2673 +1,2674 @@ /* random-drbg.c - Deterministic Random Bits Generator * Copyright 2014 Stephan Mueller * * DRBG: Deterministic Random Bits Generator * Based on NIST Recommended DRBG from NIST SP800-90A with the following * properties: * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * with and without prediction resistance * * Redistribution 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 the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * LGPLv2+, in which case the provisions of the LGPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the LGPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * * gcry_control GCRYCTL_DRBG_REINIT * ================================ * This control request re-initializes the DRBG completely, i.e. the entire * state of the DRBG is zeroized (with two exceptions listed in * GCRYCTL_DRBG_SET_ENTROPY). * * The control request takes the following values which influences how * the DRBG is re-initialized: * * - const char *flagstr * * This variable specifies the DRBG type to be used for the next * initialization. If set to NULL, the previous DRBG type is * used for the initialization. If not NULL a space separated * list of tokens with associated flag values is expected which * are ORed to form the mandatory flags of the requested DRBG * strength and cipher type. Optionally, the prediction * resistance flag can be ORed into the flags variable. * * | String token | Flag value | * |--------------+------------------------| * | aes | DRBG_CTRAES | * | serpent | DRBG_CTRSERPENT | * | twofish | DRBG_CTRTWOFISH | * | sha1 | DRBG_HASHSHA1 | * | sha256 | DRBG_HASHSHA256 | * | sha512 | DRBG_HASHSHA512 | * | hmac | DRBG_HMAC | * | sym128 | DRBG_SYM128 | * | sym192 | DRBG_SYM192 | * | sym256 | DRBG_SYM256 | * | pr | DRBG_PREDICTION_RESIST | * * For example: * * - CTR-DRBG with AES-128 without prediction resistance: * "aes sym128" * - HMAC-DRBG with SHA-512 with prediction resistance: * "hmac sha512 pr" * * - gcry_buffer_t *pers * * NULL terminated array with personalization strings to be used * for initialization. * * - int npers * * Size of PERS. * * - void *guard * * A value of NULL must be passed for this. * * The variable of flags is independent from the pers/perslen variables. If * flags is set to 0 and perslen is set to 0, the current DRBG type is * completely reset without using a personalization string. * * DRBG Usage * ========== * The SP 800-90A DRBG allows the user to specify a personalization string * for initialization as well as an additional information string for each * random number request. The following code fragments show how a caller * uses the API to use the full functionality of the DRBG. * * Usage without any additional data * --------------------------------- * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); * * * Usage with personalization string during initialization * ------------------------------------------------------- * drbg_string_t pers; * char personalization[11] = "some-string"; * * drbg_string_fill(&pers, personalization, strlen(personalization)); * // The reset completely re-initializes the DRBG with the provided * // personalization string without changing the DRBG type * ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers); * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); * * * Usage with additional information string during random number request * --------------------------------------------------------------------- * drbg_string_t addtl; * char addtl_string[11] = "some-string"; * * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string)); * // The following call is a wrapper to gcry_randomize() and returns * // the same error codes. * gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl); * * * Usage with personalization and additional information strings * ------------------------------------------------------------- * Just mix both scenarios above. * * * Switch the DRBG type to some other type * --------------------------------------- * // Switch to CTR DRBG AES-128 without prediction resistance * ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL); * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); */ #include #include #include #include #include "g10lib.h" #include "random.h" #include "rand-internal.h" #include "../cipher/bufhelp.h" /****************************************************************** * Constants ******************************************************************/ /* * DRBG flags bitmasks * * 31 (B) 28 19 (A) 0 * +-+-+-+--------+---+-----------+-----+ * |~|~|u|~~~~~~~~| 3 | 2 | 1 | * +-+-+-+--------+- -+-----------+-----+ * ctl flg| |drbg use selection flags * */ /* Internal state control flags (B) */ #define DRBG_PREDICTION_RESIST ((u32)1<<28) /* CTR type modifiers (A.1)*/ #define DRBG_CTRAES ((u32)1<<0) #define DRBG_CTRSERPENT ((u32)1<<1) #define DRBG_CTRTWOFISH ((u32)1<<2) #define DRBG_CTR_MASK (DRBG_CTRAES | DRBG_CTRSERPENT \ | DRBG_CTRTWOFISH) /* HASH type modifiers (A.2)*/ #define DRBG_HASHSHA1 ((u32)1<<4) #define DRBG_HASHSHA224 ((u32)1<<5) #define DRBG_HASHSHA256 ((u32)1<<6) #define DRBG_HASHSHA384 ((u32)1<<7) #define DRBG_HASHSHA512 ((u32)1<<8) #define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 \ | DRBG_HASHSHA256 | DRBG_HASHSHA384 \ | DRBG_HASHSHA512) /* type modifiers (A.3)*/ #define DRBG_HMAC ((u32)1<<12) #define DRBG_SYM128 ((u32)1<<13) #define DRBG_SYM192 ((u32)1<<14) #define DRBG_SYM256 ((u32)1<<15) #define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_SYM128 | DRBG_SYM192 \ | DRBG_SYM256) #define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK \ | DRBG_TYPE_MASK) #define DRBG_PR_CTRAES128 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM128) #define DRBG_PR_CTRAES192 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM192) #define DRBG_PR_CTRAES256 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM256) #define DRBG_NOPR_CTRAES128 (DRBG_CTRAES | DRBG_SYM128) #define DRBG_NOPR_CTRAES192 (DRBG_CTRAES | DRBG_SYM192) #define DRBG_NOPR_CTRAES256 (DRBG_CTRAES | DRBG_SYM256) #define DRBG_PR_HASHSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1) #define DRBG_PR_HASHSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256) #define DRBG_PR_HASHSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384) #define DRBG_PR_HASHSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512) #define DRBG_NOPR_HASHSHA1 (DRBG_HASHSHA1) #define DRBG_NOPR_HASHSHA256 (DRBG_HASHSHA256) #define DRBG_NOPR_HASHSHA384 (DRBG_HASHSHA384) #define DRBG_NOPR_HASHSHA512 (DRBG_HASHSHA512) #define DRBG_PR_HMACSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1 \ | DRBG_HMAC) #define DRBG_PR_HMACSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256 \ | DRBG_HMAC) #define DRBG_PR_HMACSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384 \ | DRBG_HMAC) #define DRBG_PR_HMACSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512 \ | DRBG_HMAC) #define DRBG_NOPR_HMACSHA1 (DRBG_HASHSHA1 | DRBG_HMAC) #define DRBG_NOPR_HMACSHA256 (DRBG_HASHSHA256 | DRBG_HMAC) #define DRBG_NOPR_HMACSHA384 (DRBG_HASHSHA384 | DRBG_HMAC) #define DRBG_NOPR_HMACSHA512 (DRBG_HASHSHA512 | DRBG_HMAC) /* The default DRGB type. */ #define DRBG_DEFAULT_TYPE DRBG_NOPR_HMACSHA256 #define DRBG_CTR_NULL_LEN 128 /****************************************************************** * Common data structures ******************************************************************/ /* * SP800-90A requires the concatenation of different data. To avoid copying * buffers around or allocate additional memory, the following data structure * is used to point to the original memory with its size. In addition, it * is used to build a linked list. The linked list defines the concatenation * of individual buffers. The order of memory block referenced in that * linked list determines the order of concatenation. */ struct drbg_string_s { const unsigned char *buf; size_t len; struct drbg_string_s *next; }; typedef struct drbg_string_s drbg_string_t; /* DRBG input data structure for DRBG generate with additional * information string. */ struct drbg_gen_s { unsigned char *outbuf; /* output buffer for random numbers */ unsigned int outlen; /* size of output buffer */ drbg_string_t *addtl; /* input buffer for * additional information string */ }; typedef struct drbg_gen_s drbg_gen_t; /* Forward declaration of the state object pointer. */ struct drbg_state_s; typedef struct drbg_state_s *drbg_state_t; struct drbg_core_s { u32 flags; /* flags for the cipher */ ushort statelen; /* maximum state length */ ushort blocklen_bytes; /* block size of output in bytes */ int backend_cipher; /* libgcrypt backend cipher */ }; struct drbg_state_ops_s { gpg_err_code_t (*update) (drbg_state_t drbg, drbg_string_t *seed, int reseed); gpg_err_code_t (*generate) (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl); gpg_err_code_t (*crypto_init) (drbg_state_t drbg); void (*crypto_fini) (drbg_state_t drbg); }; struct drbg_test_data_s { drbg_string_t *testentropy; /* TEST PARAMETER: test entropy */ int fail_seed_source:1; /* If set, the seed function will * return an error. */ }; /* This state object keeps the state of an DRBG instance. */ struct drbg_state_s { unsigned char *V; /* internal state 10.1.1.1 1a) */ unsigned char *C; /* hash: static value 10.1.1.1 1b) * hmac / ctr: key */ size_t reseed_ctr; /* Number of RNG requests since last reseed -- * 10.1.1.1 1c) */ unsigned char *scratchpad; /* some memory the DRBG can use for its * operation -- allocated during init */ void *priv_data; /* Cipher handle */ gcry_cipher_hd_t ctr_handle; /* CTR mode cipher handle */ int seeded:1; /* DRBG fully seeded? */ int pr:1; /* Prediction resistance enabled? */ /* Taken from libgcrypt ANSI X9.31 DRNG: 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 seed_init_pid; const struct drbg_state_ops_s *d_ops; const struct drbg_core_s *core; struct drbg_test_data_s *test_data; }; enum drbg_prefixes { DRBG_PREFIX0 = 0x00, DRBG_PREFIX1, DRBG_PREFIX2, DRBG_PREFIX3 }; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) /*************************************************************** * Global variables ***************************************************************/ /* Global state variable holding the current instance of the DRBG. */ static drbg_state_t drbg_state; /* This is the lock variable we use to serialize access to this RNG. */ GPGRT_LOCK_DEFINE(drbg_lock_var); /*************************************************************** * Backend cipher definitions available to DRBG ***************************************************************/ static const struct drbg_core_s drbg_cores[] = { /* Hash DRBGs */ {DRBG_HASHSHA1, 55, 20, GCRY_MD_SHA1}, {DRBG_HASHSHA256, 55, 32, GCRY_MD_SHA256}, {DRBG_HASHSHA384, 111, 48, GCRY_MD_SHA384}, {DRBG_HASHSHA512, 111, 64, GCRY_MD_SHA512}, /* HMAC DRBGs */ {DRBG_HASHSHA1 | DRBG_HMAC, 20, 20, GCRY_MD_SHA1}, {DRBG_HASHSHA256 | DRBG_HMAC, 32, 32, GCRY_MD_SHA256}, {DRBG_HASHSHA384 | DRBG_HMAC, 48, 48, GCRY_MD_SHA384}, {DRBG_HASHSHA512 | DRBG_HMAC, 64, 64, GCRY_MD_SHA512}, /* block ciphers */ {DRBG_CTRAES | DRBG_SYM128, 32, 16, GCRY_CIPHER_AES128}, {DRBG_CTRAES | DRBG_SYM192, 40, 16, GCRY_CIPHER_AES192}, {DRBG_CTRAES | DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256} }; static gpg_err_code_t drbg_hash_init (drbg_state_t drbg); static gpg_err_code_t drbg_hmac_init (drbg_state_t drbg); static gpg_err_code_t drbg_hmac_setkey (drbg_state_t drbg, const unsigned char *key); static void drbg_hash_fini (drbg_state_t drbg); static byte *drbg_hash (drbg_state_t drbg, const drbg_string_t *buf); static gpg_err_code_t drbg_sym_init (drbg_state_t drbg); static void drbg_sym_fini (drbg_state_t drbg); static gpg_err_code_t drbg_sym_setkey (drbg_state_t drbg, const unsigned char *key); static gpg_err_code_t drbg_sym (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf); static gpg_err_code_t drbg_sym_ctr (drbg_state_t drbg, const unsigned char *inbuf, unsigned int inbuflen, unsigned char *outbuf, unsigned int outbuflen); /****************************************************************** ****************************************************************** ****************************************************************** * Generic DRBG code ****************************************************************** ****************************************************************** ******************************************************************/ /****************************************************************** * Generic helper functions ******************************************************************/ #if 0 #define dbg(x) do { log_debug x; } while(0) #else #define dbg(x) #endif /* * Parse a string of flags and store the flag values at R_FLAGS. * Return 0 on success. */ static gpg_err_code_t parse_flag_string (const char *string, u32 *r_flags) { struct { const char *name; u32 flag; } table[] = { { "aes", DRBG_CTRAES }, { "serpent", DRBG_CTRSERPENT }, { "twofish", DRBG_CTRTWOFISH }, { "sha1", DRBG_HASHSHA1 }, { "sha256", DRBG_HASHSHA256 }, { "sha512", DRBG_HASHSHA512 }, { "hmac", DRBG_HMAC }, { "sym128", DRBG_SYM128 }, { "sym192", DRBG_SYM192 }, { "sym256", DRBG_SYM256 }, { "pr", DRBG_PREDICTION_RESIST } }; *r_flags = 0; if (string) { char **tl; const char *s; int i, j; tl = _gcry_strtokenize (string, NULL); if (!tl) return gpg_err_code_from_syserror (); for (i=0; (s=tl[i]); i++) { for (j=0; j < DIM (table); j++) if (!strcmp (s, table[j].name)) { *r_flags |= table[j].flag; break; } if (!(j < DIM (table))) { xfree (tl); return GPG_ERR_INV_FLAG; } } xfree (tl); } return 0; } static inline void drbg_string_fill (drbg_string_t *string, const unsigned char *buf, size_t len) { string->buf = buf; string->len = len; string->next = NULL; } static inline ushort drbg_statelen (drbg_state_t drbg) { if (drbg && drbg->core) return drbg->core->statelen; return 0; } static inline ushort drbg_blocklen (drbg_state_t drbg) { if (drbg && drbg->core) return drbg->core->blocklen_bytes; return 0; } static inline ushort drbg_keylen (drbg_state_t drbg) { if (drbg && drbg->core) return (drbg->core->statelen - drbg->core->blocklen_bytes); return 0; } static inline size_t drbg_max_request_bytes (void) { /* SP800-90A requires the limit 2**19 bits, but we return bytes */ return (1 << 16); } static inline size_t drbg_max_addtl (void) { /* SP800-90A requires 2**35 bytes additional info str / pers str */ #ifdef __LP64__ return (1UL << 35); #else /* * SP800-90A allows smaller maximum numbers to be returned -- we * return SIZE_MAX - 1 to allow the verification of the enforcement * of this value in drbg_healthcheck_sanity. */ return (SIZE_MAX - 1); #endif } static inline size_t drbg_max_requests (void) { /* SP800-90A requires 2**48 maximum requests before reseeding */ #ifdef __LP64__ return (1UL << 48); #else return SIZE_MAX; #endif } /* * Return strength of DRBG according to SP800-90A section 8.4 * * flags: DRBG flags reference * * Return: normalized strength value or 32 as a default to counter * programming errors */ static inline unsigned short drbg_sec_strength (u32 flags) { if ((flags & DRBG_HASHSHA1) || (flags & DRBG_SYM128)) return 16; else if (flags & DRBG_SYM192) return 24; else if ((flags & DRBG_SYM256) || (flags & DRBG_HASHSHA256) || (flags & DRBG_HASHSHA384) || (flags & DRBG_HASHSHA512)) return 32; else return 32; } static void drbg_add_buf (unsigned char *dst, size_t dstlen, unsigned char *add, size_t addlen) { /* implied: dstlen > addlen */ unsigned char *dstptr, *addptr; unsigned int remainder = 0; size_t len = addlen; dstptr = dst + (dstlen - 1); addptr = add + (addlen - 1); while (len) { remainder += *dstptr + *addptr; *dstptr = remainder & 0xff; remainder >>= 8; len--; dstptr--; addptr--; } len = dstlen - addlen; while (len && remainder > 0) { remainder = *dstptr + 1; *dstptr = remainder & 0xff; remainder >>= 8; len--; dstptr--; } } /* Helper variables for read_cb(). * * The _gcry_rnd*_gather_random interface does not allow to provide a * data pointer. Thus we need to use a global variable for * communication. However, the then required locking is anyway a good * idea because it does not make sense to have several readers of (say * /dev/random). It is easier to serve them one after the other. */ static unsigned char *read_cb_buffer; /* The buffer. */ static size_t read_cb_size; /* Size of the buffer. */ static size_t read_cb_len; /* Used length. */ /* Callback for generating seed from kernel device. */ static void drbg_read_cb (const void *buffer, size_t length, enum random_origins origin) { const unsigned char *p = buffer; (void) origin; gcry_assert (read_cb_buffer); /* Note that we need to protect against gatherers returning more * than the requested bytes (e.g. rndw32). */ while (length-- && read_cb_len < read_cb_size) read_cb_buffer[read_cb_len++] = *p++; } static inline int drbg_get_entropy (drbg_state_t drbg, unsigned char *buffer, size_t len) { int rc = 0; /* Perform testing as defined in 11.3.2 */ if (drbg->test_data && drbg->test_data->fail_seed_source) return -1; read_cb_buffer = buffer; read_cb_size = len; read_cb_len = 0; #if USE_RNDGETENTROPY rc = _gcry_rndgetentropy_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDLINUX rc = _gcry_rndlinux_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDUNIX rc = _gcry_rndunix_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDW32 do { rc = _gcry_rndw32_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); } while (rc >= 0 && read_cb_len < read_cb_size); #else rc = -1; #endif return rc; } /****************************************************************** * CTR DRBG callback functions ******************************************************************/ /* BCC function for CTR DRBG as defined in 10.4.3 */ static gpg_err_code_t drbg_ctr_bcc (drbg_state_t drbg, unsigned char *out, const unsigned char *key, drbg_string_t *in) { gpg_err_code_t ret = GPG_ERR_GENERAL; drbg_string_t *curr = in; size_t inpos = curr->len; const unsigned char *pos = curr->buf; drbg_string_t data; drbg_string_fill (&data, out, drbg_blocklen (drbg)); /* 10.4.3 step 1 */ memset (out, 0, drbg_blocklen (drbg)); ret = drbg_sym_setkey(drbg, key); if (ret) return ret; /* 10.4.3 step 2 / 4 */ while (inpos) { short cnt = 0; /* 10.4.3 step 4.1 */ for (cnt = 0; cnt < drbg_blocklen (drbg); cnt++) { out[cnt] ^= *pos; pos++; inpos--; /* the following branch implements the linked list * iteration. If we are at the end of the current data * set, we have to start using the next data set if * available -- the inpos value always points to the * current byte and will be zero if we have processed * the last byte of the last linked list member */ if (0 == inpos) { curr = curr->next; if (NULL != curr) { pos = curr->buf; inpos = curr->len; } else { inpos = 0; break; } } } /* 10.4.3 step 4.2 */ ret = drbg_sym (drbg, out, &data); if (ret) return ret; /* 10.4.3 step 2 */ } return 0; } /* * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df * (and drbg_ctr_bcc, but this function does not need any temporary buffers), * the scratchpad is used as follows: * drbg_ctr_update: * temp * start: drbg->scratchpad * length: drbg_statelen(drbg) + drbg_blocklen(drbg) * note: the cipher writing into this variable works * blocklen-wise. Now, when the statelen is not a multiple * of blocklen, the generateion loop below "spills over" * by at most blocklen. Thus, we need to give sufficient * memory. * df_data * start: drbg->scratchpad + * drbg_statelen(drbg) + * drbg_blocklen(drbg) * length: drbg_statelen(drbg) * * drbg_ctr_df: * pad * start: df_data + drbg_statelen(drbg) * length: drbg_blocklen(drbg) * iv * start: pad + drbg_blocklen(drbg) * length: drbg_blocklen(drbg) * temp * start: iv + drbg_blocklen(drbg) * length: drbg_satelen(drbg) + drbg_blocklen(drbg) * note: temp is the buffer that the BCC function operates * on. BCC operates blockwise. drbg_statelen(drbg) * is sufficient when the DRBG state length is a multiple * of the block size. For AES192 (and maybe other ciphers) * this is not correct and the length for temp is * insufficient (yes, that also means for such ciphers, * the final output of all BCC rounds are truncated). * Therefore, add drbg_blocklen(drbg) to cover all * possibilities. */ /* Derivation Function for CTR DRBG as defined in 10.4.2 */ static gpg_err_code_t drbg_ctr_df (drbg_state_t drbg, unsigned char *df_data, size_t bytes_to_return, drbg_string_t *addtl) { gpg_err_code_t ret = GPG_ERR_GENERAL; unsigned char L_N[8]; /* S3 is input */ drbg_string_t S1, S2, S4, cipherin; drbg_string_t *tempstr = addtl; unsigned char *pad = df_data + drbg_statelen (drbg); unsigned char *iv = pad + drbg_blocklen (drbg); unsigned char *temp = iv + drbg_blocklen (drbg); size_t padlen = 0; unsigned int templen = 0; /* 10.4.2 step 7 */ unsigned int i = 0; /* 10.4.2 step 8 */ const unsigned char *K = (unsigned char *) "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; unsigned char *X; size_t generated_len = 0; size_t inputlen = 0; memset (pad, 0, drbg_blocklen (drbg)); memset (iv, 0, drbg_blocklen (drbg)); memset (temp, 0, drbg_statelen (drbg)); /* 10.4.2 step 1 is implicit as we work byte-wise */ /* 10.4.2 step 2 */ if ((512 / 8) < bytes_to_return) return GPG_ERR_INV_ARG; /* 10.4.2 step 2 -- calculate the entire length of all input data */ for (; NULL != tempstr; tempstr = tempstr->next) inputlen += tempstr->len; buf_put_be32 (&L_N[0], inputlen); /* 10.4.2 step 3 */ buf_put_be32 (&L_N[4], bytes_to_return); /* 10.4.2 step 5: length is size of L_N, input_string, one byte, padding */ padlen = (inputlen + sizeof (L_N) + 1) % (drbg_blocklen (drbg)); /* wrap the padlen appropriately */ if (padlen) padlen = drbg_blocklen (drbg) - padlen; /* pad / padlen contains the 0x80 byte and the following zero bytes, so * add one for byte for 0x80 */ padlen++; pad[0] = 0x80; /* 10.4.2 step 4 -- first fill the linked list and then order it */ drbg_string_fill (&S1, iv, drbg_blocklen (drbg)); drbg_string_fill (&S2, L_N, sizeof (L_N)); drbg_string_fill (&S4, pad, padlen); S1.next = &S2; S2.next = addtl; /* Splice in addtl between S2 and S4 -- we place S4 at the end of the * input data chain. As this code is only triggered when addtl is not * NULL, no NULL checks are necessary.*/ tempstr = addtl; while (tempstr->next) tempstr = tempstr->next; tempstr->next = &S4; /* 10.4.2 step 9 */ while (templen < (drbg_keylen (drbg) + (drbg_blocklen (drbg)))) { /* 10.4.2 step 9.1 - the padding is implicit as the buffer * holds zeros after allocation -- even the increment of i * is irrelevant as the increment remains within length of i */ buf_put_be32 (iv, i); /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ ret = drbg_ctr_bcc (drbg, temp + templen, K, &S1); if (ret) goto out; /* 10.4.2 step 9.3 */ i++; templen += drbg_blocklen (drbg); } /* 10.4.2 step 11 */ /* implicit key len with seedlen - blocklen according to table 3 */ X = temp + (drbg_keylen (drbg)); drbg_string_fill (&cipherin, X, drbg_blocklen (drbg)); /* 10.4.2 step 12: overwriting of outval */ /* 10.4.2 step 13 */ ret = drbg_sym_setkey(drbg, temp); if (ret) goto out; while (generated_len < bytes_to_return) { short blocklen = 0; /* 10.4.2 step 13.1 */ /* the truncation of the key length is implicit as the key * is only drbg_blocklen in size -- check for the implementation * of the cipher function callback */ ret = drbg_sym (drbg, X, &cipherin); if (ret) goto out; blocklen = (drbg_blocklen (drbg) < (bytes_to_return - generated_len)) ? drbg_blocklen (drbg) : (bytes_to_return - generated_len); /* 10.4.2 step 13.2 and 14 */ memcpy (df_data + generated_len, X, blocklen); generated_len += blocklen; } ret = 0; out: memset (iv, 0, drbg_blocklen (drbg)); memset (temp, 0, drbg_statelen (drbg)); memset (pad, 0, drbg_blocklen (drbg)); return ret; } /* * Update function of CTR DRBG as defined in 10.2.1.2 * * The reseed variable has an enhanced meaning compared to the update * functions of the other DRBGs as follows: * 0 => initial seed from initialization * 1 => reseed via drbg_seed * 2 => first invocation from drbg_ctr_update when addtl is present. In * this case, the df_data scratchpad is not deleted so that it is * available for another calls to prevent calling the DF function * again. * 3 => second invocation from drbg_ctr_update. When the update function * was called with addtl, the df_data memory already contains the * DFed addtl information and we do not need to call DF again. */ static gpg_err_code_t drbg_ctr_update (drbg_state_t drbg, drbg_string_t *addtl, int reseed) { gpg_err_code_t ret = GPG_ERR_GENERAL; /* 10.2.1.2 step 1 */ unsigned char *temp = drbg->scratchpad; unsigned char *df_data = drbg->scratchpad + drbg_statelen (drbg) + drbg_blocklen (drbg); unsigned char prefix = DRBG_PREFIX1; memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg)); if (3 > reseed) memset (df_data, 0, drbg_statelen (drbg)); if (!reseed) { /* * The DRBG uses the CTR mode of the underlying AES cipher. The * CTR mode increments the counter value after the AES operation * but SP800-90A requires that the counter is incremented before * the AES operation. Hence, we increment it at the time we set * it by one. */ drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1); ret = _gcry_cipher_setkey (drbg->ctr_handle, drbg->C, drbg_keylen (drbg)); if (ret) goto out; } /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ if (addtl && 0 < addtl->len) { ret = drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl); if (ret) goto out; } ret = drbg_sym_ctr (drbg, df_data, drbg_statelen(drbg), temp, drbg_statelen(drbg)); if (ret) goto out; /* 10.2.1.2 step 5 */ ret = _gcry_cipher_setkey (drbg->ctr_handle, temp, drbg_keylen (drbg)); if (ret) goto out; /* 10.2.1.2 step 6 */ memcpy (drbg->V, temp + drbg_keylen (drbg), drbg_blocklen (drbg)); /* See above: increment counter by one to compensate timing of CTR op */ drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1); ret = 0; out: memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg)); if (2 != reseed) memset (df_data, 0, drbg_statelen (drbg)); return ret; } /* * scratchpad use: drbg_ctr_update is called independently from * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused */ /* Generate function of CTR DRBG as defined in 10.2.1.5.2 */ static gpg_err_code_t drbg_ctr_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { static const unsigned char drbg_ctr_null[DRBG_CTR_NULL_LEN] = { 0, }; gpg_err_code_t ret = 0; memset (drbg->scratchpad, 0, drbg_blocklen (drbg)); /* 10.2.1.5.2 step 2 */ if (addtl && 0 < addtl->len) { addtl->next = NULL; ret = drbg_ctr_update (drbg, addtl, 2); if (ret) return ret; } /* 10.2.1.5.2 step 4.1 */ ret = drbg_sym_ctr (drbg, drbg_ctr_null, sizeof(drbg_ctr_null), buf, buflen); if (ret) goto out; /* 10.2.1.5.2 step 6 */ if (addtl) addtl->next = NULL; ret = drbg_ctr_update (drbg, addtl, 3); out: return ret; } static struct drbg_state_ops_s drbg_ctr_ops = { drbg_ctr_update, drbg_ctr_generate, drbg_sym_init, drbg_sym_fini, }; /****************************************************************** * HMAC DRBG callback functions ******************************************************************/ static gpg_err_code_t drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed) { gpg_err_code_t ret = GPG_ERR_GENERAL; int i = 0; drbg_string_t seed1, seed2, cipherin; if (!reseed) { /* 10.1.2.3 step 2 already implicitly covered with * the initial memset(0) of drbg->C */ memset (drbg->V, 1, drbg_statelen (drbg)); ret = drbg_hmac_setkey (drbg, drbg->C); if (ret) return ret; } /* build linked list which implements the concatenation and fill * first part*/ drbg_string_fill (&seed1, drbg->V, drbg_statelen (drbg)); /* buffer will be filled in for loop below with one byte */ drbg_string_fill (&seed2, NULL, 1); seed1.next = &seed2; /* seed may be NULL */ seed2.next = seed; drbg_string_fill (&cipherin, drbg->V, drbg_statelen (drbg)); /* we execute two rounds of V/K massaging */ for (i = 2; 0 < i; i--) { byte *retval; /* first round uses 0x0, second 0x1 */ unsigned char prefix = DRBG_PREFIX0; if (1 == i) prefix = DRBG_PREFIX1; /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ seed2.buf = &prefix; retval = drbg_hash (drbg, &seed1); ret = drbg_hmac_setkey (drbg, retval); if (ret) return ret; /* 10.1.2.2 step 2 and 5 -- HMAC for V */ retval = drbg_hash (drbg, &cipherin); memcpy(drbg->V, retval, drbg_blocklen (drbg)); /* 10.1.2.2 step 3 */ if (!seed || 0 == seed->len) return ret; } return 0; } /* generate function of HMAC DRBG as defined in 10.1.2.5 */ static gpg_err_code_t drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = 0; unsigned int len = 0; drbg_string_t data; /* 10.1.2.5 step 2 */ if (addtl && 0 < addtl->len) { addtl->next = NULL; ret = drbg_hmac_update (drbg, addtl, 1); if (ret) return ret; } drbg_string_fill (&data, drbg->V, drbg_statelen (drbg)); while (len < buflen) { unsigned int outlen = 0; /* 10.1.2.5 step 4.1 */ byte *retval = drbg_hash (drbg, &data); memcpy(drbg->V, retval, drbg_blocklen (drbg)); outlen = (drbg_blocklen (drbg) < (buflen - len)) ? drbg_blocklen (drbg) : (buflen - len); /* 10.1.2.5 step 4.2 */ memcpy (buf + len, drbg->V, outlen); len += outlen; } /* 10.1.2.5 step 6 */ if (addtl) addtl->next = NULL; ret = drbg_hmac_update (drbg, addtl, 1); return ret; } static struct drbg_state_ops_s drbg_hmac_ops = { drbg_hmac_update, drbg_hmac_generate, drbg_hmac_init, drbg_hash_fini, }; /****************************************************************** * Hash DRBG callback functions ******************************************************************/ /* * scratchpad usage: as drbg_hash_update and drbg_hash_df are used * interlinked, the scratchpad is used as follows: * drbg_hash_update * start: drbg->scratchpad * length: drbg_statelen(drbg) * drbg_hash_df: * start: drbg->scratchpad + drbg_statelen(drbg) * length: drbg_blocklen(drbg) */ /* Derivation Function for Hash DRBG as defined in 10.4.1 */ static gpg_err_code_t drbg_hash_df (drbg_state_t drbg, unsigned char *outval, size_t outlen, drbg_string_t *entropy) { size_t len = 0; unsigned char input[5]; drbg_string_t data1; /* 10.4.1 step 3 */ input[0] = 1; buf_put_be32 (&input[1], (outlen * 8)); /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ drbg_string_fill (&data1, input, 5); data1.next = entropy; /* 10.4.1 step 4 */ while (len < outlen) { short blocklen = 0; /* 10.4.1 step 4.1 */ byte *retval = drbg_hash (drbg, &data1); /* 10.4.1 step 4.2 */ input[0]++; blocklen = (drbg_blocklen (drbg) < (outlen - len)) ? drbg_blocklen (drbg) : (outlen - len); memcpy (outval + len, retval, blocklen); len += blocklen; } return 0; } /* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ static gpg_err_code_t drbg_hash_update (drbg_state_t drbg, drbg_string_t *seed, int reseed) { gpg_err_code_t ret = 0; drbg_string_t data1, data2; unsigned char *V = drbg->scratchpad; unsigned char prefix = DRBG_PREFIX1; memset (drbg->scratchpad, 0, drbg_statelen (drbg)); if (!seed) return GPG_ERR_INV_ARG; if (reseed) { /* 10.1.1.3 step 1: string length is concatenation of * 1 byte, V and seed (which is concatenated entropy/addtl * input) */ memcpy (V, drbg->V, drbg_statelen (drbg)); drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, V, drbg_statelen (drbg)); data1.next = &data2; data2.next = seed; } else { drbg_string_fill (&data1, seed->buf, seed->len); data1.next = seed->next; } /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ ret = drbg_hash_df (drbg, drbg->V, drbg_statelen (drbg), &data1); if (ret) goto out; /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */ prefix = DRBG_PREFIX0; drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); data1.next = &data2; /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */ ret = drbg_hash_df (drbg, drbg->C, drbg_statelen (drbg), &data1); out: memset (drbg->scratchpad, 0, drbg_statelen (drbg)); return ret; } /* Processing of additional information string for Hash DRBG. */ static gpg_err_code_t drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl) { drbg_string_t data1, data2; drbg_string_t *data3; unsigned char prefix = DRBG_PREFIX2; byte *retval; /* 10.1.1.4 step 2 */ if (!addtl || 0 == addtl->len) return 0; /* 10.1.1.4 step 2a -- concatenation */ drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); data3 = addtl; data1.next = &data2; data2.next = data3; data3->next = NULL; /* 10.1.1.4 step 2a -- cipher invocation */ retval = drbg_hash (drbg, &data1); /* 10.1.1.4 step 2b */ drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg)); return 0; } /* * Hashgen defined in 10.1.1.4 */ static gpg_err_code_t drbg_hash_hashgen (drbg_state_t drbg, unsigned char *buf, unsigned int buflen) { unsigned int len = 0; unsigned char *src = drbg->scratchpad; drbg_string_t data; unsigned char prefix = DRBG_PREFIX1; /* 10.1.1.4 step hashgen 2 */ memcpy (src, drbg->V, drbg_statelen (drbg)); drbg_string_fill (&data, src, drbg_statelen (drbg)); while (len < buflen) { unsigned int outlen = 0; /* 10.1.1.4 step hashgen 4.1 */ byte *retval = drbg_hash (drbg, &data); outlen = (drbg_blocklen (drbg) < (buflen - len)) ? drbg_blocklen (drbg) : (buflen - len); /* 10.1.1.4 step hashgen 4.2 */ memcpy (buf + len, retval, outlen); len += outlen; /* 10.1.1.4 hashgen step 4.3 */ if (len < buflen) drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1); } memset (drbg->scratchpad, 0, drbg_statelen (drbg)); return 0; } /* Generate function for Hash DRBG as defined in 10.1.1.4 */ static gpg_err_code_t drbg_hash_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret; unsigned char prefix = DRBG_PREFIX3; drbg_string_t data1, data2; byte *retval; union { unsigned char req[8]; u64 req_int; } u; /* 10.1.1.4 step 2 */ ret = drbg_hash_process_addtl (drbg, addtl); if (ret) return ret; /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in * 10.1.1.4 */ ret = drbg_hash_hashgen (drbg, buf, buflen); if (ret) return ret; /* 10.1.1.4 step 4 */ drbg_string_fill (&data1, &prefix, 1); drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg)); data1.next = &data2; /* this is the value H as documented in 10.1.1.4 */ retval = drbg_hash (drbg, &data1); /* 10.1.1.4 step 5 */ drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg)); drbg_add_buf (drbg->V, drbg_statelen (drbg), drbg->C, drbg_statelen (drbg)); u.req_int = be_bswap64 (drbg->reseed_ctr); drbg_add_buf (drbg->V, drbg_statelen (drbg), u.req, sizeof (u.req)); return ret; } /* * scratchpad usage: as update and generate are used isolated, both * can use the scratchpad */ static struct drbg_state_ops_s drbg_hash_ops = { drbg_hash_update, drbg_hash_generate, drbg_hash_init, drbg_hash_fini, }; /****************************************************************** * Functions common for DRBG implementations ******************************************************************/ /* * Seeding or reseeding of the DRBG * * @drbg: DRBG state struct * @pers: personalization / additional information buffer * @reseed: 0 for initial seed process, 1 for reseeding * * return: * 0 on success * error value otherwise */ static gpg_err_code_t drbg_seed (drbg_state_t drbg, drbg_string_t *pers, int reseed) { gpg_err_code_t ret = 0; unsigned char *entropy = NULL; size_t entropylen = 0; drbg_string_t data1; /* 9.1 / 9.2 / 9.3.1 step 3 */ if (pers && pers->len > (drbg_max_addtl ())) { dbg (("DRBG: personalization string too long %lu\n", pers->len)); return GPG_ERR_INV_ARG; } if (drbg->test_data && drbg->test_data->testentropy) { drbg_string_fill (&data1, drbg->test_data->testentropy->buf, drbg->test_data->testentropy->len); dbg (("DRBG: using test entropy\n")); } else { /* Gather entropy equal to the security strength of the DRBG. * With a derivation function, a nonce is required in addition * to the entropy. A nonce must be at least 1/2 of the security * strength of the DRBG in size. Thus, entropy * nonce is 3/2 * of the strength. The consideration of a nonce is only * applicable during initial seeding. */ entropylen = drbg_sec_strength (drbg->core->flags); if (!entropylen) return GPG_ERR_GENERAL; if (0 == reseed) /* make sure we round up strength/2 in * case it is not divisible by 2 */ entropylen = ((entropylen + 1) / 2) * 3; dbg (("DRBG: (re)seeding with %lu bytes of entropy\n", entropylen)); entropy = xcalloc_secure (1, entropylen); if (!entropy) return GPG_ERR_ENOMEM; ret = drbg_get_entropy (drbg, entropy, entropylen); if (ret) goto out; drbg_string_fill (&data1, entropy, entropylen); } /* concatenation of entropy with personalization str / addtl input) * the variable pers is directly handed by the caller, check its * contents whether it is appropriate */ if (pers && pers->buf && 0 < pers->len && NULL == pers->next) { data1.next = pers; dbg (("DRBG: using personalization string\n")); } ret = drbg->d_ops->update (drbg, &data1, reseed); dbg (("DRBG: state updated with seed\n")); if (ret) goto out; drbg->seeded = 1; /* 10.1.1.2 / 10.1.1.3 step 5 */ drbg->reseed_ctr = 1; out: xfree (entropy); return ret; } /************************************************************************* * Exported interfaces. *************************************************************************/ /* * DRBG generate function as required by SP800-90A - this function * generates random numbers * * @drbg DRBG state handle * @buf Buffer where to store the random numbers -- the buffer must already * be pre-allocated by caller * @buflen Length of output buffer - this value defines the number of random * bytes pulled from DRBG * @addtl Additional input that is mixed into state, may be NULL -- note * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * * return: Generated number of bytes. */ static gpg_err_code_t drbg_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = GPG_ERR_INV_ARG; if (0 == buflen || !buf) { dbg (("DRBG: no buffer provided\n")); return ret; } if (addtl && NULL == addtl->buf && 0 < addtl->len) { dbg (("DRBG: wrong format of additional information\n")); return ret; } /* 9.3.1 step 2 */ if (buflen > (drbg_max_request_bytes ())) { dbg (("DRBG: requested random numbers too large %u\n", buflen)); return ret; } /* 9.3.1 step 3 is implicit with the chosen DRBG */ /* 9.3.1 step 4 */ if (addtl && addtl->len > (drbg_max_addtl ())) { dbg (("DRBG: additional information string too long %lu\n", addtl->len)); return ret; } /* 9.3.1 step 5 is implicit with the chosen DRBG */ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a * bit convoluted here, we make it simpler */ if ((drbg_max_requests ()) < drbg->reseed_ctr) drbg->seeded = 0; if (drbg->pr || !drbg->seeded) { dbg (("DRBG: reseeding before generation (prediction resistance: %s, state %s)\n", drbg->pr ? "true" : "false", drbg->seeded ? "seeded" : "unseeded")); /* 9.3.1 steps 7.1 through 7.3 */ ret = drbg_seed (drbg, addtl, 1); if (ret) return ret; /* 9.3.1 step 7.4 */ addtl = NULL; } if (addtl && addtl->buf) { dbg (("DRBG: using additional information string\n")); } /* 9.3.1 step 8 and 10 */ ret = drbg->d_ops->generate (drbg, buf, buflen, addtl); /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ drbg->reseed_ctr++; if (ret) return ret; /* 11.3.3 -- re-perform self tests after some generated random * numbers, the chosen value after which self test is performed * is arbitrary, but it should be reasonable */ /* Here we do not perform the self tests because of the following * reasons: it is mathematically impossible that the initial self tests * were successfully and the following are not. If the initial would * pass and the following would not, the system integrity is violated. * In this case, the entire system operation is questionable and it * is unlikely that the integrity violation only affects to the * correct operation of the DRBG. */ #if 0 if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) { dbg (("DRBG: start to perform self test\n")); ret = drbg_healthcheck (); if (ret) { log_fatal (("DRBG: self test failed\n")); return ret; } else { dbg (("DRBG: self test successful\n")); } } #endif return ret; } /* * Wrapper around drbg_generate which can pull arbitrary long strings * from the DRBG without hitting the maximum request limitation. * * Parameters: see drbg_generate * Return codes: see drbg_generate -- if one drbg_generate request fails, * the entire drbg_generate_long request fails */ static gpg_err_code_t drbg_generate_long (drbg_state_t drbg, unsigned char *buf, unsigned int buflen, drbg_string_t *addtl) { gpg_err_code_t ret = 0; unsigned int slice = 0; unsigned char *buf_p = buf; unsigned len = 0; do { unsigned int chunk = 0; slice = ((buflen - len) / drbg_max_request_bytes ()); chunk = slice ? drbg_max_request_bytes () : (buflen - len); ret = drbg_generate (drbg, buf_p, chunk, addtl); if (ret) return ret; buf_p += chunk; len += chunk; } while (slice > 0 && (len < buflen)); return ret; } /* * DRBG uninstantiate function as required by SP800-90A - this function * frees all buffers and the DRBG handle * * @drbg DRBG state handle * * return * 0 on success */ static gpg_err_code_t drbg_uninstantiate (drbg_state_t drbg) { if (!drbg) return GPG_ERR_INV_ARG; drbg->d_ops->crypto_fini(drbg); xfree (drbg->V); drbg->V = NULL; xfree (drbg->C); drbg->C = NULL; drbg->reseed_ctr = 0; xfree (drbg->scratchpad); drbg->scratchpad = NULL; drbg->seeded = 0; drbg->pr = 0; drbg->seed_init_pid = 0; return 0; } /* * DRBG instantiation function as required by SP800-90A - this function * sets up the DRBG handle, performs the initial seeding and all sanity * checks required by SP800-90A * * @drbg memory of state -- if NULL, new memory is allocated * @pers Personalization string that is mixed into state, may be NULL -- note * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * @coreref reference to core * @flags Flags defining the requested DRBG type and cipher type. The flags * are defined in drbg.h and may be XORed. Beware, if you XOR multiple * cipher types together, the code picks the core on a first come first * serve basis as it iterates through the available cipher cores and * uses the one with the first match. The minimum required flags are: * cipher type flag * * return * 0 on success * error value otherwise */ static gpg_err_code_t drbg_instantiate (drbg_state_t drbg, drbg_string_t *pers, int coreref, int pr) { gpg_err_code_t ret = GPG_ERR_ENOMEM; unsigned int sb_size = 0; if (!drbg) return GPG_ERR_INV_ARG; dbg (("DRBG: Initializing DRBG core %d with prediction resistance %s\n", coreref, pr ? "enabled" : "disabled")); drbg->core = &drbg_cores[coreref]; drbg->pr = pr; drbg->seeded = 0; if (drbg->core->flags & DRBG_HMAC) drbg->d_ops = &drbg_hmac_ops; else if (drbg->core->flags & DRBG_HASH_MASK) drbg->d_ops = &drbg_hash_ops; else if (drbg->core->flags & DRBG_CTR_MASK) drbg->d_ops = &drbg_ctr_ops; else return GPG_ERR_GENERAL; /* 9.1 step 1 is implicit with the selected DRBG type -- see * drbg_sec_strength() */ /* 9.1 step 2 is implicit as caller can select prediction resistance * and the flag is copied into drbg->flags -- * all DRBG types support prediction resistance */ /* 9.1 step 4 is implicit in drbg_sec_strength */ ret = drbg->d_ops->crypto_init(drbg); if (ret) goto err; drbg->V = xcalloc_secure (1, drbg_statelen (drbg)); if (!drbg->V) goto fini; drbg->C = xcalloc_secure (1, drbg_statelen (drbg)); if (!drbg->C) goto fini; /* scratchpad is only generated for CTR and Hash */ if (drbg->core->flags & DRBG_HMAC) sb_size = 0; else if (drbg->core->flags & DRBG_CTR_MASK) sb_size = drbg_statelen (drbg) + drbg_blocklen (drbg) + /* temp */ drbg_statelen (drbg) + /* df_data */ drbg_blocklen (drbg) + /* pad */ drbg_blocklen (drbg) + /* iv */ drbg_statelen (drbg) + drbg_blocklen (drbg); /* temp */ else sb_size = drbg_statelen (drbg); if (0 < sb_size) { drbg->scratchpad = xcalloc_secure (1, sb_size); if (!drbg->scratchpad) goto fini; } dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size)); /* 9.1 step 6 through 11 */ ret = drbg_seed (drbg, pers, 0); if (ret) goto fini; dbg (("DRBG: core %d %s prediction resistance successfully initialized\n", coreref, pr ? "with" : "without")); return 0; fini: drbg->d_ops->crypto_fini(drbg); err: drbg_uninstantiate (drbg); return ret; } /* * DRBG reseed function as required by SP800-90A * * @drbg DRBG state handle * @addtl Additional input that is mixed into state, may be NULL -- note * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * * return * 0 on success * error value otherwise */ static gpg_err_code_t drbg_reseed (drbg_state_t drbg,drbg_string_t *addtl) { gpg_err_code_t ret = 0; ret = drbg_seed (drbg, addtl, 1); return ret; } /****************************************************************** * Libgcrypt integration code. ******************************************************************/ /*************************************************** * Libgcrypt backend functions to the RNG API code. ***************************************************/ static inline void drbg_lock (void) { gpg_err_code_t ec; ec = gpgrt_lock_lock (&drbg_lock_var); if (ec) log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (ec)); } static inline void drbg_unlock (void) { gpg_err_code_t ec; ec = gpgrt_lock_unlock (&drbg_lock_var); if (ec) log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (ec)); } /* Basic initialization is required to initialize mutexes and do a few checks on the implementation. */ static void basic_initialization (void) { static int initialized; if (initialized) return; initialized = 1; /* 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); } /****** helper functions where lock must be held by caller *****/ /* Check whether given flags are known to point to an applicable DRBG */ static gpg_err_code_t drbg_algo_available (u32 flags, int *coreref) { int i = 0; for (i = 0; ARRAY_SIZE (drbg_cores) > i; i++) { if ((drbg_cores[i].flags & DRBG_CIPHER_MASK) == (flags & DRBG_CIPHER_MASK)) { *coreref = i; return 0; } } return GPG_ERR_GENERAL; } static gpg_err_code_t _drbg_init_internal (u32 flags, drbg_string_t *pers) { static u32 oldflags; gpg_err_code_t ret = 0; int coreref = 0; int pr = 0; /* If a caller provides 0 as flags, use the flags of the previous * initialization, otherwise use the current flags and remember them * for the next invocation. If no flag is given and no global state * is set this is the first initialization and we set the default * type. */ if (!flags && !drbg_state) flags = oldflags = DRBG_DEFAULT_TYPE; else if (!flags) flags = oldflags; else oldflags = flags; ret = drbg_algo_available (flags, &coreref); if (ret) return ret; if (drbg_state) { drbg_uninstantiate (drbg_state); } else { drbg_state = xtrycalloc_secure (1, sizeof *drbg_state); if (!drbg_state) return gpg_err_code_from_syserror (); } if (flags & DRBG_PREDICTION_RESIST) pr = 1; ret = drbg_instantiate (drbg_state, pers, coreref, pr); if (ret) fips_signal_error ("DRBG cannot be initialized"); else drbg_state->seed_init_pid = getpid (); return ret; } /************* calls available to common RNG code **************/ /* * Initialize one DRBG invoked by the libgcrypt API */ void _gcry_rngdrbg_inititialize (int full) { basic_initialization (); if (!full) return; drbg_lock (); if (!drbg_state) _drbg_init_internal (0, NULL); drbg_unlock (); } /* * Backend handler function for GCRYCTL_DRBG_REINIT * * Select a different DRBG type and initialize it. * Function checks whether requested DRBG type exists and returns an error in * case it does not. In case of an error, the previous instantiated DRBG is * left untouched and alive. Thus, in case of an error, a DRBG is always * available, even if it is not the chosen one. * * Re-initialization will be performed in any case regardless whether flags * or personalization string are set. * * If flags is NULL, do not change current DRBG. If PERS is NULL and * NPERS is 0, re-initialize without personalization string. If PERS * is not NULL NPERS must be one and PERS and the first ietm from the * bufer is take as personalization string. */ gpg_err_code_t _gcry_rngdrbg_reinit (const char *flagstr, gcry_buffer_t *pers, int npers) { gpg_err_code_t ret; unsigned int flags; /* If PERS is not given we expect NPERS to be zero; if given we expect a one-item array. */ if ((!pers && npers) || (pers && npers != 1)) return GPG_ERR_INV_ARG; ret = parse_flag_string (flagstr, &flags); if (!ret) { dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags)); drbg_lock (); if (pers) { drbg_string_t persbuf; drbg_string_fill (&persbuf, (const unsigned char *)pers[0].data + pers[0].off, pers[0].len); ret = _drbg_init_internal (flags, &persbuf); } else ret = _drbg_init_internal (flags, NULL); drbg_unlock (); } return ret; } /* Try to close the FDs of the random gather module. This is * currently only implemented for rndlinux. */ void _gcry_rngdrbg_close_fds (void) { drbg_lock (); #if USE_RNDGETENTROPY _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0); -#elif USE_RNDLINUX +#endif +#if USE_RNDLINUX _gcry_rndlinux_gather_random (NULL, 0, 0, 0); #endif drbg_unlock (); } /* Print some statistics about the RNG. */ void _gcry_rngdrbg_dump_stats (void) { /* Not yet implemented. */ /* Maybe dumping of reseed counter? */ } /* This function returns true if no real RNG is available or the * quality of the RNG has been degraded for test purposes. */ int _gcry_rngdrbg_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_rngdrbg_add_bytes (const void *buf, size_t buflen, int quality) { gpg_err_code_t ret = 0; drbg_string_t seed; (void) quality; _gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */ if (!drbg_state) return GPG_ERR_GENERAL; drbg_string_fill (&seed, (unsigned char *) buf, buflen); drbg_lock (); ret = drbg_reseed (drbg_state, &seed); drbg_unlock (); return ret; } /* This function is to be used for all types of random numbers, including * nonces */ void _gcry_rngdrbg_randomize (void *buffer, size_t length, enum gcry_random_level level) { (void) level; _gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */ drbg_lock (); if (!drbg_state) { fips_signal_error ("DRBG is not initialized"); goto bailout; } /* As reseeding changes the entire state of the DRBG, including any * key, either a re-init or a reseed is sufficient for a fork */ if (drbg_state->seed_init_pid != getpid ()) { /* We are in a child of us. Perform a reseeding. */ if (drbg_reseed (drbg_state, NULL)) { fips_signal_error ("reseeding upon fork failed"); log_fatal ("severe error getting random\n"); goto bailout; } } /* potential integer overflow is covered by drbg_generate which * ensures that length cannot overflow an unsigned int */ if (0 < length) { if (!buffer) goto bailout; if (drbg_generate_long (drbg_state, buffer, (unsigned int) length, NULL)) log_fatal ("No random numbers generated\n"); } else { drbg_gen_t *data = (drbg_gen_t *)buffer; /* catch NULL pointer */ if (!data || !data->outbuf) { fips_signal_error ("No output buffer provided"); goto bailout; } if (drbg_generate_long (drbg_state, data->outbuf, data->outlen, data->addtl)) log_fatal ("No random numbers generated\n"); } bailout: drbg_unlock (); return; } /*************************************************************** * Self-test code ***************************************************************/ /* * Test vectors from * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip */ struct gcry_drbg_test_vector drbg_test_pr[] = { { /* .flags = */ "sha256 pr" /* DRBG_PR_HASHSHA256 */, /* .entropy = */ (unsigned char *) "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d" "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0" "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1" "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6", /* .entropylen = */ 48, /* .entpra = */ (unsigned char *) "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb" "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13" "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15", /* .entprb = */ (unsigned char *) "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09" "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde" "\x76\xaa\x55\x04\x8b\x0a\x72\x95", /* .entprlen = */ 32, /* .addtla = */ (unsigned char *) "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d" "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad" "\xa9\xd0\x1d\x59\x02\xc4\xff\x70", /* .addtlb = */ (unsigned char *) "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31" "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41" "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd", /* .addtllen = */ 32, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32" "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c" "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18" "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb" "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81" "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4" "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6" "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13" "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9" "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60" "\x50\x47\xa3\x63\x81\x16\xaf\x19", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* flags = */ "hmac sha256 pr" /* DRBG_PR_HMACSHA256 */, /* .entropy = */ (unsigned char *) "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89" "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf" "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20" "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67", /* .entropylen = */ 48, /* .entpra = */ (unsigned char *) "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79" "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57" "\x20\x28\xad\xf2\x60\xd7\xcd\x45", /* .entprb = */ (unsigned char *) "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71" "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66" "\x1f\xfa\x74\xd3\xac\xa6\x74\x60", /* .entprlen = */ 32, /* .addtla = */ NULL, /* .addtlb = */ NULL, /* .addtllen = */ 0, /* .pers = */ (unsigned char *) "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f" "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce" "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa", /* .perslen = */ 32, /* .expected = */ (unsigned char *) "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99" "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3" "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75" "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61" "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88" "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e" "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c" "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce" "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc" "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc" "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "aes sym128 pr", /* DRBG_PR_CTRAES128 */ /* .entropy = */ (unsigned char *) "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06" "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97", /* .entropylen = */ 24, /* .entpra = */ (unsigned char *) "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7" "\xc4\x2c\xe8\x10", /* .entprb = */ (unsigned char *) "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22" "\x08\xf7\xa5\x01", /* .entprlen = */ 16, /* .addtla = */ (unsigned char *) "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59" "\x23\x6d\xad\x1d", /* .addtlb = */ (unsigned char *) "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12" "\xbc\x59\x31\x8c", /* .addtllen = */ 16, /* .pers = */ (unsigned char *) "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4" "\x37\x3c\x5c\x0b", /* .perslen = */ 16, /* .expected = */ (unsigned char *) "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71" "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28" "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45" "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08" "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4" "\x23\xc5\x1f\x68", /* .expectedlen = */ 64, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 } }; struct gcry_drbg_test_vector drbg_test_nopr[] = { { /* .flags = */ "sha256" /* DRBG_NOPR_HASHSHA256 */, /* .entropy = */ (unsigned char *) "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c" "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d" "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff" "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56", /* .entropylen = */ 48, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ (unsigned char *) "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73" "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10" "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd", /* .addtlb = */ (unsigned char *) "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0" "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d" "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40", /* .addtllen = */ 32, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7" "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b" "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0" "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8" "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f" "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d" "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59" "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b" "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0" "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c" "\x70\xa8\x07\x59\x97\xeb\xf6\xbe", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "hmac sha256" /* DRBG_NOPR_HMACSHA256 */, /* .entropy = */ (unsigned char *) "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf" "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54" "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf" "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e", /* .entropylen = */ 48, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ NULL, /* .addtlb = */ NULL, /* .addtllen = */ 0, /* .pers = */ (unsigned char *) "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37" "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58" "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9", /* .perslen = */ 32, /* .expected = */ (unsigned char *) "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81" "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37" "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10" "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61" "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28" "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f" "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07" "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66" "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2" "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29" "\x10\x37\x41\x03\x0c\xcc\x3a\x56", /* .expectedlen = */ 128, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "aes sym128" /* DRBG_NOPR_CTRAES128 */, /* .entropy = */ (unsigned char *) "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98" "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6", /* .entropylen = */ 24, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ (unsigned char *) "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2" "\x44\x85\xe7\xfe", /* .addtlb = */ (unsigned char *) "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4" "\x82\x16\x62\x7f", /* .addtllen = */ 16, /* .pers = */ (unsigned char *) "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f" "\x8e\xcf\xe0\x02", /* .perslen = */ 16, /* .expected = */ (unsigned char *) "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a" "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95" "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f" "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a" "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a" "\x2b\x49\x1e\x5c", /* .expectedlen = */ 64, /* .entropyreseed = */ NULL, /* .entropyreseed_len = */ 0, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */, /* .entropy = */ (unsigned char *) "\x16\x10\xb8\x28\xcc\xd2\x7d\xe0\x8c\xee\xa0\x32" "\xa2\x0e\x92\x08\x49\x2c\xf1\x70\x92\x42\xf6\xb5", /* .entropylen = */ 24, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ NULL, /* .addtlb = */ NULL, /* .addtllen = */ 0, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\x56\xf3\x3d\x4f\xdb\xb9\xa5\xb6\x4d\x26\x23\x44" "\x97\xe9\xdc\xb8\x77\x98\xc6\x8d\x08\xf7\xc4\x11" "\x99\xd4\xbd\xdf\x97\xeb\xbf\x6c\xb5\x55\x0e\x5d" "\x14\x9f\xf4\xd5\xbd\x0f\x05\xf2\x5a\x69\x88\xc1" "\x74\x36\x39\x62\x27\x18\x4a\xf8\x4a\x56\x43\x35" "\x65\x8e\x2f\x85\x72\xbe\xa3\x33\xee\xe2\xab\xff" "\x22\xff\xa6\xde\x3e\x22\xac\xa2", /* .expectedlen = */ 80, /* .entropyreseed = */ (unsigned char *) "\x72\xd2\x8c\x90\x8e\xda\xf9\xa4\xd1\xe5\x26\xd8" "\xf2\xde\xd5\x44", /* .entropyreseed_len = */ 16, /* .addtl_reseed = */ NULL, /* .addtl_reseed_len = */ 0 }, { /* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */, /* .entropy = */ (unsigned char *) "\xd9\xba\xb5\xce\xdc\xa9\x6f\x61\x78\xd6\x45\x09" "\xa0\xdf\xdc\x5e\xda\xd8\x98\x94\x14\x45\x0e\x01", /* .entropylen = */ 24, /* .entpra = */ NULL, /* .entprb = */ NULL, /* .entprlen = */ 0, /* .addtla = */ (unsigned char *) "\x04\xfa\x28\x95\xaa\x5a\x6f\x8c\x57\x43\x34\x3b" "\x80\x5e\x5e\xa4", /* .addtlb = */ (unsigned char *) "\xdf\x5d\xc4\x59\xdf\xf0\x2a\xa2\xf0\x52\xd7\x21" "\xec\x60\x72\x30", /* .addtllen = */ 16, /* .pers = */ NULL, /* .perslen = */ 0, /* .expected = */ (unsigned char *) "\xc4\x8b\x89\xf9\xda\x3f\x74\x82\x45\x55\x5d\x5d" "\x03\x3b\x69\x3d\xd7\x1a\x4d\xf5\x69\x02\x05\xce" "\xfc\xd7\x20\x11\x3c\xc2\x4e\x09\x89\x36\xff\x5e" "\x77\xb5\x41\x53\x58\x70\xb3\x39\x46\x8c\xdd\x8d" "\x6f\xaf\x8c\x56\x16\x3a\x70\x0a\x75\xb2\x3e\x59" "\x9b\x5a\xec\xf1\x6f\x3b\xaf\x6d\x5f\x24\x19\x97" "\x1f\x24\xf4\x46\x72\x0f\xea\xbe", /* .expectedlen = */ 80, /* .entropyreseed = */ (unsigned char *) "\xc6\xba\xd0\x74\xc5\x90\x67\x86\xf5\xe1\xf3\x20" "\x99\xf5\xb4\x91", /* .entropyreseed_len = */ 16, /* .addtl_reseed = */ (unsigned char *) "\x3e\x6b\xf4\x6f\x4d\xaa\x38\x25\xd7\x19\x4e\x69" "\x4e\x77\x52\xf7", /* .addtl_reseed_len = */ 16 } }; /* * Tests implement the CAVS test approach as documented in * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf */ /* * CAVS test * * This function is not static as it is needed for as a private API * call for the CAVS test tool. */ gpg_err_code_t _gcry_rngdrbg_cavs_test (struct gcry_drbg_test_vector *test, unsigned char *buf) { gpg_err_code_t ret = 0; drbg_state_t drbg = NULL; struct drbg_test_data_s test_data; drbg_string_t addtl, pers, testentropy; int coreref = 0; int pr = 0; u32 flags; ret = parse_flag_string (test->flagstr, &flags); if (ret) goto outbuf; ret = drbg_algo_available (flags, &coreref); if (ret) goto outbuf; drbg = xtrycalloc_secure (1, sizeof *drbg); if (!drbg) { ret = gpg_err_code_from_syserror (); goto outbuf; } if ((flags & DRBG_PREDICTION_RESIST)) pr = 1; test_data.testentropy = &testentropy; drbg_string_fill (&testentropy, test->entropy, test->entropylen); drbg->test_data = &test_data; drbg_string_fill (&pers, test->pers, test->perslen); ret = drbg_instantiate (drbg, &pers, coreref, pr); if (ret) goto outbuf; if (test->entropyreseed) { drbg_string_fill (&testentropy, test->entropyreseed, test->entropyreseed_len); drbg_string_fill (&addtl, test->addtl_reseed, test->addtl_reseed_len); if (drbg_reseed (drbg, &addtl)) goto outbuf; } drbg_string_fill (&addtl, test->addtla, test->addtllen); if (test->entpra) { drbg_string_fill (&testentropy, test->entpra, test->entprlen); drbg->test_data = &test_data; } drbg_generate_long (drbg, buf, test->expectedlen, &addtl); drbg_string_fill (&addtl, test->addtlb, test->addtllen); if (test->entprb) { drbg_string_fill (&testentropy, test->entprb, test->entprlen); drbg->test_data = &test_data; } drbg_generate_long (drbg, buf, test->expectedlen, &addtl); drbg_uninstantiate (drbg); outbuf: xfree (drbg); return ret; } /* * Invoke the CAVS test and perform the final check whether the * calculated random value matches the expected one. * * This function is not static as it is needed for as a private API * call for the CAVS test tool. */ gpg_err_code_t _gcry_rngdrbg_healthcheck_one (struct gcry_drbg_test_vector * test) { gpg_err_code_t ret = GPG_ERR_ENOMEM; unsigned char *buf = xcalloc_secure (1, test->expectedlen); if (!buf) return GPG_ERR_ENOMEM; ret = _gcry_rngdrbg_cavs_test (test, buf); /* FIXME: The next line is wrong. */ ret = memcmp (test->expected, buf, test->expectedlen); xfree (buf); return ret; } /* * Tests as defined in 11.3.2 in addition to the cipher tests: testing * of the error handling. * * Note, testing the reseed counter is not done as an automatic reseeding * is performed in drbg_generate when the reseed counter is too large. */ static gpg_err_code_t drbg_healthcheck_sanity (struct gcry_drbg_test_vector *test) { unsigned int len = 0; drbg_state_t drbg = NULL; gpg_err_code_t ret = GPG_ERR_GENERAL; gpg_err_code_t tmpret = GPG_ERR_GENERAL; struct drbg_test_data_s test_data; drbg_string_t addtl, testentropy; int coreref = 0; unsigned char *buf = NULL; size_t max_addtllen, max_request_bytes; u32 flags; /* only perform test in FIPS mode */ if (0 == fips_mode ()) return 0; ret = parse_flag_string (test->flagstr, &flags); if (ret) return ret; ret = GPG_ERR_GENERAL; /* Fixme: Improve handling of RET. */ buf = xtrycalloc_secure (1, test->expectedlen); if (!buf) return gpg_err_code_from_syserror (); tmpret = drbg_algo_available (flags, &coreref); if (tmpret) goto outbuf; drbg = xtrycalloc_secure (1, sizeof *drbg); if (!drbg) { ret = gpg_err_code_from_syserror (); goto outbuf; } /* if the following tests fail, it is likely that there is a buffer * overflow and we get a SIGSEV */ ret = drbg_instantiate (drbg, NULL, coreref, 1); if (ret) goto outbuf; max_addtllen = drbg_max_addtl (); max_request_bytes = drbg_max_request_bytes (); /* overflow addtllen with additional info string */ drbg_string_fill (&addtl, test->addtla, (max_addtllen + 1)); len = drbg_generate (drbg, buf, test->expectedlen, &addtl); if (len) goto outdrbg; /* overflow max_bits */ len = drbg_generate (drbg, buf, (max_request_bytes + 1), NULL); if (len) goto outdrbg; drbg_uninstantiate (drbg); /* test failing entropy source as defined in 11.3.2 */ test_data.testentropy = NULL; test_data.fail_seed_source = 1; drbg->test_data = &test_data; tmpret = drbg_instantiate (drbg, NULL, coreref, 0); if (!tmpret) goto outdrbg; test_data.fail_seed_source = 0; test_data.testentropy = &testentropy; drbg_string_fill (&testentropy, test->entropy, test->entropylen); /* overflow max addtllen with personalization string */ tmpret = drbg_instantiate (drbg, &addtl, coreref, 0); if (!tmpret) goto outdrbg; dbg (("DRBG: Sanity tests for failure code paths successfully completed\n")); ret = 0; outdrbg: drbg_uninstantiate (drbg); outbuf: xfree (buf); xfree (drbg); return ret; } /* * DRBG Healthcheck function as required in SP800-90A * * return: * 0 on success (all tests pass) * >0 on error (return code indicate the number of failures) */ static int drbg_healthcheck (void) { int ret = 0; ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[0]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[1]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[2]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[3]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[4]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[0]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[1]); ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[2]); ret += drbg_healthcheck_sanity (&drbg_test_nopr[0]); return ret; } /* Run the self-tests. */ gcry_error_t _gcry_rngdrbg_selftest (selftest_report_func_t report) { gcry_err_code_t ec; const char *errtxt = NULL; drbg_lock (); if (0 != drbg_healthcheck ()) errtxt = "RNG output does not match known value"; drbg_unlock (); if (report && errtxt) report ("random", 0, "KAT", errtxt); ec = errtxt ? GPG_ERR_SELFTEST_FAILED : 0; return gpg_error (ec); } /*************************************************************** * Cipher invocations requested by DRBG ***************************************************************/ static gpg_err_code_t drbg_hash_init (drbg_state_t drbg) { gcry_md_hd_t hd; gpg_error_t err; err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0); if (err) return err; drbg->priv_data = hd; return 0; } static gpg_err_code_t drbg_hmac_init (drbg_state_t drbg) { gcry_md_hd_t hd; gpg_error_t err; err = _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC); if (err) return err; drbg->priv_data = hd; return 0; } static gpg_err_code_t drbg_hmac_setkey (drbg_state_t drbg, const unsigned char *key) { gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data; return _gcry_md_setkey (hd, key, drbg_statelen (drbg)); } static void drbg_hash_fini (drbg_state_t drbg) { gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data; _gcry_md_close (hd); } static byte * drbg_hash (drbg_state_t drbg, const drbg_string_t *buf) { gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data; _gcry_md_reset(hd); for (; NULL != buf; buf = buf->next) _gcry_md_write (hd, buf->buf, buf->len); _gcry_md_final (hd); return _gcry_md_read (hd, drbg->core->backend_cipher); } static void drbg_sym_fini (drbg_state_t drbg) { gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data; if (hd) _gcry_cipher_close (hd); if (drbg->ctr_handle) _gcry_cipher_close (drbg->ctr_handle); } static gpg_err_code_t drbg_sym_init (drbg_state_t drbg) { gcry_cipher_hd_t hd; gpg_error_t err; err = _gcry_cipher_open (&hd, drbg->core->backend_cipher, GCRY_CIPHER_MODE_ECB, 0); if (err) { drbg_sym_fini (drbg); return err; } drbg->priv_data = hd; err = _gcry_cipher_open (&drbg->ctr_handle, drbg->core->backend_cipher, GCRY_CIPHER_MODE_CTR, 0); if (err) { drbg_sym_fini (drbg); return err; } if (drbg_blocklen (drbg) != _gcry_cipher_get_algo_blklen (drbg->core->backend_cipher)) { drbg_sym_fini (drbg); return -GPG_ERR_NO_ERROR; } return 0; } static gpg_err_code_t drbg_sym_setkey (drbg_state_t drbg, const unsigned char *key) { gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data; return _gcry_cipher_setkey (hd, key, drbg_keylen (drbg)); } static gpg_err_code_t drbg_sym (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf) { gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data; _gcry_cipher_reset(hd); if (drbg_blocklen (drbg) < buf->len) return -GPG_ERR_NO_ERROR; /* in is only component */ return _gcry_cipher_encrypt (hd, outval, drbg_blocklen (drbg), buf->buf, buf->len); } static gpg_err_code_t drbg_sym_ctr (drbg_state_t drbg, const unsigned char *inbuf, unsigned int inbuflen, unsigned char *outbuf, unsigned int outbuflen) { gpg_error_t err; _gcry_cipher_reset(drbg->ctr_handle); err = _gcry_cipher_setctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg)); if (err) return err; while (outbuflen) { unsigned int cryptlen = (inbuflen > outbuflen) ? outbuflen : inbuflen; err = _gcry_cipher_encrypt (drbg->ctr_handle, outbuf, cryptlen, inbuf, cryptlen); if (err) return err; outbuflen -= cryptlen; outbuf += cryptlen; } return _gcry_cipher_getctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg)); } diff --git a/random/random-fips.c b/random/random-fips.c index 967b1a83..5c251684 100644 --- a/random/random-fips.c +++ b/random/random-fips.c @@ -1,1130 +1,1131 @@ /* 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 . */ /* 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 #include #include #include #include #include #ifdef HAVE_GETTIMEOFDAY #include #endif #include "g10lib.h" #include "random.h" #include "rand-internal.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. */ GPGRT_LOCK_DEFINE (fips_rng_lock); 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 accidentally 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 function. 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; if (initialized) return; initialized = 1; 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) { gpg_err_code_t rc; rc = gpgrt_lock_lock (&fips_rng_lock); if (rc) log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (rc)); fips_rng_is_locked = 1; } /* Release the fips_rng_lock. */ static void unlock_rng (void) { gpg_err_code_t rc; fips_rng_is_locked = 0; rc = gpgrt_lock_unlock (&fips_rng_lock); if (rc) log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (rc)); } 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 million (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 = xmalloc_secure (nbytes); entropy_collect_buffer_size = nbytes; entropy_collect_buffer_len = 0; #if USE_RNDGETENTROPY rc = _gcry_rndgetentropy_gather_random (entropy_collect_cb, 0, X931_AES_KEYLEN, GCRY_VERY_STRONG_RANDOM); #elif 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) { xfree (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_err_code_t rc; void *buffer; gcry_assert (fips_rng_is_locked); /* Allocate a cipher context. */ rc = _gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE); if (rc) { log_error ("error creating cipher context for RNG: %s\n", _gcry_strerror (rc)); return NULL; } /* Get a key from the standard RNG or from the entropy source. */ if (for_nonce) { buffer = 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. */ rc = _gcry_cipher_setkey (hd, buffer, X931_AES_KEYLEN); wipememory (buffer, X931_AES_KEYLEN); xfree (buffer); if (rc) { log_error ("error creating key for RNG: %s\n", _gcry_strerror (rc)); _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); xfree (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 = 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 = xcalloc (1, sizeof *nonce_context); setup_guards (nonce_context); std_rng_context = xcalloc_secure (1, sizeof *std_rng_context); setup_guards (std_rng_context); strong_rng_context = 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 (); } /* Try to close the FDs of the random gather module. This is currently only implemented for rndlinux. */ void _gcry_rngfips_close_fds (void) { lock_rng (); #if USE_RNDGETENTROPY _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0); -#elif USE_RNDLINUX +#endif +#if USE_RNDLINUX _gcry_rndlinux_gather_random (NULL, 0, 0, 0); #endif unlock_rng (); } /* Print some statistics about the RNG. */ void _gcry_rngfips_dump_stats (void) { /* 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_err_code_t rc; const char *errtxt = NULL; unsigned char result[16]; gcry_assert (tempvalue_for_x931_aes_driver); test_ctx = xcalloc (1, sizeof *test_ctx); setup_guards (test_ctx); lock_rng (); for (tvidx=0; tvidx < DIM (tv); tvidx++) { /* Setup the key. */ rc = _gcry_cipher_open (&test_ctx->cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE); if (rc) { errtxt = "error creating cipher context for RNG"; goto leave; } rc = _gcry_cipher_setkey (test_ctx->cipher_hd, tv[tvidx].key, 16); if (rc) { errtxt = "error setting key for RNG"; goto leave; } test_ctx->key_init_pid = getpid (); /* Setup the seed. */ memcpy (test_ctx->seed_V, tv[tvidx].v, 16); test_ctx->is_seeded = 1; test_ctx->seed_init_pid = getpid (); /* Setup a DT value. */ test_ctx->test_dt_ptr = tv[tvidx].dt; test_ctx->test_dt_counter = ( (tv[tvidx].dt[12] << 24) |(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); xfree (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_RNDGETENTROPY) || defined(USE_RNDLINUX) || defined(USE_RNDW32) { char buffer[8]; /* Do a simple test using the public interface. This will also enforce full initialization of the RNG. We need to be fully initialized due to the global requirement of the tempvalue_for_x931_aes_driver stuff. */ _gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM); } ec = selftest_kat (report); #else /*!(USE_RNDGETENTROPY||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_err_code_t rc; 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 = xtrycalloc (1, sizeof *test_ctx + dtlen); if (!test_ctx) return gpg_err_code_from_syserror (); setup_guards (test_ctx); /* Setup the key. */ rc = _gcry_cipher_open (&test_ctx->cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE); if (rc) goto leave; rc = _gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen); if (rc) goto leave; test_ctx->key_init_pid = getpid (); /* Setup the seed. */ memcpy (test_ctx->seed_V, seed, seedlen); test_ctx->is_seeded = 1; test_ctx->seed_init_pid = getpid (); /* Setup a DT value. Because our context structure only stores a pointer we copy the DT value to the extra space we allocated in the test_ctx and set the pointer to that address. */ memcpy ((unsigned char*)test_ctx + sizeof *test_ctx, dt, dtlen); test_ctx->test_dt_ptr = (unsigned char*)test_ctx + sizeof *test_ctx; test_ctx->test_dt_counter = ( (test_ctx->test_dt_ptr[12] << 24) |(test_ctx->test_dt_ptr[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. */ rc = 0; leave: if (rc) { _gcry_cipher_close (test_ctx->cipher_hd); xfree (test_ctx); *r_context = NULL; } else *r_context = test_ctx; return rc; } /* 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); xfree (test_ctx); } } diff --git a/random/random-system.c b/random/random-system.c index 2ac8df9e..8e50120c 100644 --- a/random/random-system.c +++ b/random/random-system.c @@ -1,254 +1,255 @@ /* random-system.c - wrapper around the system's RNG * Copyright (C) 2012 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* This RNG is merely wrapper around the system's native RNG. For example on Unix systems it directly uses /dev/{u,}random. */ #include #include #include #include #include #include #ifdef HAVE_GETTIMEOFDAY #include #endif #include "g10lib.h" #include "random.h" #include "rand-internal.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. */ GPGRT_LOCK_DEFINE (system_rng_lock); static int system_rng_is_locked; /* --- Local prototypes --- */ /* --- Functions --- */ /* Basic initialization is required to initialize mutexes and do a few checks on the implementation. */ static void basic_initialization (void) { static int initialized; if (initialized) return; initialized = 1; system_rng_is_locked = 0; /* Make sure that we are still using the values we traditionally used for the random levels. */ gcry_assert (GCRY_WEAK_RANDOM == 0 && GCRY_STRONG_RANDOM == 1 && GCRY_VERY_STRONG_RANDOM == 2); } /* Acquire the system_rng_lock. */ static void lock_rng (void) { gpg_err_code_t rc; rc = gpgrt_lock_lock (&system_rng_lock); if (rc) log_fatal ("failed to acquire the System RNG lock: %s\n", gpg_strerror (rc)); system_rng_is_locked = 1; } /* Release the system_rng_lock. */ static void unlock_rng (void) { gpg_err_code_t rc; system_rng_is_locked = 0; rc = gpgrt_lock_unlock (&system_rng_lock); if (rc) log_fatal ("failed to release the System RNG lock: %s\n", gpg_strerror (rc)); } /* Helper variables for read_cb(). The _gcry_rnd*_gather_random interface does not allow to provide a data pointer. Thus we need to use a global variable for communication. However, the then required locking is anyway a good idea because it does not make sense to have several readers of (say /dev/random). It is easier to serve them one after the other. */ static unsigned char *read_cb_buffer; /* The buffer. */ static size_t read_cb_size; /* Size of the buffer. */ static size_t read_cb_len; /* Used length. */ /* Callback for _gcry_rnd*_gather_random. */ static void read_cb (const void *buffer, size_t length, enum random_origins origin) { const unsigned char *p = buffer; (void)origin; gcry_assert (system_rng_is_locked); gcry_assert (read_cb_buffer); /* Note that we need to protect against gatherers returning more than the requested bytes (e.g. rndw32). */ while (length-- && read_cb_len < read_cb_size) { read_cb_buffer[read_cb_len++] = *p++; } } /* Fill BUFFER with LENGTH bytes of random at quality LEVEL. The function either succeeds or terminates the process in case of a fatal error. */ static void get_random (void *buffer, size_t length, int level) { int rc; gcry_assert (buffer); read_cb_buffer = buffer; read_cb_size = length; read_cb_len = 0; #if USE_RNDGETENTROPY rc = _gcry_rndgetentropy_gather_random (read_cb, 0, length, level); #elif USE_RNDLINUX rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level); #elif USE_RNDUNIX rc = _gcry_rndunix_gather_random (read_cb, 0, length, level); #elif USE_RNDW32 do { rc = _gcry_rndw32_gather_random (read_cb, 0, length, level); } while (rc >= 0 && read_cb_len < read_cb_size); #else rc = -1; #endif if (rc < 0 || read_cb_len != read_cb_size) { log_fatal ("error reading random from system RNG (rc=%d)\n", rc); } } /* --- Public Functions --- */ /* Initialize this random subsystem. If FULL is false, this function merely calls the basic initialization of the module and does not do anything more. Doing this is not really required but when running in a threaded environment we might get a race condition otherwise. */ void _gcry_rngsystem_initialize (int full) { basic_initialization (); if (!full) return; /* Nothing more to initialize. */ return; } /* Try to close the FDs of the random gather module. This is currently only implemented for rndlinux. */ void _gcry_rngsystem_close_fds (void) { lock_rng (); #if USE_RNDGETENTROPY _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0); -#elif USE_RNDLINUX +#endif +#if USE_RNDLINUX _gcry_rndlinux_gather_random (NULL, 0, 0, 0); #endif unlock_rng (); } /* Print some statistics about the RNG. */ void _gcry_rngsystem_dump_stats (void) { /* Not yet implemented. */ } /* This function returns true if no real RNG is available or the quality of the RNG has been degraded for test purposes. */ int _gcry_rngsystem_is_faked (void) { return 0; /* Faked random is not supported. */ } /* Add BUFLEN bytes from BUF to the internal random pool. QUALITY should be in the range of 0..100 to indicate the goodness of the entropy added, or -1 for goodness not known. */ gcry_error_t _gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality) { (void)buf; (void)buflen; (void)quality; return 0; /* Not implemented. */ } /* Public function to fill the buffer with LENGTH bytes of cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but may be very slow. */ void _gcry_rngsystem_randomize (void *buffer, size_t length, enum gcry_random_level level) { _gcry_rngsystem_initialize (1); /* Auto-initialize if needed. */ if (level != GCRY_VERY_STRONG_RANDOM) level = GCRY_STRONG_RANDOM; lock_rng (); get_random (buffer, length, level); unlock_rng (); } diff --git a/random/rndgetentropy.c b/random/rndgetentropy.c index 5a033276..a64b7299 100644 --- a/random/rndgetentropy.c +++ b/random/rndgetentropy.c @@ -1,90 +1,102 @@ /* rndgetentropy.c - raw random number for OSes by getentropy function. * Copyright (C) 1998, 2001, 2002, 2003, 2007, * 2009 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 . */ #include #include #include #include #include #include #include #include "types.h" #include "g10lib.h" #include "rand-internal.h" /* The function returns 0 on success or true on failure (in which case * the caller will signal a fatal error). */ int _gcry_rndgetentropy_gather_random (void (*add)(const void*, size_t, enum random_origins), enum random_origins origin, size_t length, int level) { byte buffer[256]; - (void)level; - if (!add) { /* Special mode to release resouces. */ _gcry_rndjent_fini (); return 0; } + /* When using a blocking random generator try to get some entropy + * from the jitter based RNG. In this case we take up to 50% of the + * remaining requested bytes. */ + if (level >= GCRY_VERY_STRONG_RANDOM) + { + size_t n; + + n = _gcry_rndjent_poll (add, origin, length/2); + if (n > length/2) + n = length/2; + if (length > 1) + length -= n; + } + /* Enter the loop. */ while (length) { int ret; size_t nbytes; /* For a modern operating system, we use the new getentropy * function. That call guarantees that the kernel's RNG has * been properly seeded before returning any data. This is * different from /dev/urandom which may, due to its * non-blocking semantics, return data even if the kernel has * not been properly seeded. And it differs from /dev/random by * never blocking once the kernel is seeded. */ do { nbytes = length < sizeof (buffer)? length : sizeof (buffer); _gcry_pre_syscall (); ret = getentropy (buffer, nbytes); _gcry_post_syscall (); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == ENOSYS) log_fatal ("getentropy is not supported: %s\n", strerror (errno)); else { /* getentropy is supported. Some sanity checks. */ if (ret == -1) log_fatal ("unexpected error from getentropy: %s\n", strerror (errno)); (*add) (buffer, nbytes, origin); length -= nbytes; } } wipememory (buffer, sizeof buffer); return 0; /* success */ }