2003-02-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
137 /* Note, we assume that this function is used before any concurrent
138    access happens */
139 static void
140 initialize(void)
141 {
142   int err;
143
144   err = ath_mutex_init (&pool_lock);
145   if (err)
146     log_fatal ("failed to create the pool lock: %s\n", strerror (err) );
147     
148   /* The data buffer is allocated somewhat larger, so that we can use
149     this extra space (which is allocated in secure memory) as a
150     temporary hash buffer */
151   rndpool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
152                          : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
153   keypool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
154                          : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
155   is_initialized = 1;
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
736
737 static void
738 do_fast_random_poll ()
739 {
740     static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
741     static int initialized = 0;
742
743     assert (pool_is_locked);
744     rndstats.fastpolls++;
745     if( !initialized ) {
746         if( !is_initialized )
747             initialize();
748         initialized = 1;
749         fnc = _gcry_dynload_getfnc_fast_random_poll();
750     }
751     if( fnc ) {
752         (*fnc)( add_randomness, 1 );
753         return;
754     }
755
756     /* fall back to the generic function */
757   #if HAVE_GETHRTIME
758     {   hrtime_t tv;
759         tv = gethrtime();
760         add_randomness( &tv, sizeof(tv), 1 );
761     }
762   #elif HAVE_GETTIMEOFDAY
763     {   struct timeval tv;
764         if( gettimeofday( &tv, NULL ) )
765             BUG();
766         add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
767         add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
768     }
769   #elif HAVE_CLOCK_GETTIME
770     {   struct timespec tv;
771         if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
772             BUG();
773         add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
774         add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
775     }
776   #else /* use times */
777     #ifndef HAVE_DOSISH_SYSTEM
778     {   struct tms buf;
779         times( &buf );
780         add_randomness( &buf, sizeof buf, 1 );
781     }
782     #endif
783   #endif
784   #ifdef HAVE_GETRUSAGE
785     #ifndef RUSAGE_SELF
786       #ifdef __GCC__
787         #warning There is no RUSAGE_SELF on this system
788       #endif
789     #else
790     {   
791         struct rusage buf;
792         /* QNX/Neutrino does return ENOSYS - so we just ignore it and
793          * add whatever is in buf.  In a chroot environment it might not
794          * work at all (i.e. because /proc/ is not accessible), so we better 
795          * ugnore all error codes and hope for the best
796          */
797         getrusage (RUSAGE_SELF, &buf );
798         add_randomness( &buf, sizeof buf, 1 );
799         memset( &buf, 0, sizeof buf );
800     }
801     #endif
802   #endif
803     /* time and clock are availabe on all systems - so
804      * we better do it just in case one of the above functions
805      * didn't work */
806     {   time_t x = time(NULL);
807         add_randomness( &x, sizeof(x), 1 );
808     }
809     {   clock_t x = clock();
810         add_randomness( &x, sizeof(x), 1 );
811     }
812 }
813
814
815 void
816 _gcry_fast_random_poll()
817 {
818   int err;
819
820   /* We have to make sure that the intialization is done because this
821      gatherer might be called before any other functions and it is not
822      sufficient to initialize it within do_fast_random_pool becuase we
823      want to use the mutex here. FIXME: Whe should initialize the mutex
824      using a global constructor independent from the initialization
825      of the pool. */
826   if (!is_initialized)
827     initialize ();
828   err = ath_mutex_lock (&pool_lock);
829   if (err)
830     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
831   pool_is_locked = 1;
832   do_fast_random_poll ();
833   pool_is_locked = 0;
834   err = ath_mutex_unlock (&pool_lock);
835   if (err)
836     log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
837
838 }
839
840
841
842 static void
843 read_random_source( int requester, size_t length, int level )
844 {
845     static int (*fnc)(void (*)(const void*, size_t, int), int,
846                                                     size_t, int) = NULL;
847     if( !fnc ) {
848         if( !is_initialized )
849             initialize();
850         fnc = _gcry_dynload_getfnc_gather_random();
851         if( !fnc ) {
852             faked_rng = 1;
853             fnc = gather_faked;
854         }
855         if( !requester && !length && !level )
856             return; /* init only */
857     }
858     if( (*fnc)( add_randomness, requester, length, level ) < 0 )
859         log_fatal("No way to gather entropy for the RNG\n");
860 }
861
862
863 static int
864 gather_faked( void (*add)(const void*, size_t, int), int requester,
865               size_t length, int level )
866 {
867     static int initialized=0;
868     size_t n;
869     char *buffer, *p;
870
871     if( !initialized ) {
872         log_info(_("WARNING: using insecure random number generator!!\n"));
873         /* we can't use tty_printf here - do we need this function at
874           all - does it really make sense or canit be viewed as a potential
875           security problem ? wk 17.11.99 */
876 #if 0
877         tty_printf(_("The random number generator is only a kludge to let\n"
878                    "it run - it is in no way a strong RNG!\n\n"
879                    "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
880 #endif
881         initialized=1;
882 #ifdef HAVE_RAND
883         srand( time(NULL)*getpid());
884 #else
885         srandom( time(NULL)*getpid());
886 #endif
887     }
888
889     p = buffer = gcry_xmalloc( length );
890     n = length;
891 #ifdef HAVE_RAND
892     while( n-- )
893         *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
894 #else
895     while( n-- )
896         *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
897 #endif
898     add_randomness( buffer, length, requester );
899     gcry_free(buffer);
900     return 0; /* okay */
901 }
902