I have tried to make the PRNG code more readable, and also made a few
changes.  I'd appreciate it if people could review the code.

Index: md_rand.c
===================================================================
RCS file: /usr/local/openssl/cvs//openssl/crypto/rand/md_rand.c,v
retrieving revision 1.19
diff -u -r1.19 md_rand.c
--- md_rand.c   1999/05/21 11:16:36     1.19
+++ md_rand.c   1999/09/08 20:57:45
@@ -121,17 +121,19 @@
 
 #include <openssl/rand.h>
 
-/* #define NORAND      1 */
 /* #define PREDICT     1 */
 
 #define STATE_SIZE     1023
-static int state_num=0,state_index=0;
+static int state_num=0; /* number of bytes in pool */
+static state_index=0;   /* index to pool */
 static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
 static unsigned char md[MD_DIGEST_LENGTH];
-static long md_count[2]={0,0};
+static long md_count[2]={0,0}; /* counter for generation and seed operations */
+static int init=1;
 
 const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT;
 
+static void ssleay_rand_init(int);
 static void ssleay_rand_cleanup(void);
 static void ssleay_rand_seed(const void *buf, int num);
 static void ssleay_rand_bytes(unsigned char *buf, int num);
@@ -140,6 +142,7 @@
        ssleay_rand_seed,
        ssleay_rand_bytes,
        ssleay_rand_cleanup,
+       ssleay_rand_init
        }; 
 
 RAND_METHOD *RAND_SSLeay(void)
@@ -155,79 +158,117 @@
        memset(md,0,MD_DIGEST_LENGTH);
        md_count[0]=0;
        md_count[1]=0;
+       init=1;
        }
 
+static void ssleay_rand_init(int fast)
+       {
+       int r=0;
+       FILE *fh;
+       unsigned long l;
+
+       init=0;
+
+#ifdef DEVRANDOM
+       /* 
+        * Use a random entropy pool device. Linux and FreeBSD have
+        * this. Use /dev/urandom if you can as /dev/random will block
+        * if it runs out of random entries.
+        */
+       if ((fh = fopen(DEVRANDOM, "rb")) != NULL)
+               {
+               unsigned char tmpbuf[STATE_SIZE];
+               r=fread((unsigned char *)tmpbuf,1,128,fh);
+               fclose(fh);
+#if 0
+               CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+               for (i = 0; i < r; i++)
+                       state[i] ^= tmpbuf[i];
+               if (state_num < r)
+                       state_num = r;
+               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+#endif
+               RAND_seed(tmpbuf, r);
+               }
+#endif /* DEVRANDOM */
+
+       /* put in some default random data, we need more than just this */
+       l=time(NULL);
+       RAND_seed(&l,sizeof(l));
+#ifndef MSDOS
+       l=getpid();
+       RAND_seed(&l,sizeof(l));
+       l=getuid();
+       RAND_seed(&l,sizeof(l));
+#endif
+
+       if (!fast && r < 128)
+               {
+               // insert something like Peter Gutmann's Randomness-Gathering Code 
+here ...
+               }
+       }
+
 static void ssleay_rand_seed(const void *buf, int num)
        {
-       int i,j,k,st_idx,st_num;
+       int j,k,idx;
        MD_CTX m;
 
-#ifdef NORAND
-       return;
-#endif
+       if (init)
+               ssleay_rand_init(1);
 
        CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-       st_idx=state_index;
-       st_num=state_num;
-
-       state_index=(state_index+num);
+       idx=state_index;
+       state_index+=num;
        if (state_index >= STATE_SIZE)
                {
                state_index%=STATE_SIZE;
                state_num=STATE_SIZE;
                }
-       else if (state_num < STATE_SIZE)        
+       else if (state_num < STATE_SIZE && state_index > state_num)
                {
-               if (state_index > state_num)
-                       state_num=state_index;
+               state_num=state_index;
                }
        CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
-       for (i=0; i<num; i+=MD_DIGEST_LENGTH)
+       while (num > 0)
                {
-               j=(num-i);
-               j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j;
+               /* number of bytes to be added to the pool in this round */
+               j=MD_DIGEST_LENGTH;
+               if (j > num)
+                   j = num;
 
                MD_Init(&m);
                MD_Update(&m,md,MD_DIGEST_LENGTH);
-               k=(st_idx+j)-STATE_SIZE;
-               if (k > 0)
+               if (idx+j > STATE_SIZE)
                        {
-                       MD_Update(&m,&(state[st_idx]),j-k);
-                       MD_Update(&m,&(state[0]),k);
+                       MD_Update(&m, state+idx, STATE_SIZE-idx);
+                       MD_Update(&m, state, idx+j-STATE_SIZE);
                        }
                else
-                       MD_Update(&m,&(state[st_idx]),j);
-                       
-               MD_Update(&m,buf,j);
-               MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
-               MD_Final(md,&m);
-               md_count[1]++;
+                       MD_Update(&m, state+idx, j);
 
-               buf=(const char *)buf + j;
+               MD_Update(&m, buf, j);
+               MD_Update(&m, (unsigned char *) md_count, sizeof(md_count));
+               MD_Final(md, &m);
+               md_count[1]++;
 
+               /* xor j hash bytes into state at idx */
                for (k=0; k<j; k++)
                        {
-                       state[st_idx++]^=md[k];
-                       if (st_idx >= STATE_SIZE)
-                               {
-                               st_idx=0;
-                               st_num=STATE_SIZE;
-                               }
+                       state[idx++]^=md[k];
+                       if (idx >= STATE_SIZE)
+                               idx=0;
                        }
+
+               buf+=j, num-=j;
                }
        memset((char *)&m,0,sizeof(m));
        }
 
 static void ssleay_rand_bytes(unsigned char *buf, int num)
        {
-       int i,j,k,st_num,st_idx;
+       int j,k,idx;
        MD_CTX m;
-       static int init=1;
-       unsigned long l;
-#ifdef DEVRANDOM
-       FILE *fh;
-#endif
 
 #ifdef PREDICT
        {
@@ -239,94 +280,53 @@
        }
 #endif
 
-       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-
        if (init)
-               {
-               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
-               /* put in some default random data, we need more than
-                * just this */
-               RAND_seed(&m,sizeof(m));
-#ifndef MSDOS
-               l=getpid();
-               RAND_seed(&l,sizeof(l));
-               l=getuid();
-               RAND_seed(&l,sizeof(l));
-#endif
-               l=time(NULL);
-               RAND_seed(&l,sizeof(l));
-
-/* #ifdef DEVRANDOM */
-               /* 
-                * Use a random entropy pool device.
-                * Linux 1.3.x and FreeBSD-Current has 
-                * this. Use /dev/urandom if you can
-                * as /dev/random will block if it runs out
-                * of random entries.
-                */
-               if ((fh = fopen(DEVRANDOM, "r")) != NULL)
-                       {
-                       unsigned char tmpbuf[32];
+               ssleay_rand_init(1);
 
-                       fread((unsigned char *)tmpbuf,1,32,fh);
-                       /* we don't care how many bytes we read,
-                        * we will just copy the 'stack' if there is
-                        * nothing else :-) */
-                       fclose(fh);
-                       RAND_seed(tmpbuf,32);
-                       memset(tmpbuf,0,32);
-                       }
-/* #endif */
-#ifdef PURIFY
-               memset(state,0,STATE_SIZE);
-               memset(md,0,MD_DIGEST_LENGTH);
-#endif
-               CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-               init=0;
-               }
-
-       st_idx=state_index;
-       st_num=state_num;
+       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+       idx=state_index;
        state_index+=num;
        if (state_index > state_num)
-               state_index=(state_index%state_num);
+               state_index%=state_num;
 
        CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
        while (num > 0)
                {
-               j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
-               num-=j;
+               /* number of bytes to be generated in the round */
+               j=MD_DIGEST_LENGTH/2;
+               if (j > num)
+                   j = num;
+
                MD_Init(&m);
-               MD_Update(&m,&(md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2);
-               MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
-#ifndef PURIFY
-               MD_Update(&m,buf,j); /* purify complains */
-#endif
-               k=(st_idx+j)-st_num;
-               if (k > 0)
+               MD_Update(&m, md+MD_DIGEST_LENGTH/2, MD_DIGEST_LENGTH/2);
+               MD_Update(&m, (unsigned char *) md_count, sizeof(md_count));
+
+               if (idx+j > state_num)
                        {
-                       MD_Update(&m,&(state[st_idx]),j-k);
-                       MD_Update(&m,&(state[0]),k);
+                       MD_Update(&m, state+idx, state_num-idx);
+                       MD_Update(&m, state, idx+j-state_num);
                        }
                else
-                       MD_Update(&m,&(state[st_idx]),j);
-               MD_Final(md,&m);
+                       MD_Update(&m, state + idx, j);
+               MD_Final(md, &m);
 
-               for (i=0; i<j; i++)
+               /* output bytes, update state at idx */
+               for (k=0; k<j; k++)
                        {
-                       if (st_idx >= st_num)
-                               st_idx=0;
-                       state[st_idx++]^=md[i];
-                       *(buf++)=md[i+MD_DIGEST_LENGTH/2];
+                       if (idx >= state_num)
+                               idx=0;
+                       state[idx++]^=md[k];
+                       *(buf++)=md[k+MD_DIGEST_LENGTH/2];
                        }
+               num-=j;
                }
 
        MD_Init(&m);
-       MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
+       MD_Update(&m, (unsigned char *) md_count, sizeof(md_count));
        md_count[0]++;
-       MD_Update(&m,md,MD_DIGEST_LENGTH);
-       MD_Final(md,&m);
+       MD_Update(&m, md, MD_DIGEST_LENGTH);
+       MD_Final(md, &m);
        memset(&m,0,sizeof(m));
        }
 
@@ -354,7 +354,7 @@
  */
 /*
  * I have modified the loading of bytes via RAND_seed() mechanism since
- * the origional would have been very very CPU intensive since RAND_seed()
+ * the original would have been very very CPU intensive since RAND_seed()
  * does an MD5 per 16 bytes of input.  The cost to digest 16 bytes is the same
  * as that to digest 56 bytes.  So under the old system, a screen of
  * 1024*768*256 would have been CPU cost of approximatly 49,000 56 byte MD5
@@ -408,10 +408,10 @@
        /* Copy bitmap bits from memory DC to bmbits */
        GetBitmapBits(hBitmap, size, bmbits);
 
-       /* Get the MD5 of the bitmap */
+       /* Get the MD of the bitmap */
        MD(bmbits,size,md);
 
-       /* Seed the random generator with the MD5 digest */
+       /* Seed the random generator with the MD digest */
        RAND_seed(md, MD_DIGEST_LENGTH);
        }
 
Index: rand.h
===================================================================
RCS file: /usr/local/openssl/cvs//openssl/crypto/rand/rand.h,v
retrieving revision 1.4
diff -u -r1.4 rand.h
--- rand.h      1999/04/26 16:42:20     1.4
+++ rand.h      1999/09/08 20:50:29
@@ -68,12 +68,14 @@
        void (*seed)(const void *buf, int num);
        void (*bytes)(unsigned char *buf, int num);
        void (*cleanup)(void);
+       void (*init)(int fast);
        } RAND_METHOD;
 
 void RAND_set_rand_method(RAND_METHOD *meth);
-RAND_METHOD *RAND_get_rand_method(void );
+RAND_METHOD *RAND_get_rand_method(void);
 RAND_METHOD *RAND_SSLeay(void);
-void RAND_cleanup(void );
+void RAND_init(int);
+void RAND_cleanup(void);
 void RAND_bytes(unsigned char *buf,int num);
 void RAND_seed(const void *buf,int num);
 int  RAND_load_file(const char *file,long max_bytes);
Index: rand_lib.c
===================================================================
RCS file: /usr/local/openssl/cvs//openssl/crypto/rand/rand_lib.c,v
retrieving revision 1.5
diff -u -r1.5 rand_lib.c
--- rand_lib.c  1999/04/23 22:11:52     1.5
+++ rand_lib.c  1999/09/08 20:53:55
@@ -96,3 +96,8 @@
                rand_meth->bytes(buf,num);
        }
 
+void RAND_init(fast)
+       {
+       if (rand_meth != NULL)
+               rand_meth->init(fast);
+       }
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to