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                       openssl-dev@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to