[openssl-dev] Improving OpenSSL default RNG

Alessandro Ghedini alessandro at ghedini.me
Fri Oct 23 13:22:39 UTC 2015


Hello everyone,

(sorry for the wall of text...)

one of the things that both BoringSSL and LibreSSL have in common is the
replacement of OpenSSL's default RNG RAND_SSLeay() with a simpler and saner
alternative. Given RAND_SSLeay() complexity I think it'd be worth to at least
consider possible alternatives for OpenSSL.

BoringSSL started using the system RNG (e.g. /dev/urandom) for every call to
RAND_bytes(). Additionally, if the RDRAND instruction is available, the output
of RDRAND is mixed with the output of the system RNG using ChaCha20. This uses
thread-local storage to keep the global RNG state.

Incidentally, BoringSSL added a whole new API for thread-local storage which
OpenSSL could adopt given that e.g. the ASYNC support could benefit from it
(there are other interesting bits in BoringSSL, like the new threading API that
could also be adopted by OpenSSL).

The BoringSSL method is very simple but it needs a read from /dev/urandom for
every call to RAND_bytes() which can be slow (though, BoringSSL's RAND_bytes()
seems to implement some sort of buffering for /dev/urandom so the cost may be
lower).

On the other hand, LibreSSL replaced the whole RAND_* API with calls to
OpenBSD's arc4random(). This is a nice and simple scheme that uses ChaCha20 to
mix the internal RNG state, which is regularly reseeded from the system RNG.
The core logic of this (excluding ChaCha20 and platform-specific bits) is
implemented in less than 200 lines of code and, at least in theory, it's the
one that provides the best performance/simplicity trade-off (ChaCha20 can be
pretty fast even for non-asm platform-generic implementations).

Both of these methods are robust and mostly platform-indipendent (e.g. none of
them uses the system time, PID or uninitilized buffers to seed the RNG state)
and have simple implementations, so I think OpenSSL can benefit a lot from
adopting one of them. The astute readers may point out that OpenSSL doesn't
support ChaCha20 yet, but that's hopefully coming soon.

I think there's also room for improvement in the platform-specific RAND_poll()
implementations, e.g.:

- on Linux getrandom() should be used if available
- on OpenBSD getentropy() should be used instead of arc4random()
- the /dev/urandom code IMO can be simplified
- the non-CryptGenRandom() code on Windows is just crazy. Do we even support
  Windows versions before XP?
- is EGD actually used anywhere today?
- what about Netware, OS/2 and VMS, do we have any users on them? IIRC support
  for other platforms has already been removed, what are the criteria for
  keeping support for one?
- etc...

For comparison, OpenBSD's getentropy() implementation [0] is much cleaner and
supports many of the platforms supported by OpenSSL.

So, any thought? If there's interest in this, I can look into investigating
these things more in detail and propose possible patches.

Cheers

[0] https://github.com/libressl-portable/openbsd/tree/master/src/lib/libcrypto/crypto
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://mta.openssl.org/pipermail/openssl-dev/attachments/20151023/6e79eebd/attachment.sig>


More information about the openssl-dev mailing list