/** Interface to the (hopefully) good crypto random number generator. Will use our internal PRNG if more than 40 bytes of random generation has been requested, otherwise tries to read from /dev/random **/ _PUBLIC_ void generate_random_buffer(uint8_t *out, int len) { unsigned char md4_buf[64]; unsigned char tmp_buf[16]; unsigned char *p; if(!done_reseed) { bytes_since_reseed += len; /* Magic constant to try and avoid reading 40 bytes * and setting up the PRNG if the app only ever wants * a few bytes */ if (bytes_since_reseed < 40) { if (urand_fd == -1) { urand_fd = open( "/dev/urandom", O_RDONLY,0); if (urand_fd != -1) { smb_set_close_on_exec(urand_fd); } } if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { return; } } urand_fd = do_reseed(urand_fd); done_reseed = true; } /* * Generate random numbers in chunks of 64 bytes, * then md4 them & copy to the output buffer. * This way the raw state of the stream is never externally * seen. */ p = out; while(len > 0) { int copy_len = len > 16 ? 16 : len; get_random_stream(md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; len -= copy_len; } }
void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) { 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) { urand_fd = do_reseed(True, urand_fd); done_reseed = True; } if (urand_fd != -1 && len > 0) { if (read(urand_fd, out, len) == len) return; /* len bytes of random data read from urandom. */ /* Read of urand error, drop back to non urand method. */ close(urand_fd); urand_fd = -1; do_reseed(False, -1); done_reseed = True; } /* * Generate random numbers in chunks of 64 bytes, * then md4 them & copy to the output buffer. * This way the raw state of the stream is never externally * seen. */ p = out; while(len > 0) { int copy_len = len > 16 ? 16 : len; get_random_stream(md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; len -= copy_len; } }