* random.c: Fix prototype of the fast random gatherer. Noted by Joe
[gnupg.git] / cipher / random.c
index 8c552bd..4dd8d54 100644 (file)
@@ -1,5 +1,6 @@
 /* random.c  - random number generator
- *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002,
+ *               2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -15,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 
 #include <errno.h>
 #include <string.h>
 #include <time.h>
+#ifndef _WIN32
 #include <sys/time.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
-#ifdef HAVE_GETHRTIME
-  #include <sys/times.h>
+#ifdef HAVE_GETHRTIME
+#include <sys/times.h>
 #endif
 #ifdef HAVE_GETTIMEOFDAY
-  #include <sys/times.h>
+#include <sys/times.h>
+#endif
+#ifdef HAVE_TIMES
+#include <sys/times.h>
 #endif
 #ifdef HAVE_GETRUSAGE
-  #include <sys/resource.h>
+#include <sys/resource.h>
 #endif
-#ifdef __MINGW32__
-  #include <process.h>
+#ifdef _WIN32
+#include <process.h>
 #endif
 #include "util.h"
 #include "rmd.h"
 #include "i18n.h"
 #include "random.h"
 #include "rand-internal.h"
-#include "dynload.h"
-
+#include "algorithms.h"
 
 #ifndef RAND_MAX   /* for SunOS */
-  #define RAND_MAX 32767
+#define RAND_MAX 32767
 #endif
 
 
 #if SIZEOF_UNSIGNED_LONG == 8
-  #define ADD_VALUE 0xa5a5a5a5a5a5a5a5
+#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
 #elif SIZEOF_UNSIGNED_LONG == 4
-  #define ADD_VALUE 0xa5a5a5a5
+#define ADD_VALUE 0xa5a5a5a5
 #else
-  #error weird size for an unsigned long
+#error weird size for an unsigned long
 #endif
 
 #define BLOCKLEN  64   /* hash this amount of bytes */
@@ -82,7 +88,7 @@
 #define POOLBLOCKS 30
 #define POOLSIZE (POOLBLOCKS*DIGESTLEN)
 #if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
-  #error Please make sure that poolsize is a multiple of ulong
+#error Please make sure that poolsize is a multiple of ulong
 #endif
 #define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
 
@@ -125,6 +131,69 @@ static struct {
     ulong naddbytes;
 } rndstats;
 
+
+static int (*
+getfnc_gather_random (void))(void (*)(const void*, size_t, int), int,
+                        size_t, int)
+{
+#ifdef USE_ALL_RANDOM_MODULES
+  static int (*fnc)(void (*)(const void*, size_t, int), int, size_t, int);
+  
+  if (fnc)
+    return fnc;
+# ifdef USE_RNDLINUX
+  if ( !access (NAME_OF_DEV_RANDOM, R_OK)
+       && !access (NAME_OF_DEV_URANDOM, R_OK))
+    {
+      fnc = rndlinux_gather_random;
+      return fnc;
+    }
+# endif
+# ifdef USE_RNDEGD
+  if ( rndegd_connect_socket (1) != -1 )
+    {
+      fnc = rndegd_gather_random;
+      return fnc;
+    }
+# endif
+# ifdef USE_RNDUNIX
+  fnc = rndunix_gather_random;
+  return fnc;
+# endif
+
+  log_fatal (_("no entropy gathering module detected\n"));
+
+#else
+# ifdef USE_RNDLINUX
+  return rndlinux_gather_random;
+# endif
+# ifdef USE_RNDUNIX
+  return rndunix_gather_random;
+# endif
+# ifdef USE_RNDEGD
+  return rndegd_gather_random;
+# endif
+# ifdef USE_RNDW32
+  return rndw32_gather_random;
+# endif
+# ifdef USE_RNDRISCOS
+  return rndriscos_gather_random;
+# endif
+#endif
+  return NULL;
+}
+
+static int (*
+getfnc_fast_random_poll (void))( void (*)(const void*, size_t, int), int)
+{
+#ifdef USE_RNDW32
+  return rndw32_gather_random_fast;
+#endif
+  return NULL;
+}
+
+
+
 static void
 initialize(void)
 {
@@ -136,7 +205,6 @@ initialize(void)
     keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
                           : m_alloc_clear(POOLSIZE+BLOCKLEN);
     is_initialized = 1;
-    cipher_modules_constructor();
 }
 
 static void
@@ -144,7 +212,7 @@ burn_stack (int bytes)
 {
     char buf[128];
     
-    memset (buf, 0, sizeof buf);
+    wipememory(buf,sizeof buf);
     bytes -= sizeof buf;
     if (bytes > 0)
         burn_stack (bytes);
@@ -250,9 +318,9 @@ mix_pool(byte *pool)
     RMD160_CONTEXT md;
 
     rmd160_init( &md );
- #if DIGESTLEN != 20
-    #error must have a digest length of 20 for ripe-md-160
- #endif
+#if DIGESTLEN != 20
+#error must have a digest length of 20 for ripe-md-160
+#endif
     /* loop over the pool */
     pend = pool + POOLSIZE;
     memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
@@ -306,11 +374,11 @@ read_seed_file(void)
     if( !seed_file_name )
        return 0;
 
-  #ifdef HAVE_DOSISH_SYSTEM
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
     fd = open( seed_file_name, O_RDONLY | O_BINARY );
-  #else
+#else
     fd = open( seed_file_name, O_RDONLY );
-  #endif
+#endif
     if( fd == -1 && errno == ENOENT) {
        allow_seed_file_update = 1;
        return 0;
@@ -337,7 +405,7 @@ read_seed_file(void)
        return 0;
     }
     if( sb.st_size != POOLSIZE ) {
-       log_info(_("warning: invalid size of random_seed file - not used\n") );
+       log_info(_("WARNING: invalid size of random_seed file - not used\n") );
        close(fd);
        return 0;
     }
@@ -396,12 +464,12 @@ update_random_seed_file()
     mix_pool(rndpool); rndstats.mixrnd++;
     mix_pool(keypool); rndstats.mixkey++;
 
-  #ifdef HAVE_DOSISH_SYSTEM
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
     fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
                                                        S_IRUSR|S_IWUSR );
-  #else
+#else
     fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
-  #endif
+#endif
     if( fd == -1 ) {
        log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
        return;
@@ -503,7 +571,7 @@ read_pool( byte *buffer, size_t length, int level )
        if( pool_balance < 0 )
            pool_balance = 0;
        /* and clear the keypool */
-       memset( keypool, 0, POOLSIZE );
+       wipememory(keypool, POOLSIZE);
     }
 }
 
@@ -552,7 +620,7 @@ random_poll()
 void
 fast_random_poll()
 {
-    static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
+    static int (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
     static int initialized = 0;
 
     rndstats.fastpolls++;
@@ -560,7 +628,7 @@ fast_random_poll()
        if( !is_initialized )
            initialize();
        initialized = 1;
-       fnc = dynload_getfnc_fast_random_poll();
+       fnc = getfnc_fast_random_poll();
     }
     if( fnc ) {
        (*fnc)( add_randomness, 1 );
@@ -568,41 +636,40 @@ fast_random_poll()
     }
 
     /* fall back to the generic function */
-  #if defined(HAVE_GETHRTIME) && !defined(HAVE_BROKEN_GETHRTIME)
+#if defined(HAVE_GETHRTIME) && !defined(HAVE_BROKEN_GETHRTIME)
     {  hrtime_t tv;
         /* On some Solaris and HPUX system gethrtime raises an SIGILL, but we 
          * checked this with configure */
        tv = gethrtime();
        add_randomness( &tv, sizeof(tv), 1 );
     }
-  #elif defined (HAVE_GETTIMEOFDAY)
+#elif defined (HAVE_GETTIMEOFDAY)
     {  struct timeval tv;
        if( gettimeofday( &tv, NULL ) )
            BUG();
        add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
        add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
     }
-  #elif defined (HAVE_CLOCK_GETTIME)
+#elif defined (HAVE_CLOCK_GETTIME)
     {  struct timespec tv;
        if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
            BUG();
        add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
        add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
     }
-  #else /* use times */
-    #ifndef HAVE_DOSISH_SYSTEM
+#elif defined (HAVE_TIMES)
     {  struct tms buf;
-       times( &buf );
+        if( times( &buf ) == -1 )
+           BUG();
        add_randomness( &buf, sizeof buf, 1 );
     }
-    #endif
-  #endif
-  #ifdef HAVE_GETRUSAGE
-    #ifndef RUSAGE_SELF
-      #ifdef __GCC__
-       #warning There is no RUSAGE_SELF on this system
-      #endif
-    #else
+#endif
+#ifdef HAVE_GETRUSAGE
+#ifndef RUSAGE_SELF
+#ifdef __GCC__
+#warning There is no RUSAGE_SELF on this system
+#endif
+#else
     {  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
@@ -612,10 +679,10 @@ fast_random_poll()
         getrusage( RUSAGE_SELF, &buf );
         
        add_randomness( &buf, sizeof buf, 1 );
-       memset( &buf, 0, sizeof buf );
+       wipememory( &buf, sizeof buf );
     }
-    #endif
-  #endif
+#endif
+#endif
     /* time and clock are available on all systems - so
      * we better do it just in case one of the above functions
      * didn't work */
@@ -637,7 +704,7 @@ read_random_source( int requester, size_t length, int level )
     if( !fnc ) {
        if( !is_initialized )
            initialize();
-       fnc = dynload_getfnc_gather_random();
+       fnc = getfnc_gather_random();
        if( !fnc ) {
            faked_rng = 1;
            fnc = gather_faked;
@@ -664,24 +731,23 @@ gather_faked( void (*add)(const void*, size_t, int), int requester,
                   "it run - it is in no way a strong RNG!\n\n"
                   "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
        initialized=1;
-      #ifdef HAVE_RAND
+#ifdef HAVE_RAND
        srand(make_timestamp()*getpid());
-      #else
+#else
        srandom(make_timestamp()*getpid());
-      #endif
+#endif
     }
 
     p = buffer = m_alloc( length );
     n = length;
-  #ifdef HAVE_RAND
+#ifdef HAVE_RAND
     while( n-- )
        *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
-  #else
+#else
     while( n-- )
        *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
-  #endif
+#endif
     add_randomness( buffer, length, requester );
     m_free(buffer);
     return 0; /* okay */
 }
-