summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/cipher/random.c
Unidiff
Diffstat (limited to 'pwmanager/libcrypt/cipher/random.c') (more/less context) (show whitespace changes)
-rw-r--r--pwmanager/libcrypt/cipher/random.c1134
1 files changed, 1134 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/random.c b/pwmanager/libcrypt/cipher/random.c
new file mode 100644
index 0000000..e0d04a4
--- a/dev/null
+++ b/pwmanager/libcrypt/cipher/random.c
@@ -0,0 +1,1134 @@
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 in
23 * Peter Gutmann's paper: "Software Generation of Practically Strong
24 * Random Numbers". See also chapter 6 in his book "Cryptographic
25 * Security Architecture", New York, 2004, ISBN 0-387-95387-6.
26 */
27
28
29#include <config.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <assert.h>
33#include <errno.h>
34#include <string.h>
35#include <sys/time.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <unistd.h>
39#include <fcntl.h>
40#include <time.h>
41 #ifdefHAVE_GETHRTIME
42#include <sys/times.h>
43#endif
44#ifdef HAVE_GETTIMEOFDAY
45#include <sys/times.h>
46#endif
47#ifdef HAVE_GETRUSAGE
48#include <sys/resource.h>
49#endif
50#ifdef __MINGW32__
51#include <process.h>
52#endif
53#include "g10lib.h"
54#include "rmd.h"
55#include "random.h"
56#include "rand-internal.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
88static int is_initialized;
89#define MASK_LEVEL(a) do { (a) &= 3; } while(0)
90 static char *rndpool;/* allocated size is POOLSIZE+BLOCKLEN */
91 static char *keypool;/* allocated size is POOLSIZE+BLOCKLEN */
92static size_t pool_readpos;
93static size_t pool_writepos;
94static int pool_filled;
95static int pool_balance;
96static int just_mixed;
97static int did_initial_extra_seeding;
98static char *seed_file_name;
99static int allow_seed_file_update;
100
101static int secure_alloc;
102static int quick_test;
103static int faked_rng;
104
105static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER;
106static int pool_is_locked; /* only used for assertion */
107
108static ath_mutex_t nonce_buffer_lock = ATH_MUTEX_INITIALIZER;
109
110static byte *get_random_bytes( size_t nbytes, int level, int secure );
111static void read_pool( byte *buffer, size_t length, int level );
112static void add_randomness( const void *buffer, size_t length, int source );
113static void random_poll(void);
114static void do_fast_random_poll (void);
115static void read_random_source( int requester, size_t length, int level);
116static int gather_faked( void (*add)(const void*, size_t, int), int requester,
117 size_t length, int level );
118
119static struct {
120 ulong mixrnd;
121 ulong mixkey;
122 ulong slowpolls;
123 ulong fastpolls;
124 ulong getbytes1;
125 ulong ngetbytes1;
126 ulong getbytes2;
127 ulong ngetbytes2;
128 ulong addbytes;
129 ulong naddbytes;
130} rndstats;
131
132static void (*progress_cb) (void *,const char*,int,int, int );
133static void *progress_cb_data;
134
135/* Note, we assume that this function is used before any concurrent
136 access happens. */
137static void
138initialize(void)
139{
140 int err;
141
142 err = ath_mutex_init (&pool_lock);
143 if (err)
144 log_fatal ("failed to create the pool lock: %s\n", strerror (err) );
145
146 err = ath_mutex_init (&nonce_buffer_lock);
147 if (err)
148 log_fatal ("failed to create the nonce buffer lock: %s\n",
149 strerror (err) );
150
151 /* The data buffer is allocated somewhat larger, so that we can use
152 this extra space (which is allocated in secure memory) as a
153 temporary hash buffer */
154 rndpool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
155 : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
156 keypool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
157 : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
158 is_initialized = 1;
159
160}
161
162
163/* Used to register a progress callback. */
164void
165_gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
166 void *cb_data )
167{
168 progress_cb = cb;
169 progress_cb_data = cb_data;
170}
171
172
173/* This progress function is currently used by the random modules to give hint
174 on how much more entropy is required. */
175void
176_gcry_random_progress (const char *what, int printchar, int current, int total)
177{
178 if (progress_cb)
179 progress_cb (progress_cb_data, what, printchar, current, total);
180}
181
182
183/* Initialize this random subsystem. This function merely calls the
184 initialize and does not do anything more. Doing this is not really
185 required but when running in a threaded environment we might get a
186 race condition otherwise. */
187void
188_gcry_random_initialize ()
189{
190 if (!is_initialized)
191 initialize ();
192}
193
194void
195_gcry_random_dump_stats()
196{
197 log_info (
198 "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
199 " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n",
200 POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
201 rndstats.naddbytes, rndstats.addbytes,
202 rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
203 rndstats.ngetbytes2, rndstats.getbytes2 );
204}
205
206void
207_gcry_secure_random_alloc()
208{
209 secure_alloc = 1;
210}
211
212
213int
214_gcry_quick_random_gen( int onoff )
215{
216 int last;
217
218 /* No need to lock it here because we are only initializing. A
219 prerequisite of the entire code is that it has already been
220 initialized before any possible concurrent access */
221 read_random_source(0,0,0); /* init */
222 last = quick_test;
223 if( onoff != -1 )
224 quick_test = onoff;
225 return faked_rng? 1 : last;
226}
227
228int
229_gcry_random_is_faked()
230{
231 if( !is_initialized )
232 initialize();
233 return (faked_rng || quick_test);
234}
235
236/*
237 * Return a pointer to a randomized buffer of LEVEL and NBYTES length.
238 * Caller must free the buffer.
239 */
240static byte *
241get_random_bytes ( size_t nbytes, int level, int secure)
242{
243 byte *buf, *p;
244 int err;
245
246 /* First a hack toavoid the strong random using our regression test suite. */
247 if (quick_test && level > 1)
248 level = 1;
249
250 /* Make sure the requested level is in range. */
251 MASK_LEVEL(level);
252
253 /* Lock the pool. */
254 err = ath_mutex_lock (&pool_lock);
255 if (err)
256 log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
257 pool_is_locked = 1;
258
259 /* Keep some statistics. */
260 if (level >= 2)
261 {
262 rndstats.getbytes2 += nbytes;
263 rndstats.ngetbytes2++;
264 }
265 else
266 {
267 rndstats.getbytes1 += nbytes;
268 rndstats.ngetbytes1++;
269 }
270
271 /* Allocate the return buffer. */
272 buf = secure && secure_alloc ? gcry_xmalloc_secure( nbytes )
273 : gcry_xmalloc( nbytes );
274
275 /* Fill that buffer with random. */
276 for (p = buf; nbytes > 0; )
277 {
278 size_t n;
279
280 n = nbytes > POOLSIZE? POOLSIZE : nbytes;
281 read_pool( p, n, level );
282 nbytes -= n;
283 p += n;
284 }
285
286 /* Release the pool lock. */
287 pool_is_locked = 0;
288 err = ath_mutex_unlock (&pool_lock);
289 if (err)
290 log_fatal ("failed to release the pool lock: %s\n", strerror (err));
291
292 /* Return the buffer. */
293 return buf;
294}
295
296
297/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
298 should be in the range of 0..100 to indicate the goodness of the
299 entropy added, or -1 for goodness not known.
300
301 Note, that this function currently does nothing.
302*/
303gcry_error_t
304gcry_random_add_bytes (const void * buf, size_t buflen, int quality)
305{
306 gcry_err_code_t err = GPG_ERR_NO_ERROR;
307
308 if (!buf || quality < -1 || quality > 100)
309 err = GPG_ERR_INV_ARG;
310 if (!buflen)
311 return 0; /* Shortcut this dummy case. */
312#if 0
313 /* Before we actuall enable this code, we need to lock the pool,
314 have a look at the quality and find a way to add them without
315 disturbing the real entropy (we have estimated). */
316 /*add_randomness( buf, buflen, 1 );*/
317#endif
318 return err;
319}
320
321/* The public function to return random data of the quality LEVEL. */
322void *
323gcry_random_bytes( size_t nbytes, enum gcry_random_level level )
324{
325 if (!is_initialized)
326 initialize();
327 return get_random_bytes( nbytes, level, 0 );
328}
329
330/* The public function to return random data of the quality LEVEL;
331 this version of the function retrun the random a buffer allocated
332 in secure memory. */
333void *
334gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level )
335{
336 if (!is_initialized)
337 initialize();
338 return get_random_bytes( nbytes, level, 1 );
339}
340
341
342/* Public function to fill the buffer with LENGTH bytes of
343 cryptographically strong random bytes. level 0 is not very strong,
344 1 is strong enough for most usage, 2 is good for key generation
345 stuff but may be very slow. */
346void
347gcry_randomize (byte *buffer, size_t length, enum gcry_random_level level)
348{
349 byte *p;
350 int err;
351
352 /* Make sure we are initialized. */
353 if (!is_initialized)
354 initialize ();
355
356 /* Handle our hack used for regression tests of Libgcrypt. */
357 if( quick_test && level > 1 )
358 level = 1;
359
360 /* Make sure the level is okay. */
361 MASK_LEVEL(level);
362
363 /* Acquire the pool lock. */
364 err = ath_mutex_lock (&pool_lock);
365 if (err)
366 log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
367 pool_is_locked = 1;
368
369 /* Update the statistics. */
370 if (level >= 2)
371 {
372 rndstats.getbytes2 += length;
373 rndstats.ngetbytes2++;
374 }
375 else
376 {
377 rndstats.getbytes1 += length;
378 rndstats.ngetbytes1++;
379 }
380
381 /* Read the random into the provided buffer. */
382 for (p = buffer; length > 0;)
383 {
384 size_t n;
385
386 n = length > POOLSIZE? POOLSIZE : length;
387 read_pool (p, n, level);
388 length -= n;
389 p += n;
390 }
391
392 /* Release the pool lock. */
393 pool_is_locked = 0;
394 err = ath_mutex_unlock (&pool_lock);
395 if (err)
396 log_fatal ("failed to release the pool lock: %s\n", strerror (err));
397
398}
399
400
401
402
403/*
404 Mix the pool:
405
406 |........blocks*20byte........|20byte|..44byte..|
407 <..44byte..> <20byte>
408 | |
409 | +------+
410 +---------------------------|----------+
411 v v
412 |........blocks*20byte........|20byte|..44byte..|
413 <.....64bytes.....>
414 |
415 +----------------------------------+
416 Hash
417 v
418 |.............................|20byte|..44byte..|
419 <20byte><20byte><..44byte..>
420 | |
421 | +---------------------+
422 +-----------------------------+ |
423 v v
424 |.............................|20byte|..44byte..|
425 <.....64byte......>
426 |
427 +-------------------------+
428 Hash
429 v
430 |.............................|20byte|..44byte..|
431 <20byte><20byte><..44byte..>
432
433 and so on until we did this for all blocks.
434
435 To better protect against implementation errors in this code, we
436 xor a digest of the entire pool into the pool before mixing.
437
438 Note, that this function muts only be called with a locked pool.
439 */
440static void
441mix_pool(byte *pool)
442{
443 static unsigned char failsafe_digest[DIGESTLEN];
444 static int failsafe_digest_valid;
445
446 char *hashbuf = pool + POOLSIZE;
447 char *p, *pend;
448 int i, n;
449 RMD160_CONTEXT md;
450
451#if DIGESTLEN != 20
452#error must have a digest length of 20 for ripe-md-160
453#endif
454
455 assert (pool_is_locked);
456 _gcry_rmd160_init( &md );
457
458 /* loop over the pool */
459 pend = pool + POOLSIZE;
460 memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
461 memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
462 _gcry_rmd160_mixblock( &md, hashbuf);
463 memcpy(pool, hashbuf, 20 );
464
465 if (failsafe_digest_valid && (char *)pool == rndpool)
466 {
467 for (i=0; i < 20; i++)
468 pool[i] ^= failsafe_digest[i];
469 }
470
471 p = pool;
472 for (n=1; n < POOLBLOCKS; n++)
473 {
474 memcpy (hashbuf, p, DIGESTLEN);
475
476 p += DIGESTLEN;
477 if (p+DIGESTLEN+BLOCKLEN < pend)
478 memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
479 else
480 {
481 char *pp = p + DIGESTLEN;
482
483 for (i=DIGESTLEN; i < BLOCKLEN; i++ )
484 {
485 if ( pp >= pend )
486 pp = pool;
487 hashbuf[i] = *pp++;
488 }
489 }
490
491 _gcry_rmd160_mixblock( &md, hashbuf);
492 memcpy(p, hashbuf, 20 );
493 }
494
495 /* Our hash implementation does only leave small parts (64 bytes)
496 of the pool on the stack, so it is okay not to require secure
497 memory here. Before we use this pool, it will be copied to the
498 help buffer anyway. */
499 if ( (char*)pool == rndpool)
500 {
501 _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE);
502 failsafe_digest_valid = 1;
503 }
504
505 _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */
506}
507
508
509void
510_gcry_set_random_seed_file( const char *name )
511{
512 if (seed_file_name)
513 BUG ();
514 seed_file_name = gcry_xstrdup (name);
515}
516
517
518/*
519 Read in a seed form the random_seed file
520 and return true if this was successful.
521 */
522static int
523read_seed_file (void)
524{
525 int fd;
526 struct stat sb;
527 unsigned char buffer[POOLSIZE];
528 int n;
529
530 assert (pool_is_locked);
531
532 if (!seed_file_name)
533 return 0;
534
535#ifdef HAVE_DOSISH_SYSTEM
536 fd = open( seed_file_name, O_RDONLY | O_BINARY );
537#else
538 fd = open( seed_file_name, O_RDONLY );
539#endif
540 if( fd == -1 && errno == ENOENT)
541 {
542 allow_seed_file_update = 1;
543 return 0;
544 }
545
546 if (fd == -1 )
547 {
548 log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
549 return 0;
550 }
551 if (fstat( fd, &sb ) )
552 {
553 log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
554 close(fd);
555 return 0;
556 }
557 if (!S_ISREG(sb.st_mode) )
558 {
559 log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
560 close(fd);
561 return 0;
562 }
563 if (!sb.st_size )
564 {
565 log_info(_("note: random_seed file is empty\n") );
566 close(fd);
567 allow_seed_file_update = 1;
568 return 0;
569 }
570 if (sb.st_size != POOLSIZE )
571 {
572 log_info(_("warning: invalid size of random_seed file - not used\n") );
573 close(fd);
574 return 0;
575 }
576
577 do
578 {
579 n = read( fd, buffer, POOLSIZE );
580 }
581 while (n == -1 && errno == EINTR );
582
583 if (n != POOLSIZE)
584 {
585 log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
586 close(fd);/*NOTREACHED*/
587 return 0;
588 }
589
590 close(fd);
591
592 add_randomness( buffer, POOLSIZE, 0 );
593 /* add some minor entropy to the pool now (this will also force a mixing) */
594 {
595 pid_t x = getpid();
596 add_randomness( &x, sizeof(x), 0 );
597 }
598 {
599 time_t x = time(NULL);
600 add_randomness( &x, sizeof(x), 0 );
601 }
602 {
603 clock_t x = clock();
604 add_randomness( &x, sizeof(x), 0 );
605 }
606
607 /* And read a few bytes from our entropy source. By using a level
608 * of 0 this will not block and might not return anything with some
609 * entropy drivers, however the rndlinux driver will use
610 * /dev/urandom and return some stuff - Do not read to much as we
611 * want to be friendly to the scare system entropy resource. */
612 read_random_source( 0, 16, 0 );
613
614 allow_seed_file_update = 1;
615 return 1;
616}
617
618
619void
620_gcry_update_random_seed_file()
621{
622 ulong *sp, *dp;
623 int fd, i;
624 int err;
625
626 if ( !seed_file_name || !is_initialized || !pool_filled )
627 return;
628 if ( !allow_seed_file_update )
629 {
630 log_info(_("note: random_seed file not updated\n"));
631 return;
632 }
633
634 err = ath_mutex_lock (&pool_lock);
635 if (err)
636 log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
637 pool_is_locked = 1;
638
639 /* copy the entropy pool to a scratch pool and mix both of them */
640 for (i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
641 i < POOLWORDS; i++, dp++, sp++ )
642 {
643 *dp = *sp + ADD_VALUE;
644 }
645 mix_pool(rndpool); rndstats.mixrnd++;
646 mix_pool(keypool); rndstats.mixkey++;
647
648#ifdef HAVE_DOSISH_SYSTEM
649 fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
650 S_IRUSR|S_IWUSR );
651#else
652 fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
653#endif
654
655 if (fd == -1 )
656 log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
657 else
658 {
659 do
660 {
661 i = write (fd, keypool, POOLSIZE );
662 }
663 while( i == -1 && errno == EINTR );
664 if (i != POOLSIZE)
665 log_info (_("can't write `%s': %s\n"),
666 seed_file_name, strerror(errno) );
667 if (close(fd))
668 log_info(_("can't close `%s': %s\n"),
669 seed_file_name, strerror(errno) );
670 }
671
672 pool_is_locked = 0;
673 err = ath_mutex_unlock (&pool_lock);
674 if (err)
675 log_fatal ("failed to release the pool lock: %s\n", strerror (err));
676
677}
678
679
680/* Read random out of the pool. This function is the core of the
681 public random fucntions. Note that Level 0 is not anymore handeld
682 special and in fact an alias for level 1. */
683static void
684read_pool (byte *buffer, size_t length, int level)
685{
686 int i;
687 unsigned long *sp, *dp;
688 volatile pid_t my_pid; /* The volatile is there to make sure the
689 compiler does not optimize the code away
690 in case the getpid function is badly
691 attributed. */
692
693 retry:
694 /* Get our own pid, so that we can detect a fork. */
695 my_pid = getpid ();
696
697 assert (pool_is_locked);
698
699 /* Our code does not allow to extract more than POOLSIZE. Better
700 check it here. */
701 if (length > POOLSIZE)
702 {
703 log_bug("too many random bits requested\n");
704 }
705
706 if (!pool_filled)
707 {
708 if (read_seed_file() )
709 pool_filled = 1;
710 }
711
712 /* For level 2 quality (key generation) we always make sure that the
713 pool has been seeded enough initially. */
714 if (level == 2 && !did_initial_extra_seeding)
715 {
716 size_t needed;
717
718 pool_balance = 0;
719 needed = length - pool_balance;
720 if (needed < POOLSIZE/2)
721 needed = POOLSIZE/2;
722 else if( needed > POOLSIZE )
723 BUG ();
724 read_random_source (3, needed, 2);
725 pool_balance += needed;
726 did_initial_extra_seeding = 1;
727 }
728
729 /* For level 2 make sure that there is enough random in the pool. */
730 if (level == 2 && pool_balance < length)
731 {
732 size_t needed;
733
734 if (pool_balance < 0)
735 pool_balance = 0;
736 needed = length - pool_balance;
737 if (needed > POOLSIZE)
738 BUG ();
739 read_random_source( 3, needed, 2 );
740 pool_balance += needed;
741 }
742
743 /* make sure the pool is filled */
744 while (!pool_filled)
745 random_poll();
746
747 /* Always do a fast random poll (we have to use the unlocked version). */
748 do_fast_random_poll();
749
750 /* Mix the pool (if add_randomness() didn't it). */
751 if (!just_mixed)
752 {
753 mix_pool(rndpool);
754 rndstats.mixrnd++;
755 }
756
757 /* Create a new pool. */
758 for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
759 i < POOLWORDS; i++, dp++, sp++ )
760 *dp = *sp + ADD_VALUE;
761
762 /* Mix both pools. */
763 mix_pool(rndpool); rndstats.mixrnd++;
764 mix_pool(keypool); rndstats.mixkey++;
765
766 /* Read the required data. We use a readpoiter to read from a
767 different position each time */
768 while (length--)
769 {
770 *buffer++ = keypool[pool_readpos++];
771 if (pool_readpos >= POOLSIZE)
772 pool_readpos = 0;
773 pool_balance--;
774 }
775
776 if (pool_balance < 0)
777 pool_balance = 0;
778
779 /* Clear the keypool. */
780 memset (keypool, 0, POOLSIZE);
781
782 /* We need to detect whether a fork has happened. A fork might have
783 an identical pool and thus the child and the parent could emit
784 the very same random number. Obviously this can only happen when
785 running multi-threaded and the pool lock should even catch this.
786 However things do get wrong and thus we better check and retry it
787 here. We assume that the thread library has no other fatal
788 faults, though.
789 */
790 if ( getpid () != my_pid )
791 goto retry;
792}
793
794
795/*
796 * Add LENGTH bytes of randomness from buffer to the pool.
797 * source may be used to specify the randomness source.
798 * Source is:
799 *0 - used ony for initialization
800 *1 - fast random poll function
801 *2 - normal poll function
802 *3 - used when level 2 random quality has been requested
803 * to do an extra pool seed.
804 */
805static void
806add_randomness( const void *buffer, size_t length, int source )
807{
808 const byte *p = buffer;
809
810 assert (pool_is_locked);
811 if (!is_initialized)
812 initialize ();
813 rndstats.addbytes += length;
814 rndstats.naddbytes++;
815 while (length-- )
816 {
817 rndpool[pool_writepos++] ^= *p++;
818 if (pool_writepos >= POOLSIZE )
819 {
820 if (source > 1)
821 pool_filled = 1;
822 pool_writepos = 0;
823 mix_pool(rndpool); rndstats.mixrnd++;
824 just_mixed = !length;
825 }
826 }
827}
828
829
830
831static void
832random_poll()
833{
834 rndstats.slowpolls++;
835 read_random_source (2, POOLSIZE/5, 1);
836}
837
838
839static int (*
840getfnc_gather_random (void))(void (*)(const void*, size_t, int), int,
841 size_t, int)
842{
843 static int (*fnc)(void (*)(const void*, size_t, int), int, size_t, int);
844
845 if (fnc)
846 return fnc;
847
848#if USE_RNDLINUX
849 if ( !access (NAME_OF_DEV_RANDOM, R_OK)
850 && !access (NAME_OF_DEV_URANDOM, R_OK))
851 {
852 fnc = _gcry_rndlinux_gather_random;
853 return fnc;
854 }
855#endif
856
857#if USE_RNDEGD
858 if ( _gcry_rndegd_connect_socket (1) != -1 )
859 {
860 fnc = _gcry_rndegd_gather_random;
861 return fnc;
862 }
863#endif
864
865#if USE_RNDUNIX
866 fnc = _gcry_rndunix_gather_random;
867 return fnc;
868#endif
869
870#if USE_RNDW32
871 fnc = _gcry_rndw32_gather_random;
872 return fnc;
873#endif
874
875 log_fatal (_("no entropy gathering module detected\n"));
876
877 return NULL; /*NOTREACHED*/
878}
879
880static void (*
881getfnc_fast_random_poll (void))( void (*)(const void*, size_t, int), int)
882{
883#if USE_RNDW32
884 return _gcry_rndw32_gather_random_fast;
885#endif
886 return NULL;
887}
888
889
890static void
891do_fast_random_poll (void)
892{
893 static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
894 static int initialized = 0;
895
896 assert (pool_is_locked);
897
898 rndstats.fastpolls++;
899
900 if (!initialized )
901 {
902 if (!is_initialized )
903 initialize();
904 initialized = 1;
905 fnc = getfnc_fast_random_poll ();
906 }
907
908 if (fnc)
909 (*fnc)( add_randomness, 1 );
910
911 /* Continue with the generic functions. */
912#if HAVE_GETHRTIME
913 {
914 hrtime_t tv;
915 tv = gethrtime();
916 add_randomness( &tv, sizeof(tv), 1 );
917 }
918#elif HAVE_GETTIMEOFDAY
919 {
920 struct timeval tv;
921 if( gettimeofday( &tv, NULL ) )
922 BUG();
923 add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
924 add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
925 }
926#elif HAVE_CLOCK_GETTIME
927 {struct timespec tv;
928 if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
929 BUG();
930 add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
931 add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
932 }
933#else /* use times */
934# ifndef HAVE_DOSISH_SYSTEM
935 {struct tms buf;
936 times( &buf );
937 add_randomness( &buf, sizeof buf, 1 );
938 }
939# endif
940#endif
941
942#ifdef HAVE_GETRUSAGE
943# ifdef RUSAGE_SELF
944 {
945 struct rusage buf;
946 /* QNX/Neutrino does return ENOSYS - so we just ignore it and
947 * add whatever is in buf. In a chroot environment it might not
948 * work at all (i.e. because /proc/ is not accessible), so we better
949 * ugnore all error codes and hope for the best
950 */
951 getrusage (RUSAGE_SELF, &buf );
952 add_randomness( &buf, sizeof buf, 1 );
953 memset( &buf, 0, sizeof buf );
954 }
955# else /*!RUSAGE_SELF*/
956# ifdef __GCC__
957# warning There is no RUSAGE_SELF on this system
958# endif
959# endif /*!RUSAGE_SELF*/
960#endif /*HAVE_GETRUSAGE*/
961
962 /* time and clock are availabe on all systems - so we better do it
963 just in case one of the above functions didn't work */
964 {
965 time_t x = time(NULL);
966 add_randomness( &x, sizeof(x), 1 );
967 }
968 {
969 clock_t x = clock();
970 add_randomness( &x, sizeof(x), 1 );
971 }
972}
973
974
975/* The fast random pool function as called at some places in
976 libgcrypt. This is merely a wrapper to make sure that this module
977 is initalized and to look the pool. */
978void
979_gcry_fast_random_poll (void)
980{
981 int err;
982
983 /* We have to make sure that the intialization is done because this
984 gatherer might be called before any other functions and it is not
985 sufficient to initialize it within do_fast_random_pool because we
986 want to use the mutex here. FIXME: Whe should initialize the
987 mutex using a global constructor independent from the
988 initialization of the pool. */
989 if (!is_initialized)
990 initialize ();
991 err = ath_mutex_lock (&pool_lock);
992 if (err)
993 log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
994 pool_is_locked = 1;
995
996 do_fast_random_poll ();
997
998 pool_is_locked = 0;
999 err = ath_mutex_unlock (&pool_lock);
1000 if (err)
1001 log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
1002
1003}
1004
1005
1006
1007static void
1008read_random_source( int requester, size_t length, int level )
1009{
1010 static int (*fnc)(void (*)(const void*, size_t, int), int,
1011 size_t, int) = NULL;
1012 if (!fnc )
1013 {
1014 if (!is_initialized )
1015 initialize();
1016
1017 fnc = getfnc_gather_random ();
1018
1019 if (!fnc)
1020 {
1021 faked_rng = 1;
1022 fnc = gather_faked;
1023 }
1024 if (!requester && !length && !level)
1025 return; /* Just the init was requested. */
1026 }
1027
1028 if ((*fnc)( add_randomness, requester, length, level ) < 0)
1029 log_fatal ("No way to gather entropy for the RNG\n");
1030}
1031
1032
1033static int
1034gather_faked( void (*add)(const void*, size_t, int), int requester,
1035 size_t length, int level )
1036{
1037 static int initialized=0;
1038 size_t n;
1039 char *buffer, *p;
1040
1041 if( !initialized ) {
1042 log_info(_("WARNING: using insecure random number generator!!\n"));
1043 /* we can't use tty_printf here - do we need this function at
1044 all - does it really make sense or canit be viewed as a potential
1045 security problem ? wk 17.11.99 */
1046#if 0
1047 tty_printf(_("The random number generator is only a kludge to let\n"
1048 "it run - it is in no way a strong RNG!\n\n"
1049 "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
1050#endif
1051 initialized=1;
1052#ifdef HAVE_RAND
1053 srand( time(NULL)*getpid());
1054#else
1055 srandom( time(NULL)*getpid());
1056#endif
1057 }
1058
1059 p = buffer = gcry_xmalloc( length );
1060 n = length;
1061#ifdef HAVE_RAND
1062 while( n-- )
1063 *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
1064#else
1065 while( n-- )
1066 *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
1067#endif
1068 add_randomness( buffer, length, requester );
1069 gcry_free(buffer);
1070 return 0; /* okay */
1071}
1072
1073
1074/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
1075void
1076gcry_create_nonce (unsigned char *buffer, size_t length)
1077{
1078 static unsigned char nonce_buffer[20+8];
1079 static int nonce_buffer_initialized = 0;
1080 unsigned char *p;
1081 size_t n;
1082 int err;
1083
1084 /* Make sure we are initialized. */
1085 if (!is_initialized)
1086 initialize ();
1087
1088 /* Acquire the nonce buffer lock. */
1089 err = ath_mutex_lock (&nonce_buffer_lock);
1090 if (err)
1091 log_fatal ("failed to acquire the nonce buffer lock: %s\n",
1092 strerror (err));
1093
1094 /* The first time intialize our buffer. */
1095 if (!nonce_buffer_initialized)
1096 {
1097 pid_t apid = getpid ();
1098 time_t atime = time (NULL);
1099
1100 if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
1101 BUG ();
1102
1103 /* Initialize the first 20 bytes with a reasonable value so that
1104 a failure of gcry_randomize won't affect us too much. Don't
1105 care about the uninitialized remaining bytes. */
1106 p = nonce_buffer;
1107 memcpy (p, &apid, sizeof apid);
1108 p += sizeof apid;
1109 memcpy (p, &atime, sizeof atime);
1110
1111 /* Initialize the never changing private part of 64 bits. */
1112 gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
1113
1114 nonce_buffer_initialized = 1;
1115 }
1116
1117 /* Create the nonce by hashing the entire buffer, returning the hash
1118 and updating the first 20 bytes of the buffer with this hash. */
1119 for (p = buffer; length > 0; length -= n, p += n)
1120 {
1121 _gcry_sha1_hash_buffer (nonce_buffer,
1122 nonce_buffer, sizeof nonce_buffer);
1123 n = length > 20? 20 : length;
1124 memcpy (p, nonce_buffer, n);
1125 }
1126
1127
1128 /* Release the nonce buffer lock. */
1129 err = ath_mutex_unlock (&nonce_buffer_lock);
1130 if (err)
1131 log_fatal ("failed to release the nonce buffer lock: %s\n",
1132 strerror (err));
1133
1134}