2003-04-16 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / cipher / random.c
1 /* random.c  -  random number generator
2  * Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /****************
22  * This random number generator is modelled after the one described
23  * in Peter Gutmann's Paper: "Software Generation of Practically
24  * Strong Random Numbers".
25  */
26
27
28 #include <config.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <time.h>
40 #ifdef  HAVE_GETHRTIME
41   #include <sys/times.h>
42 #endif
43 #ifdef HAVE_GETTIMEOFDAY
44   #include <sys/times.h>
45 #endif
46 #ifdef HAVE_GETRUSAGE
47   #include <sys/resource.h>
48 #endif
49 #ifdef __MINGW32__
50   #include <process.h>
51 #endif
52 #include "g10lib.h"
53 #include "rmd.h"
54 #include "random.h"
55 #include "rand-internal.h"
56 //#include "dynload.h"
57 #include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */
58 #include "ath.h"
59
60 #ifndef RAND_MAX   /* for SunOS */
61   #define RAND_MAX 32767
62 #endif
63
64
65 #if SIZEOF_UNSIGNED_LONG == 8
66   #define ADD_VALUE 0xa5a5a5a5a5a5a5a5
67 #elif SIZEOF_UNSIGNED_LONG == 4
68   #define ADD_VALUE 0xa5a5a5a5
69 #else
70   #error weird size for an unsigned long
71 #endif
72
73 #define BLOCKLEN  64   /* hash this amount of bytes */
74 #define DIGESTLEN 20   /* into a digest of this length (rmd160) */
75 /* poolblocks is the number of digests which make up the pool
76  * and poolsize must be a multiple of the digest length
77  * to make the AND operations faster, the size should also be
78  * a multiple of ulong
79  */
80 #define POOLBLOCKS 30
81 #define POOLSIZE (POOLBLOCKS*DIGESTLEN)
82 #if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
83   #error Please make sure that poolsize is a multiple of ulong
84 #endif
85 #define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
86
87
88 static int is_initialized;
89 #define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0)
90 static char *rndpool;   /* allocated size is POOLSIZE+BLOCKLEN */
91 static char *keypool;   /* allocated size is POOLSIZE+BLOCKLEN */
92 static size_t pool_readpos;
93 static size_t pool_writepos;
94 static int pool_filled;
95 static int pool_balance;
96 static int just_mixed;
97 static int did_initial_extra_seeding;
98 static char *seed_file_name;
99 static int allow_seed_file_update;
100
101 static unsigned char failsafe_digest[DIGESTLEN];
102 static int failsafe_digest_valid;
103
104 static int secure_alloc;
105 static int quick_test;
106 static int faked_rng;
107
108 static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER;
109 static int pool_is_locked; /* only used for assertion */
110
111 static byte *get_random_bytes( size_t nbytes, int level, int secure );
112 static void read_pool( byte *buffer, size_t length, int level );
113 static void add_randomness( const void *buffer, size_t length, int source );
114 static void random_poll(void);
115 static void do_fast_random_poll (void);
116 static void read_random_source( int requester, size_t length, int level);
117 static int gather_faked( void (*add)(const void*, size_t, int), int requester,
118                                                     size_t length, int level );
119
120 static struct {
121     ulong mixrnd;
122     ulong mixkey;
123     ulong slowpolls;
124     ulong fastpolls;
125     ulong getbytes1;
126     ulong ngetbytes1;
127     ulong getbytes2;
128     ulong ngetbytes2;
129     ulong addbytes;
130     ulong naddbytes;
131 } rndstats;
132
133 static void (*progress_cb) (void *,const char*,int,int, int );
134 static void *progress_cb_data;
135
136 /* Note, we assume that this function is used before any concurrent
137    access happens */
138 static void
139 initialize(void)
140 {
141   int err;
142
143   err = ath_mutex_init (&pool_lock);
144   if (err)
145     log_fatal ("failed to create the pool lock: %s\n", strerror (err) );
146     
147   /* The data buffer is allocated somewhat larger, so that we can use
148     this extra space (which is allocated in secure memory) as a
149     temporary hash buffer */
150   rndpool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
151                          : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
152   keypool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
153                          : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
154   is_initialized = 1;
155
156   //_gcry_cipher_modules_constructor ();
157 }
158
159
160 /* Used to register a progress callback. */
161 void
162 _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
163                                 void *cb_data )
164 {
165   progress_cb = cb;
166   progress_cb_data = cb_data;
167 }
168
169
170 /* This progress function is currently used by the random modules to give hint
171    on how much more entropy is required. */
172 void
173 _gcry_random_progress (const char *what, int printchar, int current, int total)
174 {
175   if (progress_cb)
176     progress_cb (progress_cb_data, what, printchar, current, total);
177 }
178
179
180 /* Initialize this random subsystem.  This function memrely calls the
181    initialzies and does not do anything more.  Doing this is not
182    really required but when running in a threaded environment we might
183    get a race condition otherwise. */
184 void
185 _gcry_random_initialize ()
186 {
187   if (!is_initialized)
188     initialize ();
189 }
190
191 void
192 _gcry_random_dump_stats()
193 {
194     log_info (
195             "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
196             "              outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n",
197         POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
198                   rndstats.naddbytes, rndstats.addbytes,
199         rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
200                     rndstats.ngetbytes2, rndstats.getbytes2 );
201 }
202
203 void
204 _gcry_secure_random_alloc()
205 {
206     secure_alloc = 1;
207 }
208
209
210 int
211 _gcry_quick_random_gen( int onoff )
212 {
213     int last;
214
215     /* No need to lock it here because we are only initializing.  A
216        prerequisite of the entire code is that it has already been
217        initialized before any possible concurrent access */
218     read_random_source(0,0,0); /* init */
219     last = quick_test;
220     if( onoff != -1 )
221         quick_test = onoff;
222     return faked_rng? 1 : last;
223 }
224
225 int
226 _gcry_random_is_faked()
227 {
228     if( !is_initialized )
229         initialize();
230     return faked_rng || quick_test;
231 }
232
233 /****************
234  * Return a pointer to a randomized buffer of level 0 and LENGTH bits
235  * caller must free the buffer.
236  * Note: The returned value is rounded up to bytes.
237  */
238 static byte *
239 get_random_bytes( size_t nbytes, int level, int secure )
240 {
241     byte *buf, *p;
242     int err;
243
244     if( quick_test && level > 1 )
245         level = 1;
246     MASK_LEVEL(level);
247
248     err = ath_mutex_lock (&pool_lock);
249     if (err)
250       log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
251     pool_is_locked = 1;
252     if( level == 1 ) {
253         rndstats.getbytes1 += nbytes;
254         rndstats.ngetbytes1++;
255     }
256     else if( level >= 2 ) {
257         rndstats.getbytes2 += nbytes;
258         rndstats.ngetbytes2++;
259     }
260
261     buf = secure && secure_alloc ? gcry_xmalloc_secure( nbytes )
262                                  : gcry_xmalloc( nbytes );
263     for( p = buf; nbytes > 0; ) {
264         size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes;
265         read_pool( p, n, level );
266         nbytes -= n;
267         p += n;
268     }
269
270     pool_is_locked = 0;
271     err = ath_mutex_unlock (&pool_lock);
272     if (err)
273       log_fatal ("failed to release the pool lock: %s\n", strerror (err));
274     return buf;
275 }
276
277
278 /* Add BUFLEN bytes from BUF to the internal random pool.  QUALITY
279    should be in the range of 0..100 to indicate the goodness of the
280    entropy added, or -1 for goodness not known. 
281
282    Note, that this fucntion currently does nothing.
283 */
284 int 
285 gcry_random_add_bytes (const void * buf, size_t buflen, int quality)
286 {
287   if (!buf || quality < -1 || quality > 100)
288     return GCRYERR_INV_ARG;
289   if (!buflen)
290     return 0; /* Shortcut this dummy case. */
291   /* Before we actuall enbale this code, we need to lock the pool,
292      have a look at the quality and find a way to add them without
293      disturbing the real entropy (we have estimated). */
294   /*add_randomness( buf, buflen, 1 );*/
295   return 0;
296 }   
297     
298
299 void *
300 gcry_random_bytes( size_t nbytes, enum gcry_random_level level )
301 {
302   if (!is_initialized)
303     initialize();
304   return get_random_bytes( nbytes, level, 0 );
305 }
306
307 void *
308 gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level )
309 {
310   if (!is_initialized)
311     initialize();
312   return get_random_bytes( nbytes, level, 1 );
313 }
314
315
316 /* Fill the buffer with LENGTH bytes of cryptographically strong
317    random bytes. level 0 is not very strong, 1 is strong enough for
318    most usage, 2 is good for key generation stuff but may be very
319    slow.  */
320 void
321 gcry_randomize (byte *buffer, size_t length, enum gcry_random_level level)
322 {
323   byte *p;
324   int err;
325
326   if (!is_initialized)
327     initialize ();
328
329   if( quick_test && level > 1 )
330     level = 1;
331   MASK_LEVEL(level);
332
333   err = ath_mutex_lock (&pool_lock);
334   if (err)
335     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
336   pool_is_locked = 1;
337   if (level == 1)
338     {
339       rndstats.getbytes1 += length;
340       rndstats.ngetbytes1++;
341     }
342   else if (level >= 2)
343     {
344       rndstats.getbytes2 += length;
345       rndstats.ngetbytes2++;
346     }
347
348   for (p = buffer; length > 0;)
349     {
350       size_t n = length > POOLSIZE? POOLSIZE : length;
351       read_pool (p, n, level);
352       length -= n;
353       p += n;
354     }
355
356   pool_is_locked = 0;
357   err = ath_mutex_unlock (&pool_lock);
358   if (err)
359     log_fatal ("failed to release the pool lock: %s\n", strerror (err));
360 }
361
362
363
364
365 /*
366    Mix the pool:
367
368    |........blocks*20byte........|20byte|..44byte..|
369    <..44byte..>           <20byte> 
370         |                    |
371         |                    +------+
372         +---------------------------|----------+
373                                     v          v
374    |........blocks*20byte........|20byte|..44byte..|
375                                  <.....64bytes.....>   
376                                          |
377       +----------------------------------+
378      Hash
379       v
380    |.............................|20byte|..44byte..|
381    <20byte><20byte><..44byte..>
382       |                |
383       |                +---------------------+
384       +-----------------------------+        |
385                                     v        v
386    |.............................|20byte|..44byte..|
387                                  <.....64byte......>
388                                         |
389               +-------------------------+
390              Hash
391               v
392    |.............................|20byte|..44byte..|
393    <20byte><20byte><..44byte..>
394
395    and so on until we did this for all blocks. 
396
397  */
398 static void
399 mix_pool(byte *pool)
400 {
401     char *hashbuf = pool + POOLSIZE;
402     char *p, *pend;
403     int i, n;
404     RMD160_CONTEXT md;
405
406     assert (pool_is_locked);
407     _gcry_rmd160_init( &md );
408 #if DIGESTLEN != 20
409 #  error must have a digest length of 20 for ripe-md-160
410 #endif
411     /* loop over the pool */
412     pend = pool + POOLSIZE;
413     memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
414     memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
415     _gcry_rmd160_mixblock( &md, hashbuf);
416     memcpy(pool, hashbuf, 20 );
417     if (failsafe_digest_valid && (char *)pool == rndpool)
418       {
419         for (i=0; i < 20; i++)
420           pool[i] ^= failsafe_digest[i];
421       }
422
423     p = pool;
424     for( n=1; n < POOLBLOCKS; n++ ) {
425         memcpy(hashbuf, p, DIGESTLEN );
426
427         p += DIGESTLEN;
428         if( p+DIGESTLEN+BLOCKLEN < pend )
429             memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
430         else {
431             char *pp = p+DIGESTLEN;
432             for(i=DIGESTLEN; i < BLOCKLEN; i++ ) {
433                 if( pp >= pend )
434                     pp = pool;
435                 hashbuf[i] = *pp++;
436             }
437         }
438
439         _gcry_rmd160_mixblock( &md, hashbuf);
440         memcpy(p, hashbuf, 20 );
441     }
442     /* Hmmm: our hash implementation does only leave small parts (64
443        bytes) of the pool on the stack, so I thnik it ios okay not to
444        require secure memory here.  Before we use this pool, it gets
445        copied to the help buffer anyway. */
446     if ( (char*)pool == rndpool)
447       {
448         _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE);
449         failsafe_digest_valid = 1;
450       }
451     _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */
452 }
453
454 void
455 _gcry_set_random_seed_file( const char *name )
456 {
457     if( seed_file_name )
458         BUG();
459     seed_file_name = gcry_xstrdup( name );
460 }
461
462 /****************
463  * Read in a seed form the random_seed file
464  * and return true if this was successful
465  */
466 static int
467 read_seed_file()
468 {
469     int fd;
470     struct stat sb;
471     unsigned char buffer[POOLSIZE];
472     int n;
473
474     assert (pool_is_locked);
475     if( !seed_file_name )
476         return 0;
477
478   #ifdef HAVE_DOSISH_SYSTEM
479     fd = open( seed_file_name, O_RDONLY | O_BINARY );
480   #else
481     fd = open( seed_file_name, O_RDONLY );
482   #endif
483     if( fd == -1 && errno == ENOENT) {
484         allow_seed_file_update = 1;
485         return 0;
486     }
487
488     if( fd == -1 ) {
489         log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
490         return 0;
491     }
492     if( fstat( fd, &sb ) ) {
493         log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
494         close(fd);
495         return 0;
496     }
497     if( !S_ISREG(sb.st_mode) ) {
498         log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
499         close(fd);
500         return 0;
501     }
502     if( !sb.st_size ) {
503         log_info(_("note: random_seed file is empty\n") );
504         close(fd);
505         allow_seed_file_update = 1;
506         return 0;
507     }
508     if( sb.st_size != POOLSIZE ) {
509         log_info(_("warning: invalid size of random_seed file - not used\n") );
510         close(fd);
511         return 0;
512     }
513     do {
514         n = read( fd, buffer, POOLSIZE );
515     } while( n == -1 && errno == EINTR );
516     if( n != POOLSIZE ) {
517         log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
518         close(fd);
519         return 0;
520     }
521
522     close(fd);
523
524     add_randomness( buffer, POOLSIZE, 0 );
525     /* add some minor entropy to the pool now (this will also force a mixing) */
526     {   pid_t x = getpid();
527         add_randomness( &x, sizeof(x), 0 );
528     }
529     {   time_t x = time(NULL);
530         add_randomness( &x, sizeof(x), 0 );
531     }
532     {   clock_t x = clock();
533         add_randomness( &x, sizeof(x), 0 );
534     }
535     /* And read a few bytes from our entropy source.  By using
536      * a level of 0 this will not block and might not return anything
537      * with some entropy drivers, however the rndlinux driver will use
538      * /dev/urandom and return some stuff - Do not read to much as we
539      * want to be friendly to the scare system entropy resource. */
540     read_random_source( 0, 16, 0 );
541
542     allow_seed_file_update = 1;
543     return 1;
544 }
545
546 void
547 _gcry_update_random_seed_file()
548 {
549   ulong *sp, *dp;
550   int fd, i;
551   int err;
552   
553   if ( !seed_file_name || !is_initialized || !pool_filled )
554     return;
555   if ( !allow_seed_file_update )
556     {
557       log_info(_("note: random_seed file not updated\n"));
558       return;
559     }
560
561   err = ath_mutex_lock (&pool_lock);
562   if (err)
563     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
564   pool_is_locked = 1;
565
566     /* copy the entropy pool to a scratch pool and mix both of them */
567   for (i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
568        i < POOLWORDS; i++, dp++, sp++ ) 
569     {
570       *dp = *sp + ADD_VALUE;
571     }
572   mix_pool(rndpool); rndstats.mixrnd++;
573   mix_pool(keypool); rndstats.mixkey++;
574
575 #ifdef HAVE_DOSISH_SYSTEM
576   fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
577              S_IRUSR|S_IWUSR );
578 #else
579   fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
580 #endif
581
582   if (fd == -1 )
583     log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
584   else 
585     {
586       do {
587         i = write (fd, keypool, POOLSIZE );
588       } while( i == -1 && errno == EINTR );
589     if (i != POOLSIZE) 
590       log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) );
591     if (close(fd))
592       log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) );
593     }
594
595   pool_is_locked = 0;
596   err = ath_mutex_unlock (&pool_lock);
597   if (err)
598     log_fatal ("failed to release the pool lock: %s\n", strerror (err));
599 }
600
601
602 static void
603 read_pool( byte *buffer, size_t length, int level )
604 {
605     int i;
606     ulong *sp, *dp;
607
608     assert (pool_is_locked);
609     if( length > POOLSIZE ) {
610         log_bug("too many random bits requested\n");
611     }
612
613     if( !pool_filled ) {
614         if( read_seed_file() )
615             pool_filled = 1;
616     }
617
618     /* For level 2 quality (key generation) we always make
619      * sure that the pool has been seeded enough initially */
620     if( level == 2 && !did_initial_extra_seeding ) {
621         size_t needed;
622
623         pool_balance = 0;
624         needed = length - pool_balance;
625         if( needed < POOLSIZE/2 )
626             needed = POOLSIZE/2;
627         else if( needed > POOLSIZE )
628             BUG();
629         read_random_source( 3, needed, 2 );
630         pool_balance += needed;
631         did_initial_extra_seeding=1;
632     }
633
634     /* for level 2 make sure that there is enough random in the pool */
635     if( level == 2 && pool_balance < length ) {
636         size_t needed;
637
638         if( pool_balance < 0 )
639             pool_balance = 0;
640         needed = length - pool_balance;
641         if( needed > POOLSIZE )
642             BUG();
643         read_random_source( 3, needed, 2 );
644         pool_balance += needed;
645     }
646
647     /* make sure the pool is filled */
648     while( !pool_filled )
649         random_poll();
650
651     /* always do a fast random poll - we have to use the unlocked version*/
652     do_fast_random_poll();
653
654     if( !level ) { /* no need for cryptographic strong random */
655         /* create a new pool */
656         for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
657                                     i < POOLWORDS; i++, dp++, sp++ )
658             *dp = *sp + ADD_VALUE;
659         /* must mix both pools */
660         mix_pool(rndpool); rndstats.mixrnd++;
661         mix_pool(keypool); rndstats.mixkey++;
662         memcpy( buffer, keypool, length );
663     }
664     else {
665         /* mix the pool (if add_randomness() didn't it) */
666         if( !just_mixed ) {
667             mix_pool(rndpool);
668             rndstats.mixrnd++;
669         }
670         /* create a new pool */
671         for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
672                                     i < POOLWORDS; i++, dp++, sp++ )
673             *dp = *sp + ADD_VALUE;
674         /* and mix both pools */
675         mix_pool(rndpool); rndstats.mixrnd++;
676         mix_pool(keypool); rndstats.mixkey++;
677         /* read the required data
678          * we use a readpoiter to read from a different postion each
679          * time */
680         while( length-- ) {
681             *buffer++ = keypool[pool_readpos++];
682             if( pool_readpos >= POOLSIZE )
683                 pool_readpos = 0;
684             pool_balance--;
685         }
686         if( pool_balance < 0 )
687             pool_balance = 0;
688         /* and clear the keypool */
689         memset( keypool, 0, POOLSIZE );
690     }
691 }
692
693
694 /****************
695  * Add LENGTH bytes of randomness from buffer to the pool.
696  * source may be used to specify the randomness source.
697  * Source is:
698  *      0 - used ony for initialization
699  *      1 - fast random poll function
700  *      2 - normal poll function
701  *      3 - used when level 2 random quality has been requested
702  *          to do an extra pool seed.
703  */
704 static void
705 add_randomness( const void *buffer, size_t length, int source )
706 {
707     const byte *p = buffer;
708
709     assert (pool_is_locked);
710     if( !is_initialized )
711         initialize();
712     rndstats.addbytes += length;
713     rndstats.naddbytes++;
714     while( length-- ) {
715         rndpool[pool_writepos++] ^= *p++;
716         if( pool_writepos >= POOLSIZE ) {
717             if( source > 1 )
718                 pool_filled = 1;
719             pool_writepos = 0;
720             mix_pool(rndpool); rndstats.mixrnd++;
721             just_mixed = !length;
722         }
723     }
724 }
725
726
727
728 static void
729 random_poll()
730 {
731     rndstats.slowpolls++;
732     read_random_source( 2, POOLSIZE/5, 1 );
733 }
734
735 static int (*
736 getfnc_gather_random (void))(void (*)(const void*, size_t, int), int,
737                              size_t, int)
738 {
739 #if USE_RNDLINUX
740   int rndlinux_gather_random (void (*add) (const void *, size_t, int),
741                               int requester, size_t length, int level);
742 #endif
743 #if USE_RNDUNIX
744   int rndunix_gather_random (void (*add) (const void *, size_t, int),
745                              int requester, size_t length, int level);
746 #endif
747 #if USE_RNDEGD
748   int rndegd_gather_random (void (*add) (const void *, size_t, int),
749                             int requester, size_t length, int level);
750   int rndegd_connect_socket (int nofail);
751 #endif
752 #if USE_RNDW32
753   int rndw32_gather_random (void (*add) (const void *, size_t, int),
754                             int requester, size_t length, int level);
755 #endif
756
757 #ifdef USE_ALL_RANDOM_MODULES
758   static int (*fnc)(void (*)(const void*, size_t, int), int, size_t, int);
759   
760   if (fnc)
761     return fnc;
762 # if USE_RNDLINUX
763   if ( !access (NAME_OF_DEV_RANDOM, R_OK)
764        && !access (NAME_OF_DEV_RANDOM, R_OK))
765     {
766       fnc = rndlinux_gather_random;
767       return fnc;
768     }
769 # endif
770 # if USE_RNDEGD
771   if ( rndegd_connect_socket (1) != -1 )
772     {
773       fnc = rndegd_gather_random;
774       return fnc;
775     }
776 # endif
777 # if USE_RNDUNIX
778   fnc = rndunix_gather_random;
779   return fnc;
780 # endif
781
782   log_fatal (_("no entropy gathering module detected\n"));
783
784 #else
785 # if USE_RNDLINUX
786   return rndlinux_gather_random;
787 # endif
788 # if USE_RNDUNIX
789   return rndunix_gather_random;
790 # endif
791 # if USE_RNDEGD
792   return rndegd_gather_random;
793 # endif
794 # if USE_RNDW32
795   return rndw32_gather_random;
796 # endif
797 # if USE_RNDRISCOS
798   return rndriscos_gather_random;
799 # endif
800 #endif
801   return NULL;
802 }
803
804 static void (*
805 getfnc_fast_random_poll (void))( void (*)(const void*, size_t, int), int)
806 {
807 #if USE_RNDW32
808   int rndw32_gather_random_fast (void (*add) (const void *, size_t, int),
809                                  int requester);
810   return rndw32_gather_random_fast;
811 #endif
812   return NULL;
813 }
814
815
816 static void
817 do_fast_random_poll ()
818 {
819     static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
820     static int initialized = 0;
821
822     assert (pool_is_locked);
823     rndstats.fastpolls++;
824     if( !initialized ) {
825         if( !is_initialized )
826             initialize();
827         initialized = 1;
828         fnc = getfnc_fast_random_poll ();
829     }
830     if( fnc ) {
831         (*fnc)( add_randomness, 1 );
832         return;
833     }
834
835     /* fall back to the generic function */
836   #if HAVE_GETHRTIME
837     {   hrtime_t tv;
838         tv = gethrtime();
839         add_randomness( &tv, sizeof(tv), 1 );
840     }
841   #elif HAVE_GETTIMEOFDAY
842     {   struct timeval tv;
843         if( gettimeofday( &tv, NULL ) )
844             BUG();
845         add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
846         add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
847     }
848   #elif HAVE_CLOCK_GETTIME
849     {   struct timespec tv;
850         if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
851             BUG();
852         add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
853         add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
854     }
855   #else /* use times */
856     #ifndef HAVE_DOSISH_SYSTEM
857     {   struct tms buf;
858         times( &buf );
859         add_randomness( &buf, sizeof buf, 1 );
860     }
861     #endif
862   #endif
863   #ifdef HAVE_GETRUSAGE
864     #ifndef RUSAGE_SELF
865       #ifdef __GCC__
866         #warning There is no RUSAGE_SELF on this system
867       #endif
868     #else
869     {   
870         struct rusage buf;
871         /* QNX/Neutrino does return ENOSYS - so we just ignore it and
872          * add whatever is in buf.  In a chroot environment it might not
873          * work at all (i.e. because /proc/ is not accessible), so we better 
874          * ugnore all error codes and hope for the best
875          */
876         getrusage (RUSAGE_SELF, &buf );
877         add_randomness( &buf, sizeof buf, 1 );
878         memset( &buf, 0, sizeof buf );
879     }
880     #endif
881   #endif
882     /* time and clock are availabe on all systems - so
883      * we better do it just in case one of the above functions
884      * didn't work */
885     {   time_t x = time(NULL);
886         add_randomness( &x, sizeof(x), 1 );
887     }
888     {   clock_t x = clock();
889         add_randomness( &x, sizeof(x), 1 );
890     }
891 }
892
893
894 void
895 _gcry_fast_random_poll()
896 {
897   int err;
898
899   /* We have to make sure that the intialization is done because this
900      gatherer might be called before any other functions and it is not
901      sufficient to initialize it within do_fast_random_pool becuase we
902      want to use the mutex here. FIXME: Whe should initialize the mutex
903      using a global constructor independent from the initialization
904      of the pool. */
905   if (!is_initialized)
906     initialize ();
907   err = ath_mutex_lock (&pool_lock);
908   if (err)
909     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
910   pool_is_locked = 1;
911   do_fast_random_poll ();
912   pool_is_locked = 0;
913   err = ath_mutex_unlock (&pool_lock);
914   if (err)
915     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
916
917 }
918
919
920
921 static void
922 read_random_source( int requester, size_t length, int level )
923 {
924     static int (*fnc)(void (*)(const void*, size_t, int), int,
925                                                     size_t, int) = NULL;
926     if( !fnc ) {
927         if( !is_initialized )
928           initialize();
929         fnc = getfnc_gather_random ();
930         //fnc = ((GcryRandomSpec *) randoms_registered->spec)->add;
931         //fnc = _gcry_dynload_getfnc_gather_random();
932         if( !fnc ) {
933             faked_rng = 1;
934             fnc = gather_faked;
935         }
936         if( !requester && !length && !level )
937             return; /* init only */
938     }
939     if( (*fnc)( add_randomness, requester, length, level ) < 0 )
940         log_fatal("No way to gather entropy for the RNG\n");
941 }
942
943
944 static int
945 gather_faked( void (*add)(const void*, size_t, int), int requester,
946               size_t length, int level )
947 {
948     static int initialized=0;
949     size_t n;
950     char *buffer, *p;
951
952     if( !initialized ) {
953         log_info(_("WARNING: using insecure random number generator!!\n"));
954         /* we can't use tty_printf here - do we need this function at
955           all - does it really make sense or canit be viewed as a potential
956           security problem ? wk 17.11.99 */
957 #if 0
958         tty_printf(_("The random number generator is only a kludge to let\n"
959                    "it run - it is in no way a strong RNG!\n\n"
960                    "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
961 #endif
962         initialized=1;
963 #ifdef HAVE_RAND
964         srand( time(NULL)*getpid());
965 #else
966         srandom( time(NULL)*getpid());
967 #endif
968     }
969
970     p = buffer = gcry_xmalloc( length );
971     n = length;
972 #ifdef HAVE_RAND
973     while( n-- )
974         *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
975 #else
976     while( n-- )
977         *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
978 #endif
979     add_randomness( buffer, length, requester );
980     gcry_free(buffer);
981     return 0; /* okay */
982 }
983