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