File libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff of Package compat-libgcrypt11.3673

diff -rNU 20 ../libgcrypt-1.5.0-o/random/random-csprng.c ./random/random-csprng.c
--- ../libgcrypt-1.5.0-o/random/random-csprng.c	2011-10-18 13:39:24.000000000 +0200
+++ ./random/random-csprng.c	2011-10-18 13:39:41.000000000 +0200
@@ -810,41 +810,41 @@
   add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
   /* add some minor entropy to the pool now (this will also force a mixing) */
   {
     pid_t x = getpid();
     add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
   }
   {
     time_t x = time(NULL);
     add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
   }
   {
     clock_t x = clock();
     add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
   }
 
   /* And read a few bytes from our entropy source.  By using a level
    * of 0 this will not block and might not return anything with some
    * entropy drivers, however the rndlinux driver will use
    * /dev/urandom and return some stuff - Do not read too much as we
    * want to be friendly to the scare system entropy resource. */
-  read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM );
+  read_random_source ( RANDOM_ORIGIN_INIT, 16, -1 );
 
   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 )
diff -rNU 20 ../libgcrypt-1.5.0-o/random/random-fips.c ./random/random-fips.c
--- ../libgcrypt-1.5.0-o/random/random-fips.c	2011-10-18 13:39:24.000000000 +0200
+++ ./random/random-fips.c	2011-10-18 13:39:41.000000000 +0200
@@ -10,44 +10,44 @@
  *
  * Libgcrypt is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
    The core of this deterministic random number generator is
    implemented according to the document "NIST-Recommended Random
    Number Generator Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key
    Triple DES and AES Algorithms" (2005-01-31).  This implementation
    uses the AES variant.
 
    There are 3 random context which map to the different levels of
    random quality:
 
-   Generator                Seed and Key        Kernel entropy (init/reseed)
-   ------------------------------------------------------------
-   GCRY_VERY_STRONG_RANDOM  /dev/random         256/128 bits
-   GCRY_STRONG_RANDOM       /dev/random         256/128 bits
+   Generator                Seed and Key                      Kernel entropy (init/reseed)
+   ---------------------------------------------------------------------------------------
+   GCRY_VERY_STRONG_RANDOM  /etc/gcrypt/rngseed+/dev/urandom  256/128 bits
+   GCRY_STRONG_RANDOM       /etc/gcrypt/rngseed+/dev/urandom  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.
 
@@ -545,41 +545,41 @@
 }
 
 
 /* Get NBYTES of entropy from the kernel device.  The callers needs to
    free the returned buffer.  The function either succeeds or
    terminates the process in case of a fatal error. */
 static void *
 get_entropy (size_t nbytes)
 {
   void *result;
   int rc;
 
   gcry_assert (!entropy_collect_buffer);
   entropy_collect_buffer = gcry_xmalloc_secure (nbytes);
   entropy_collect_buffer_size = nbytes;
   entropy_collect_buffer_len = 0;
 
 #if USE_RNDLINUX
   rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0,
                                      X931_AES_KEYLEN,
-                                     GCRY_VERY_STRONG_RANDOM);
+                                     -1);
 #elif USE_RNDW32
   do
     {
       rc = _gcry_rndw32_gather_random (entropy_collect_cb, 0,
                                        X931_AES_KEYLEN,
                                        GCRY_VERY_STRONG_RANDOM);
     }
   while (rc >= 0 && entropy_collect_buffer_len < entropy_collect_buffer_size);
 #else
   rc = -1;
 #endif
 
   if (rc < 0 || entropy_collect_buffer_len != entropy_collect_buffer_size)
     {
       gcry_free (entropy_collect_buffer);
       entropy_collect_buffer = NULL;
       log_fatal ("error getting entropy data\n");
     }
   result = entropy_collect_buffer;
   entropy_collect_buffer = NULL;
diff -rNU 20 ../libgcrypt-1.5.0-o/random/rndlinux.c ./random/rndlinux.c
--- ../libgcrypt-1.5.0-o/random/rndlinux.c	2011-10-18 13:39:24.000000000 +0200
+++ ./random/rndlinux.c	2011-10-18 15:53:34.000000000 +0200
@@ -19,124 +19,157 @@
  */
 
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #ifdef HAVE_GETTIMEOFDAY
 # include <sys/times.h>
 #endif
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include "types.h"
 #include "g10lib.h"
 #include "rand-internal.h"
 
-static int open_device ( const char *name );
+#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed"
+static int open_device ( const char *name, int fatal );
 
 
 static int
 set_cloexec_flag (int fd)
 {
   int oldflags;
 
   oldflags= fcntl (fd, F_GETFD, 0);
   if (oldflags < 0)
     return oldflags;
   oldflags |= FD_CLOEXEC;
   return fcntl (fd, F_SETFD, oldflags);
 }
 
 
 
 /*
  * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists)).
  */
 static int
-open_device ( const char *name )
+open_device ( const char *name, int fatal )
 {
   int fd;
 
   fd = open ( name, O_RDONLY );
   if ( fd == -1 )
-    log_fatal ("can't open %s: %s\n", name, strerror(errno) );
+    {
+      if (fatal)
+        log_fatal ("can't open %s: %s\n", name, strerror(errno) );
+      return fd;
+    }
 
   if (set_cloexec_flag (fd))
     log_error ("error setting FD_CLOEXEC on fd %d: %s\n",
                fd, strerror (errno));
 
   /* We used to do the following check, however it turned out that this
      is not portable since more OSes provide a random device which is
      sometimes implemented as another device type.
 
      struct stat sb;
 
      if( fstat( fd, &sb ) )
         log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
      if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
         log_fatal("invalid random device!\n" );
   */
   return fd;
 }
 
 
 int
 _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
                                           enum random_origins),
                               enum random_origins origin,
                               size_t length, int level )
 {
   static int fd_urandom = -1;
   static int fd_random = -1;
+  static int fd_configured = -1;
   int fd;
   int n;
   byte buffer[768];
   size_t n_hw;
+  size_t orig_length = length;
   size_t want = length;
   size_t last_so_far = 0;
   int any_need_entropy = 0;
   int delay;
 
   /* First read from a hardware source.  However let it account only
      for up to 50% of the requested bytes.  */
   n_hw = _gcry_rndhw_poll_slow (add, origin);
   if (n_hw > length/2)
     n_hw = length/2;
   if (length > 1)
     length -= n_hw;
 
   /* Open the requested device.  */
+
+  /* Clarification: path how "level == -1" comes about:
+	gcry_random_bytes( ... , GCRY_STRONG_RANDOM) (public) ->
+	  do_randomize(buffer, nbytes, level) ->
+	    _gcry_rngcsprng_randomize(buffer, length, level) ->
+	      read_pool (p, n, level) ->
+	        read_seed_file(),
+	        random_poll() ->
+	          read_random_source(..., ..., GCRY_STRONG_RANDOM),
+		read_random_source(... , ..., , -1 ) (note: -1) ->
+		  slow_gather_fnc(..., ..., ..., level) 
+			function pointer set by getfnc_gather_random() to
+		    _gcry_rndlinux_gather_random() , which is here.
+   */
+            
+
+  if (level == -1)
+    {
+      if (fd_configured == -1)
+        fd_configured = open_device ( NAME_OF_CFG_RNGSEED, 0 );
+      fd = fd_configured;
+      if (fd == -1)
+        level = 1;
+    }
+
+
   if (level >= 2)
     {
       if( fd_random == -1 )
-        fd_random = open_device ( NAME_OF_DEV_RANDOM );
+        fd_random = open_device ( NAME_OF_DEV_RANDOM, 1 );
       fd = fd_random;
     }
-  else
+  else if (level != -1)
     {
       if( fd_urandom == -1 )
-        fd_urandom = open_device ( NAME_OF_DEV_URANDOM );
+        fd_urandom = open_device ( NAME_OF_DEV_URANDOM, 1 );
       fd = fd_urandom;
     }
 
   /* Enter the read loop.  */
   delay = 0;  /* Start with 0 seconds so that we do no block on the
                  first iteration and in turn call the progress function
                  before blocking.  To give the OS a better chance to
                  return with something we will actually use 100ms. */
   while (length)
     {
       fd_set rfds;
       struct timeval tv;
       int rc;
 
       FD_ZERO(&rfds);
       FD_SET(fd, &rfds);
       tv.tv_sec = delay;
       tv.tv_usec = delay? 0 : 100000;
       if ( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) )
         {
@@ -160,25 +193,28 @@
         }
 
       do
         {
           int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
           n = read(fd, buffer, nbytes );
           if( n >= 0 && n > nbytes )
             {
               log_error("bogus read from random device (n=%d)\n", n );
               n = nbytes;
             }
         }
       while( n == -1 && errno == EINTR );
       if ( n == -1 )
         log_fatal("read error on random device: %s\n", strerror(errno));
       (*add)( buffer, n, origin );
       length -= n;
     }
   memset(buffer, 0, sizeof(buffer) );
 
+  if (level == -1)
+       _gcry_rndlinux_gather_random(add, origin, orig_length, 1);
+
   if (any_need_entropy)
     _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want);
 
   return 0; /* success */
 }