aboutsummaryrefslogtreecommitdiffstats
path: root/cipher/random.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>1998-11-25 11:52:41 +0000
committerWerner Koch <[email protected]>1998-11-25 11:52:41 +0000
commit2e494682b63e9f7abc2a34711618f4ebd21e2744 (patch)
treee8afb0e10b4657a3d841ff9cb02a752698c19f97 /cipher/random.c
parentReady for version 0.4.4 (diff)
downloadgnupg-2e494682b63e9f7abc2a34711618f4ebd21e2744.tar.gz
gnupg-2e494682b63e9f7abc2a34711618f4ebd21e2744.zip
Restructured the RNG source and add support for loadable
random modules.
Diffstat (limited to '')
-rw-r--r--cipher/random.c143
1 files changed, 136 insertions, 7 deletions
diff --git a/cipher/random.c b/cipher/random.c
index e22f3d70c..e173a5279 100644
--- a/cipher/random.c
+++ b/cipher/random.c
@@ -36,7 +36,9 @@
#include "rmd.h"
#include "ttyio.h"
#include "i18n.h"
+#include "random.h"
#include "rand-internal.h"
+#include "dynload.h"
#if SIZEOF_UNSIGNED_LONG == 8
@@ -47,6 +49,20 @@
#error weird size for an unsigned long
#endif
+#define BLOCKLEN 64 /* hash this amount of bytes */
+#define DIGESTLEN 20 /* into a digest of this length (rmd160) */
+/* poolblocks is the number of digests which make up the pool
+ * and poolsize must be a multiple of the digest length
+ * to make the AND operations faster, the size should also be
+ * a multiple of ulong
+ */
+#define POOLBLOCKS 30
+#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
+#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
+ #error Please make sure that poolsize is a multiple of ulong
+#endif
+#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
+
static int is_initialized;
#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0)
@@ -60,9 +76,16 @@ static int just_mixed;
static int secure_alloc;
static int quick_test;
+static int faked_rng;
static void read_pool( byte *buffer, size_t length, int level );
+static void add_randomness( const void *buffer, size_t length, int source );
+static void random_poll(void);
+static void read_random_source( byte *buffer, size_t length, int level );
+#ifndef HAVE_DEV_RANDOM
+static int gather_faked( byte *buffer, size_t *r_length, int level );
+#endif
static void
@@ -76,6 +99,20 @@ initialize()
keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
: m_alloc_clear(POOLSIZE+BLOCKLEN);
is_initialized = 1;
+
+ #if USE_RNDLINUX
+ rndlinux_constructor();
+ #elif USE_RNDUNIX
+ rndunix_constructor();
+ #elif USE_RNDW32
+ rndw32_constructor();
+ #elif USE_RNDOS2
+ rndos2_constructor();
+ #elif USE_RNDATARI
+ rndatari_constructor();
+ #elif USE_RNDMVS
+ rndmvs_constructor();
+ #endif
}
void
@@ -88,13 +125,13 @@ secure_random_alloc()
int
quick_random_gen( int onoff )
{
- int last = quick_test;
+ int last;
+
+ read_random_source( NULL, 0, 0 ); /* load module */
+ last = quick_test;
if( onoff != -1 )
quick_test = onoff;
- #ifdef USE_RAND_DUMMY
- last = 1; /* insecure RNG */
- #endif
- return last;
+ return faked_rng? 1 : last;
}
@@ -250,9 +287,9 @@ read_pool( byte *buffer, size_t length, int level )
/****************
* Add LENGTH bytes of randomness from buffer to the pool.
- * source may be used to specify the randomeness source.
+ * source may be used to specify the randomness source.
*/
-void
+static void
add_randomness( const void *buffer, size_t length, int source )
{
if( !is_initialized )
@@ -271,3 +308,95 @@ add_randomness( const void *buffer, size_t length, int source )
+static void
+random_poll()
+{
+ char buf[POOLSIZE/5];
+ read_random_source( buf, POOLSIZE/5, 1 );
+ add_randomness( buf, POOLSIZE/5, 2);
+ memset( buf, 0, POOLSIZE/5);
+}
+
+
+void
+fast_random_poll()
+{
+ static void (*fnc)( void (*)(const void*, size_t, int)) = NULL;
+ static int initialized = 0;
+
+ if( !initialized ) {
+ if( !is_initialized )
+ initialize();
+ initialized = 1;
+ fnc = dynload_getfnc_fast_random_poll();
+ if( !fnc )
+ log_info("Ooops: No fast random poll function\n");
+ }
+ if( fnc )
+ (*fnc)( add_randomness );
+}
+
+
+
+static void
+read_random_source( byte *buffer, size_t length, int level )
+{
+ static int (*fnc)(byte*, size_t*, int) = NULL;
+ int nbytes;
+ int goodness;
+
+ if( !fnc ) {
+ if( !is_initialized )
+ initialize();
+ fnc = dynload_getfnc_gather_random();
+ if( !fnc ) {
+ faked_rng = 1;
+ #ifndef HAVE_DEV_RANDOM
+ fnc = gather_faked;
+ #else
+ BUG();
+ #endif
+ }
+ }
+ while( length ) {
+ nbytes = length;
+ goodness = (*fnc)( buffer, &nbytes, level );
+ buffer +=nbytes;
+ length -= nbytes;
+ /* FIXME: how can we handle the goodness */
+ }
+}
+
+
+#ifndef HAVE_DEV_RANDOM
+static int
+gather_faked( byte *buffer, size_t *r_length, int level )
+{
+ static int initialized=0;
+ size_t length = *r_length;
+
+ if( !initialized ) {
+ log_info(_("WARNING: using insecure random number generator!!\n"));
+ tty_printf(_("The random number generator is only a kludge to let\n"
+ "it compile - it is in no way a strong RNG!\n\n"
+ "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
+ initialized=1;
+ #ifdef HAVE_RAND
+ srand(make_timestamp()*getpid());
+ #else
+ srandom(make_timestamp()*getpid());
+ #endif
+ }
+
+ #ifdef HAVE_RAND
+ while( length-- )
+ *buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
+ #else
+ while( length-- )
+ *buffer++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
+ #endif
+ return 100; /* We really fake it ;-) */
+}
+
+#endif /* ! HAVE_DEV_RANDOM */
+