r10656: BIG merge from trunk. Features not copied over
[samba.git] / source / lib / genrand.c
index ee8bc0b1d5abc59a11e75596cdc39872d3a0c874..f37bbc9c2fd3b310e7971246d80aa2e5801af7c6 100644 (file)
 
 #include "includes.h"
 
-static unsigned char hash[258];
+static unsigned char smb_arc4_state[258];
 static uint32 counter;
-static unsigned char *reseed_data;
-static size_t reseed_data_size;
+
+static BOOL done_reseed = False;
+static void (*reseed_callback)(int *newseed);
 
 /**************************************************************** 
  Copy any user given reseed data.
 *****************************************************************/
 
-void set_rand_reseed_data(unsigned char *data, size_t len)
+void set_rand_reseed_callback(void (*fn)(int *))
 {
-       SAFE_FREE(reseed_data);
-       reseed_data_size = 0;
-
-       reseed_data = (unsigned char *)memdup(data, len);
-       if (reseed_data)
-               reseed_data_size = len;
+       reseed_callback = fn;
+       set_need_random_reseed();
 }
 
-/**************************************************************** 
- Setup the seed.
-*****************************************************************/
-
-static void seed_random_stream(unsigned char *seedval, size_t seedlen)
+void set_need_random_reseed(void)
 {
-       unsigned char j = 0;
-       size_t ind;
-
-       for (ind = 0; ind < 256; ind++)
-               hash[ind] = (unsigned char)ind;
-
-       for( ind = 0; ind < 256; ind++) {
-               unsigned char tc;
-
-               j += (hash[ind] + seedval[ind%seedlen]);
-
-               tc = hash[ind];
-               hash[ind] = hash[j];
-               hash[j] = tc;
-       }
-
-       hash[256] = 0;
-       hash[257] = 0;
+       done_reseed = False;
 }
 
-/**************************************************************** 
- Get datasize bytes worth of random data.
-*****************************************************************/
-
-static void get_random_stream(unsigned char *data, size_t datasize)
+static void get_rand_reseed_data(int *reseed_data)
 {
-       unsigned char index_i = hash[256];
-       unsigned char index_j = hash[257];
-       size_t ind;
-
-       for( ind = 0; ind < datasize; ind++) {
-               unsigned char tc;
-               unsigned char t;
-
-               index_i++;
-               index_j += hash[index_i];
-
-               tc = hash[index_i];
-               hash[index_i] = hash[index_j];
-               hash[index_j] = tc;
-
-               t = hash[index_i] + hash[index_j];
-               data[ind] = hash[t];
+       if (reseed_callback) {
+               reseed_callback(reseed_data);
+       } else {
+               *reseed_data = 0;
        }
-
-       hash[256] = index_i;
-       hash[257] = index_j;
 }
 
 /****************************************************************
@@ -101,7 +57,7 @@ static void get_random_stream(unsigned char *data, size_t datasize)
  Note that the hash is not initialised.
 *****************************************************************/
 
-static void do_filehash(char *fname, unsigned char *the_hash)
+static void do_filehash(const char *fname, unsigned char *the_hash)
 {
        unsigned char buf[1011]; /* deliberate weird size */
        unsigned char tmp_md4[16];
@@ -136,6 +92,7 @@ static int do_reseed(BOOL use_fd, int fd)
        unsigned char seed_inbuf[40];
        uint32 v1, v2; struct timeval tval; pid_t mypid;
        struct passwd *pw;
+       int reseed_data = 0;
 
        if (use_fd) {
                if (fd != -1)
@@ -183,13 +140,14 @@ static int do_reseed(BOOL use_fd, int fd)
         * Add any user-given reseed data.
         */
 
+       get_rand_reseed_data(&reseed_data);
        if (reseed_data) {
                size_t i;
                for (i = 0; i < sizeof(seed_inbuf); i++)
-                       seed_inbuf[i] ^= reseed_data[i % reseed_data_size];
+                       seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)];
        }
 
-       seed_random_stream(seed_inbuf, sizeof(seed_inbuf));
+       smb_arc4_init(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf));
 
        return -1;
 }
@@ -198,15 +156,14 @@ static int do_reseed(BOOL use_fd, int fd)
  Interface to the (hopefully) good crypto random number generator.
 ********************************************************************/
 
-void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now)
+void generate_random_buffer( unsigned char *out, int len)
 {
-       static BOOL done_reseed = False;
        static int urand_fd = -1;
        unsigned char md4_buf[64];
        unsigned char tmp_buf[16];
        unsigned char *p;
 
-       if(!done_reseed || do_reseed_now) {
+       if(!done_reseed) {
                urand_fd = do_reseed(True, urand_fd);
                done_reseed = True;
        }
@@ -234,7 +191,7 @@ void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now)
        while(len > 0) {
                int copy_len = len > 16 ? 16 : len;
 
-               get_random_stream(md4_buf, sizeof(md4_buf));
+               smb_arc4_crypt(smb_arc4_state, md4_buf, sizeof(md4_buf));
                mdfour(tmp_buf, md4_buf, sizeof(md4_buf));
                memcpy(p, tmp_buf, copy_len);
                p += copy_len;
@@ -257,9 +214,9 @@ char *generate_random_str(size_t len)
 
        if (len > sizeof(retstr)-1)
                len = sizeof(retstr) -1;
-       generate_random_buffer( retstr, len, False);
+       generate_random_buffer( retstr, len);
        for (i = 0; i < len; i++)
-               retstr[i] = c_list[ retstr[i] % sizeof(c_list) ];
+               retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ];
 
        retstr[i] = '\0';