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]