2003-07-23 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 gcry_error_t
285 gcry_random_add_bytes (const void * buf, size_t buflen, int quality)
286 {
287   gcry_err_code_t err = GPG_ERR_NO_ERROR;
288
289   if (!buf || quality < -1 || quality > 100)
290     err = GPG_ERR_INV_ARG;
291   /* FIXME */
292 #if 0
293   if (!buflen)
294     return 0; /* Shortcut this dummy case. */
295   /* Before we actuall enbale this code, we need to lock the pool,
296      have a look at the quality and find a way to add them without
297      disturbing the real entropy (we have estimated). */
298   /*add_randomness( buf, buflen, 1 );*/
299 #endif
300   return err;
301 }   
302     
303
304 void *
305 gcry_random_bytes( size_t nbytes, enum gcry_random_level level )
306 {
307   if (!is_initialized)
308     initialize();
309   return get_random_bytes( nbytes, level, 0 );
310 }
311
312 void *
313 gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level )
314 {
315   if (!is_initialized)
316     initialize();
317   return get_random_bytes( nbytes, level, 1 );
318 }
319
320
321 /* Fill the buffer with LENGTH bytes of cryptographically strong
322    random bytes. level 0 is not very strong, 1 is strong enough for
323    most usage, 2 is good for key generation stuff but may be very
324    slow.  */
325 void
326 gcry_randomize (byte *buffer, size_t length, enum gcry_random_level level)
327 {
328   byte *p;
329   int err;
330
331   if (!is_initialized)
332     initialize ();
333
334   if( quick_test && level > 1 )
335     level = 1;
336   MASK_LEVEL(level);
337
338   err = ath_mutex_lock (&pool_lock);
339   if (err)
340     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
341   pool_is_locked = 1;
342   if (level == 1)
343     {
344       rndstats.getbytes1 += length;
345       rndstats.ngetbytes1++;
346     }
347   else if (level >= 2)
348     {
349       rndstats.getbytes2 += length;
350       rndstats.ngetbytes2++;
351     }
352
353   for (p = buffer; length > 0;)
354     {
355       size_t n = length > POOLSIZE? POOLSIZE : length;
356       read_pool (p, n, level);
357       length -= n;
358       p += n;
359     }
360
361   pool_is_locked = 0;
362   err = ath_mutex_unlock (&pool_lock);
363   if (err)
364     log_fatal ("failed to release the pool lock: %s\n", strerror (err));
365 }
366
367
368
369
370 /*
371    Mix the pool:
372
373    |........blocks*20byte........|20byte|..44byte..|
374    <..44byte..>           <20byte> 
375         |                    |
376         |                    +------+
377         +---------------------------|----------+
378                                     v          v
379    |........blocks*20byte........|20byte|..44byte..|
380                                  <.....64bytes.....>   
381                                          |
382       +----------------------------------+
383      Hash
384       v
385    |.............................|20byte|..44byte..|
386    <20byte><20byte><..44byte..>
387       |                |
388       |                +---------------------+
389       +-----------------------------+        |
390                                     v        v
391    |.............................|20byte|..44byte..|
392                                  <.....64byte......>
393                                         |
394               +-------------------------+
395              Hash
396               v
397    |.............................|20byte|..44byte..|
398    <20byte><20byte><..44byte..>
399
400    and so on until we did this for all blocks. 
401
402  */
403 static void
404 mix_pool(byte *pool)
405 {
406     char *hashbuf = pool + POOLSIZE;
407     char *p, *pend;
408     int i, n;
409     RMD160_CONTEXT md;
410
411     assert (pool_is_locked);
412     _gcry_rmd160_init( &md );
413 #if DIGESTLEN != 20
414 #error must have a digest length of 20 for ripe-md-160
415 #endif
416     /* loop over the pool */
417     pend = pool + POOLSIZE;
418     memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
419     memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
420     _gcry_rmd160_mixblock( &md, hashbuf);
421     memcpy(pool, hashbuf, 20 );
422     if (failsafe_digest_valid && (char *)pool == rndpool)
423       {
424         for (i=0; i < 20; i++)
425           pool[i] ^= failsafe_digest[i];
426       }
427
428     p = pool;
429     for( n=1; n < POOLBLOCKS; n++ ) {
430         memcpy(hashbuf, p, DIGESTLEN );
431
432         p += DIGESTLEN;
433         if( p+DIGESTLEN+BLOCKLEN < pend )
434             memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
435         else {
436             char *pp = p+DIGESTLEN;
437             for(i=DIGESTLEN; i < BLOCKLEN; i++ ) {
438                 if( pp >= pend )
439                     pp = pool;
440                 hashbuf[i] = *pp++;
441             }
442         }
443
444         _gcry_rmd160_mixblock( &md, hashbuf);
445         memcpy(p, hashbuf, 20 );
446     }
447     /* Hmmm: our hash implementation does only leave small parts (64
448        bytes) of the pool on the stack, so I thnik it ios okay not to
449        require secure memory here.  Before we use this pool, it gets
450        copied to the help buffer anyway. */
451     if ( (char*)pool == rndpool)
452       {
453         _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE);
454         failsafe_digest_valid = 1;
455       }
456     _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */
457 }
458
459 void
460 _gcry_set_random_seed_file( const char *name )
461 {
462     if( seed_file_name )
463         BUG();
464     seed_file_name = gcry_xstrdup( name );
465 }
466
467 /****************
468  * Read in a seed form the random_seed file
469  * and return true if this was successful
470  */
471 static int
472 read_seed_file()
473 {
474     int fd;
475     struct stat sb;
476     unsigned char buffer[POOLSIZE];
477     int n;
478
479     assert (pool_is_locked);
480     if( !seed_file_name )
481         return 0;
482
483 #ifdef HAVE_DOSISH_SYSTEM
484     fd = open( seed_file_name, O_RDONLY | O_BINARY );
485 #else
486     fd = open( seed_file_name, O_RDONLY );
487 #endif
488     if( fd == -1 && errno == ENOENT) {
489         allow_seed_file_update = 1;
490         return 0;
491     }
492
493     if( fd == -1 ) {
494         log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
495         return 0;
496     }
497     if( fstat( fd, &sb ) ) {
498         log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
499         close(fd);
500         return 0;
501     }
502     if( !S_ISREG(sb.st_mode) ) {
503         log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
504         close(fd);
505         return 0;
506     }
507     if( !sb.st_size ) {
508         log_info(_("note: random_seed file is empty\n") );
509         close(fd);
510         allow_seed_file_update = 1;
511         return 0;
512     }
513     if( sb.st_size != POOLSIZE ) {
514         log_info(_("warning: invalid size of random_seed file - not used\n") );
515         close(fd);
516         return 0;
517     }
518     do {
519         n = read( fd, buffer, POOLSIZE );
520     } while( n == -1 && errno == EINTR );
521     if( n != POOLSIZE ) {
522         log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
523         close(fd);
524         return 0;
525     }
526
527     close(fd);
528
529     add_randomness( buffer, POOLSIZE, 0 );
530     /* add some minor entropy to the pool now (this will also force a mixing) */
531     {   pid_t x = getpid();
532         add_randomness( &x, sizeof(x), 0 );
533     }
534     {   time_t x = time(NULL);
535         add_randomness( &x, sizeof(x), 0 );
536     }
537     {   clock_t x = clock();
538         add_randomness( &x, sizeof(x), 0 );
539     }
540     /* And read a few bytes from our entropy source.  By using
541      * a level of 0 this will not block and might not return anything
542      * with some entropy drivers, however the rndlinux driver will use
543      * /dev/urandom and return some stuff - Do not read to much as we
544      * want to be friendly to the scare system entropy resource. */
545     read_random_source( 0, 16, 0 );
546
547     allow_seed_file_update = 1;
548     return 1;
549 }
550
551 void
552 _gcry_update_random_seed_file()
553 {
554   ulong *sp, *dp;
555   int fd, i;
556   int err;
557   
558   if ( !seed_file_name || !is_initialized || !pool_filled )
559     return;
560   if ( !allow_seed_file_update )
561     {
562       log_info(_("note: random_seed file not updated\n"));
563       return;
564     }
565
566   err = ath_mutex_lock (&pool_lock);
567   if (err)
568     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
569   pool_is_locked = 1;
570
571     /* copy the entropy pool to a scratch pool and mix both of them */
572   for (i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
573        i < POOLWORDS; i++, dp++, sp++ ) 
574     {
575       *dp = *sp + ADD_VALUE;
576     }
577   mix_pool(rndpool); rndstats.mixrnd++;
578   mix_pool(keypool); rndstats.mixkey++;
579
580 #ifdef HAVE_DOSISH_SYSTEM
581   fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
582              S_IRUSR|S_IWUSR );
583 #else
584   fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
585 #endif
586
587   if (fd == -1 )
588     log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
589   else 
590     {
591       do {
592         i = write (fd, keypool, POOLSIZE );
593       } while( i == -1 && errno == EINTR );
594     if (i != POOLSIZE) 
595       log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) );
596     if (close(fd))
597       log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) );
598     }
599
600   pool_is_locked = 0;
601   err = ath_mutex_unlock (&pool_lock);
602   if (err)
603     log_fatal ("failed to release the pool lock: %s\n", strerror (err));
604 }
605
606
607 static void
608 read_pool( byte *buffer, size_t length, int level )
609 {
610     int i;
611     ulong *sp, *dp;
612
613     assert (pool_is_locked);
614     if( length > POOLSIZE ) {
615         log_bug("too many random bits requested\n");
616     }
617
618     if( !pool_filled ) {
619         if( read_seed_file() )
620             pool_filled = 1;
621     }
622
623     /* For level 2 quality (key generation) we always make
624      * sure that the pool has been seeded enough initially */
625     if( level == 2 && !did_initial_extra_seeding ) {
626         size_t needed;
627
628         pool_balance = 0;
629         needed = length - pool_balance;
630         if( needed < POOLSIZE/2 )
631             needed = POOLSIZE/2;
632         else if( needed > POOLSIZE )
633             BUG();
634         read_random_source( 3, needed, 2 );
635         pool_balance += needed;
636         did_initial_extra_seeding=1;
637     }
638
639     /* for level 2 make sure that there is enough random in the pool */
640     if( level == 2 && pool_balance < length ) {
641         size_t needed;
642
643         if( pool_balance < 0 )
644             pool_balance = 0;
645         needed = length - pool_balance;
646         if( needed > POOLSIZE )
647             BUG();
648         read_random_source( 3, needed, 2 );
649         pool_balance += needed;
650     }
651
652     /* make sure the pool is filled */
653     while( !pool_filled )
654         random_poll();
655
656     /* always do a fast random poll - we have to use the unlocked version*/
657     do_fast_random_poll();
658
659     if( !level ) { /* no need for cryptographic strong random */
660         /* create a new pool */
661         for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
662                                     i < POOLWORDS; i++, dp++, sp++ )
663             *dp = *sp + ADD_VALUE;
664         /* must mix both pools */
665         mix_pool(rndpool); rndstats.mixrnd++;
666         mix_pool(keypool); rndstats.mixkey++;
667         memcpy( buffer, keypool, length );
668     }
669     else {
670         /* mix the pool (if add_randomness() didn't it) */
671         if( !just_mixed ) {
672             mix_pool(rndpool);
673             rndstats.mixrnd++;
674         }
675         /* create a new pool */
676         for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
677                                     i < POOLWORDS; i++, dp++, sp++ )
678             *dp = *sp + ADD_VALUE;
679         /* and mix both pools */
680         mix_pool(rndpool); rndstats.mixrnd++;
681         mix_pool(keypool); rndstats.mixkey++;
682         /* read the required data
683          * we use a readpoiter to read from a different postion each
684          * time */
685         while( length-- ) {
686             *buffer++ = keypool[pool_readpos++];
687             if( pool_readpos >= POOLSIZE )
688                 pool_readpos = 0;
689             pool_balance--;
690         }
691         if( pool_balance < 0 )
692             pool_balance = 0;
693         /* and clear the keypool */
694         memset( keypool, 0, POOLSIZE );
695     }
696 }
697
698
699 /****************
700  * Add LENGTH bytes of randomness from buffer to the pool.
701  * source may be used to specify the randomness source.
702  * Source is:
703  *      0 - used ony for initialization
704  *      1 - fast random poll function
705  *      2 - normal poll function
706  *      3 - used when level 2 random quality has been requested
707  *          to do an extra pool seed.
708  */
709 static void
710 add_randomness( const void *buffer, size_t length, int source )
711 {
712     const byte *p = buffer;
713
714     assert (pool_is_locked);
715     if( !is_initialized )
716         initialize();
717     rndstats.addbytes += length;
718     rndstats.naddbytes++;
719     while( length-- ) {
720         rndpool[pool_writepos++] ^= *p++;
721         if( pool_writepos >= POOLSIZE ) {
722             if( source > 1 )
723                 pool_filled = 1;
724             pool_writepos = 0;
725             mix_pool(rndpool); rndstats.mixrnd++;
726             just_mixed = !length;
727         }
728     }
729 }
730
731
732
733 static void
734 random_poll()
735 {
736     rndstats.slowpolls++;
737     read_random_source( 2, POOLSIZE/5, 1 );
738 }
739
740 static int (*
741 getfnc_gather_random (void))(void (*)(const void*, size_t, int), int,
742                              size_t, int)
743 {
744   int rndlinux_gather_random (void (*add) (const void *, size_t, int),
745                               int requester, size_t length, int level);
746   int rndunix_gather_random (void (*add) (const void *, size_t, int),
747                              int requester, size_t length, int level);
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   int rndw32_gather_random (void (*add) (const void *, size_t, int),
752                             int requester, size_t length, int level);
753
754   static int (*fnc)(void (*)(const void*, size_t, int), int, size_t, int);
755   
756   if (fnc)
757     return fnc;
758
759 #if USE_RNDLINUX
760   if ( !access (NAME_OF_DEV_RANDOM, R_OK)
761        && !access (NAME_OF_DEV_RANDOM, R_OK))
762     {
763       fnc = rndlinux_gather_random;
764       return fnc;
765     }
766 #endif
767
768 #if USE_RNDEGD
769   if ( rndegd_connect_socket (1) != -1 )
770     {
771       fnc = rndegd_gather_random;
772       return fnc;
773     }
774 #endif
775
776 #if USE_RNDUNIX
777   fnc = rndunix_gather_random;
778   return fnc;
779 #endif
780
781   log_fatal (_("no entropy gathering module detected\n"));
782
783   return NULL;
784 }
785
786 static void (*
787 getfnc_fast_random_poll (void))( void (*)(const void*, size_t, int), int)
788 {
789 #if USE_RNDW32
790   int rndw32_gather_random_fast (void (*add) (const void *, size_t, int),
791                                  int requester);
792   return rndw32_gather_random_fast;
793 #endif
794   return NULL;
795 }
796
797
798 static void
799 do_fast_random_poll ()
800 {
801     static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
802     static int initialized = 0;
803
804     assert (pool_is_locked);
805     rndstats.fastpolls++;
806     if( !initialized ) {
807         if( !is_initialized )
808             initialize();
809         initialized = 1;
810         fnc = getfnc_fast_random_poll ();
811     }
812     if( fnc ) {
813         (*fnc)( add_randomness, 1 );
814         return;
815     }
816
817     /* fall back to the generic function */
818 #if HAVE_GETHRTIME
819     {   hrtime_t tv;
820         tv = gethrtime();
821         add_randomness( &tv, sizeof(tv), 1 );
822     }
823 #elif HAVE_GETTIMEOFDAY
824     {   struct timeval tv;
825         if( gettimeofday( &tv, NULL ) )
826             BUG();
827         add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
828         add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
829     }
830 #elif HAVE_CLOCK_GETTIME
831     {   struct timespec tv;
832         if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
833             BUG();
834         add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
835         add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
836     }
837 #else /* use times */
838 #ifndef HAVE_DOSISH_SYSTEM
839     {   struct tms buf;
840         times( &buf );
841         add_randomness( &buf, sizeof buf, 1 );
842     }
843 #endif
844 #endif
845 #ifdef HAVE_GETRUSAGE
846 #ifndef RUSAGE_SELF
847 #ifdef __GCC__
848         #warning There is no RUSAGE_SELF on this system
849 #endif
850 #else
851     {   
852         struct rusage buf;
853         /* QNX/Neutrino does return ENOSYS - so we just ignore it and
854          * add whatever is in buf.  In a chroot environment it might not
855          * work at all (i.e. because /proc/ is not accessible), so we better 
856          * ugnore all error codes and hope for the best
857          */
858         getrusage (RUSAGE_SELF, &buf );
859         add_randomness( &buf, sizeof buf, 1 );
860         memset( &buf, 0, sizeof buf );
861     }
862 #endif
863 #endif
864     /* time and clock are availabe on all systems - so
865      * we better do it just in case one of the above functions
866      * didn't work */
867     {   time_t x = time(NULL);
868         add_randomness( &x, sizeof(x), 1 );
869     }
870     {   clock_t x = clock();
871         add_randomness( &x, sizeof(x), 1 );
872     }
873 }
874
875
876 void
877 _gcry_fast_random_poll()
878 {
879   int err;
880
881   /* We have to make sure that the intialization is done because this
882      gatherer might be called before any other functions and it is not
883      sufficient to initialize it within do_fast_random_pool becuase we
884      want to use the mutex here. FIXME: Whe should initialize the mutex
885      using a global constructor independent from the initialization
886      of the pool. */
887   if (!is_initialized)
888     initialize ();
889   err = ath_mutex_lock (&pool_lock);
890   if (err)
891     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
892   pool_is_locked = 1;
893   do_fast_random_poll ();
894   pool_is_locked = 0;
895   err = ath_mutex_unlock (&pool_lock);
896   if (err)
897     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
898
899 }
900
901
902
903 static void
904 read_random_source( int requester, size_t length, int level )
905 {
906     static int (*fnc)(void (*)(const void*, size_t, int), int,
907                                                     size_t, int) = NULL;
908     if( !fnc ) {
909         if( !is_initialized )
910           initialize();
911         fnc = getfnc_gather_random ();
912         //fnc = ((GcryRandomSpec *) randoms_registered->spec)->add;
913         //fnc = _gcry_dynload_getfnc_gather_random();
914         if( !fnc ) {
915             faked_rng = 1;
916             fnc = gather_faked;
917         }
918         if( !requester && !length && !level )
919             return; /* init only */
920     }
921     if( (*fnc)( add_randomness, requester, length, level ) < 0 )
922         log_fatal("No way to gather entropy for the RNG\n");
923 }
924
925
926 static int
927 gather_faked( void (*add)(const void*, size_t, int), int requester,
928               size_t length, int level )
929 {
930     static int initialized=0;
931     size_t n;
932     char *buffer, *p;
933
934     if( !initialized ) {
935         log_info(_("WARNING: using insecure random number generator!!\n"));
936         /* we can't use tty_printf here - do we need this function at
937           all - does it really make sense or canit be viewed as a potential
938           security problem ? wk 17.11.99 */
939 #if 0
940         tty_printf(_("The random number generator is only a kludge to let\n"
941                    "it run - it is in no way a strong RNG!\n\n"
942                    "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
943 #endif
944         initialized=1;
945 #ifdef HAVE_RAND
946         srand( time(NULL)*getpid());
947 #else
948         srandom( time(NULL)*getpid());
949 #endif
950     }
951
952     p = buffer = gcry_xmalloc( length );
953     n = length;
954 #ifdef HAVE_RAND
955     while( n-- )
956         *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
957 #else
958     while( n-- )
959         *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
960 #endif
961     add_randomness( buffer, length, requester );
962     gcry_free(buffer);
963     return 0; /* okay */
964 }
965