NetBSD recently changed to a /dev/urandom implementation which keys a
stream generator per-open rather than one that draws bits directly
from the kernel entropy pool. When we did this we added a number of
extra warnings that are triggered by applications consuming large
amounts of entropy.
Shortly thereafter, we noticed that OpenSSH sshd uses a great deal of
entropy indeed, though it does not directly access /dev/urandom nor
does it directly call the OpenSSL RAND API. The root cause of this
behavior is that sshd re-execs itself for each new connection, which
then causes OpenSSL to reinitialize the SSLeay entropy gathering
functions that are in crypto/rand/md_rand.c. They in turn call
RAND_poll() in crypto/rand/rand_unix.c, and for each call to RAND_poll,
OpenSSL opens /dev/urandom, reads 256 bits, and closes /dev/urandom.
While considering ways for OpenSSH to be somewhat stingier with random
bits from the kernel, I noticed two rather dubious things about the
md_rand.c/rand_unix.c code:
* First, there is an #ifdef OpenBSD block which replaces the entirety
of RAND_poll() with calls to arc4random(). I can only assume this
was done when someone running OpenBSD noticed the same problem with
excessive entropy consumption from /dev/urandom that I have just
noticed on NetBSD.
Unless I misunderstand, this means that all the key material for the
new FIPS-compliant CTR_DRBG is in fact being supplied by an instance
of RC4! That seems extremely questionable at best.
* Second, I believe the interaction of the "initialized" and "ok" tests
in ssleay_rand_bytes() in md_rand.c is not right, because it prevents
an application from seeding the generator with entropy of its own
choice rather than having it autopmatically seeded by RAND_poll().
I think the block:
if (!initialized)
{
RAND_poll();
initialized = 1;
}
Should be removed. I think that the RAND_poll() call should be moved
to the "if (!ok)" block just below, instead. As I read the code, this
would allow an application to seed the generator with entropy via
RAND_seed(), RAND_add(), or RAND_load_file() and avoid the /dev/urandom
use. With this change I could make OpenSSH sshd pass entropy from parent
to child when re-executing itself, which would be a huge improvement
to entropy consumption on many server systems and would also probably
allow removal of the awful arc4random() hack mentioned above, while
achieving what I think was probably its original design goal.
Opinions?
Thor
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]