File libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff of Package libgcrypt

From: draht@suse.com
Subject: /etc/gcrypt/rngseed symlink

logic error in evaluation of routine to open /dev/{u,}random or
/etc/gcrypt/rngseed (open_device()) causes abort() in cases where
do_randomize(nbytes, level) is called with level == 1
(GCRY_STRONG_RANDOM).

References: bnc#724841
https://bugzilla.novell.com/show_bug.cgi?id=724841

---
 random/random-csprng.c |    2 +-
 random/random-fips.c   |   10 +++++-----
 random/rndlinux.c      |   48 ++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 48 insertions(+), 12 deletions(-)

Index: libgcrypt-1.5.2/random/random-csprng.c
===================================================================
--- libgcrypt-1.5.2.orig/random/random-csprng.c
+++ libgcrypt-1.5.2/random/random-csprng.c
@@ -827,7 +827,7 @@ read_seed_file (void)
    * 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;
Index: libgcrypt-1.5.2/random/random-fips.c
===================================================================
--- libgcrypt-1.5.2.orig/random/random-fips.c
+++ libgcrypt-1.5.2/random/random-fips.c
@@ -27,10 +27,10 @@
    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
@@ -562,7 +562,7 @@ get_entropy (size_t nbytes)
 #if USE_RNDLINUX
   rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0,
                                      X931_AES_KEYLEN,
-                                     GCRY_VERY_STRONG_RANDOM);
+                                     -1);
 #elif USE_RNDW32
   do
     {
Index: libgcrypt-1.5.2/random/rndlinux.c
===================================================================
--- libgcrypt-1.5.2.orig/random/rndlinux.c
+++ libgcrypt-1.5.2/random/rndlinux.c
@@ -36,7 +36,8 @@
 #include "g10lib.h"
 #include "rand-internal.h"
 
-static int open_device ( const char *name );
+static int open_device ( const char *name, int fatal );
+#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed"
 
 
 static int
@@ -57,13 +58,17 @@ set_cloexec_flag (int fd)
  * 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",
@@ -92,10 +97,12 @@ _gcry_rndlinux_gather_random (void (*add
 {
   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;
@@ -110,16 +117,42 @@ _gcry_rndlinux_gather_random (void (*add
     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;
     }
 
@@ -187,6 +220,9 @@ _gcry_rndlinux_gather_random (void (*add
     }
   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);
 
openSUSE Build Service is sponsored by