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