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