247b211
diff -up libgcrypt-1.6.1/random/random-fips.c.cfgrandom libgcrypt-1.6.1/random/random-fips.c
247b211
--- libgcrypt-1.6.1/random/random-fips.c.cfgrandom	2014-02-28 16:06:20.026572478 +0100
247b211
+++ libgcrypt-1.6.1/random/random-fips.c	2014-02-28 16:06:34.851915121 +0100
b0d0a7f
@@ -27,10 +27,10 @@
b0d0a7f
    There are 3 random context which map to the different levels of
b0d0a7f
    random quality:
b0d0a7f
 
b0d0a7f
-   Generator                Seed and Key        Kernel entropy (init/reseed)
b0d0a7f
-   ------------------------------------------------------------
b505458
-   GCRY_VERY_STRONG_RANDOM  /dev/random         256/128 bits
b505458
-   GCRY_STRONG_RANDOM       /dev/random         256/128 bits
b0d0a7f
+   Generator                Seed and Key                      Kernel entropy (init/reseed)
b0d0a7f
+   ---------------------------------------------------------------------------------------
b0d0a7f
+   GCRY_VERY_STRONG_RANDOM  /etc/gcrypt/rngseed+/dev/urandom  256/128 bits
b0d0a7f
+   GCRY_STRONG_RANDOM       /etc/gcrypt/rngseed+/dev/urandom  256/128 bits
b0d0a7f
    gcry_create_nonce        GCRY_STRONG_RANDOM  n/a
b0d0a7f
 
b0d0a7f
    All random generators return their data in 128 bit blocks.  If the
b505458
@@ -40,8 +40,10 @@
b0d0a7f
    (SEED_TTL) output blocks; the re-seeding is disabled in test mode.
b0d0a7f
 
b0d0a7f
    The GCRY_VERY_STRONG_RANDOM and GCRY_STRONG_RANDOM generators are
b505458
-   keyed and seeded from the /dev/random device.  Thus these
b505458
-   generators may block until the kernel has collected enough entropy.
b0d0a7f
+   keyed and seeded with data that is loaded from the /etc/gcrypt/rngseed
b0d0a7f
+   if the device or symlink to device exists xored with the data
b0d0a7f
+   from the /dev/urandom device. This allows the system administrator
b0d0a7f
+   to always seed the RNGs from /dev/random if it is required.
b0d0a7f
 
b0d0a7f
    The gcry_create_nonce generator is keyed and seeded from the
b0d0a7f
    GCRY_STRONG_RANDOM generator.  It may also block if the
b505458
@@ -560,9 +562,13 @@ get_entropy (size_t nbytes)
9371d8c
   entropy_collect_buffer_len = 0;
9371d8c
 
b0d0a7f
 #if USE_RNDLINUX
9371d8c
+  _gcry_rndlinux_gather_random (entropy_collect_cb, 0,
9371d8c
+                                     X931_AES_KEYLEN,
9371d8c
+                                     -1);
9371d8c
+  entropy_collect_buffer_len = 0;
b0d0a7f
   rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0,
b0d0a7f
                                      X931_AES_KEYLEN,
b505458
-                                     GCRY_VERY_STRONG_RANDOM);
b505458
+                                     GCRY_STRONG_RANDOM);
b505458
 #elif USE_RNDW32
b505458
   do
b505458
     {
247b211
@@ -713,7 +719,7 @@ get_random (void *buffer, size_t length,
247b211
       || rng_ctx->seed_init_pid != getpid ())
247b211
     {
247b211
       /* Just reinitialize the key & seed. */
247b211
-      gcry_cipher_close(rng_ctx->cipher_hd);
247b211
+      _gcry_cipher_close(rng_ctx->cipher_hd);
247b211
       rng_ctx->cipher_hd = NULL;
247b211
       rng_ctx->is_seeded = 0;
247b211
       goto reinitialize;
247b211
diff -up libgcrypt-1.6.1/random/rndlinux.c.cfgrandom libgcrypt-1.6.1/random/rndlinux.c
247b211
--- libgcrypt-1.6.1/random/rndlinux.c.cfgrandom	2013-12-16 18:44:32.000000000 +0100
247b211
+++ libgcrypt-1.6.1/random/rndlinux.c	2014-02-28 16:06:20.027572501 +0100
b505458
@@ -36,7 +36,9 @@
b0d0a7f
 #include "g10lib.h"
b0d0a7f
 #include "rand-internal.h"
b0d0a7f
 
247b211
-static int open_device (const char *name, int retry);
b0d0a7f
+#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed"
b0d0a7f
+
247b211
+static int open_device (const char *name, int retry, int fatal);
b0d0a7f
 
b0d0a7f
 
b0d0a7f
 static int
247b211
@@ -59,7 +61,7 @@ set_cloexec_flag (int fd)
247b211
  * a fatal error but retries until it is able to reopen the device.
b0d0a7f
  */
b0d0a7f
 static int
247b211
-open_device (const char *name, int retry)
247b211
+open_device (const char *name, int retry, int fatal)
b0d0a7f
 {
b0d0a7f
   int fd;
b0d0a7f
 
247b211
@@ -67,6 +69,8 @@ open_device (const char *name, int retry
247b211
     _gcry_random_progress ("open_dev_random", 'X', 1, 0);
247b211
  again:
247b211
   fd = open (name, O_RDONLY);
247b211
+  if (fd == -1 && !fatal)
247b211
+      return fd;
247b211
   if (fd == -1 && retry)
247b211
     {
247b211
       struct timeval tv;
247b211
@@ -111,6 +115,7 @@ _gcry_rndlinux_gather_random (void (*add
b0d0a7f
 {
b0d0a7f
   static int fd_urandom = -1;
b0d0a7f
   static int fd_random = -1;
b0d0a7f
+  static int fd_configured = -1;
247b211
   static unsigned char ever_opened;
b0d0a7f
   int fd;
b0d0a7f
   int n;
247b211
@@ -134,6 +139,11 @@ _gcry_rndlinux_gather_random (void (*add
247b211
           close (fd_urandom);
247b211
           fd_urandom = -1;
247b211
         }
247b211
+      if (fd_configured != -1)
247b211
+        {
247b211
+          close (fd_configured);
247b211
+          fd_configured = -1;
247b211
+        }
247b211
       return 0;
247b211
     }
b0d0a7f
 
247b211
@@ -153,20 +163,30 @@ _gcry_rndlinux_gather_random (void (*add
247b211
      that we always require the device to be existent but want a more
247b211
      graceful behaviour if the rarely needed close operation has been
247b211
      used and the device needs to be re-opened later. */
b0d0a7f
+
b0d0a7f
+  if (level == -1)
b0d0a7f
+    {
b0d0a7f
+      if (fd_configured == -1)
247b211
+        fd_configured = open_device ( NAME_OF_CFG_RNGSEED, 0, 0 );
b0d0a7f
+      fd = fd_configured;
b0d0a7f
+      if (fd == -1)
9371d8c
+        return -1;
b0d0a7f
+    }
b0d0a7f
+
b0d0a7f
   if (level >= 2)
b0d0a7f
     {
247b211
       if (fd_random == -1)
247b211
         {
247b211
-          fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1));
247b211
+          fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1), 1);
247b211
           ever_opened |= 1;
247b211
         }
b0d0a7f
       fd = fd_random;
b0d0a7f
     }
b0d0a7f
-  else
b0d0a7f
+  else if (level != -1)
b0d0a7f
     {
247b211
       if (fd_urandom == -1)
247b211
         {
247b211
-          fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2));
247b211
+          fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2), 1);
247b211
           ever_opened |= 2;
247b211
         }
b0d0a7f
       fd = fd_urandom;