As I was going through Crypt::SSLeay, preparing it for the next release, I noticed the following code, written way before my time,
...
int rand_bytes_read;
static int bNotFirstTime;
char buf[ 1024 ];
...
if(!bNotFirstTime) {
SSLeay_add_all_algorithms();
SSL_load_error_strings();
ERR_load_crypto_strings();
SSL_library_init();
bNotFirstTime = 1;
}
/**** Code from ..., 10/3/2002 ****/
/**** Use /dev/urandom to seed if available ****/
rand_bytes_read = RAND_load_file("/dev/urandom", 1024);
if (rand_bytes_read <= 0) {
/* Couldn't read /dev/urandom, just seed off
* of the stack variable (the old way)
*/
RAND_seed(buf,sizeof buf);
}
First, it seems to me that the correct way to check if RAND_load_file
succeeded is to check if bytes read is equal to bytes requested.
Leaving that aside, it is my understanding that SSL_library_init
does seed the PRNG from /dev/urandom
if it is available, and from other sources on Windows etc.
Is there a reason to try to re-seed the PRNG every time a new context is created (
SSL_library_init
is only invoked the first time)?Is using the contents of a stack variable an acceptable way to provide randomness?
OpenSSL's Wiki states:
InitializationOpenSSL will attempt to seed the random number generator automatically upon instantiation by calling
RAND_poll
.RAND_poll
seeds the random number generator using a system-specific entropy source, which is/dev/urandom
on UNIX-like operating systems, and is a combination ofCryptGenRandom
and other sources of entropy on Windows.Be careful when deferring to
RAND_poll
on some Unix systems because it does not seed the generator. See the code guarded withOPENSSL_SYS_VXWORKS
in rand_unix.c. Additionally,RAND_poll
can have negative interactions on newer Windows platforms, so your program could hang or crash depending on the potential issue. See Windows Issues below.
PS: Crypt::SSLeay
provides support for Perl's LWP::UserAgent to communicate over HTTPS. It is no longer used by default, but it is maintained so as not to break older setups.