[cryptography] Just how bad is OpenSSL ?

Patrick Pelletier code at funwithsoftware.org
Sat Oct 27 21:47:05 EDT 2012

On 10/26/12 11:29 AM, John Case wrote:

> So, given what is in the stanford report and then reading this rant
> about openssl, I am wondering just how bad openssl is ?  I've never had
> to implement it or code with it, so I really have no idea.

I think that "OpenSSL is written by monkeys" is a bit sensationalist and 
unfair, but I do think it's fair to say that OpenSSL is user-hostile, 
and is written by experts for their own use, not for others to come 
along and use.

The biggest problem with OpenSSL is that it is really, really poorly 
documented.  There is no "big picture, gentle introduction" 
documentation that ships with OpenSSL.  Most of the OpenSSL functions 
are documented in man pages, but some important functions are not 
documented.  And the man pages often don't explain enough about the 
functions, like "why would I want to use this function instead of that 
one, when they both sound like they do the same thing?"  Also, the 
naming of the man pages is user-hostile.  The worst one is that there is 
a man page named "rand".  The other OpenSSL man pages tell me to see 
"rand(3)".  But, of course, "man 3 rand" gets me the man page for the C 
standard library function, rand().  I eventually figured out I needed to 
do "man 3ssl rand" to get the man page for OpenSSL's random number 

As far as I can tell, there is only one decent book that has been 
written about OpenSSL: the O'Reilly book "Network Security with 
OpenSSL".  It is ten years old now, which is not as bad as it sounds, 
because OpenSSL hasn't changed that much since then.  Nevertheless, it 
obviously doesn't cover anything that's been added to OpenSSL in the 
past decade, and I had to modify some of the code examples because 
current versions of OpenSSL are better about using "const" in function 
prototypes, for instance.  I also got some good laughs, like when the 
book talked about this brand-new algorithm called AES that OpenSSL had 
just recently added support for.

Between reading the O'Reilly book, the man pages, the OpenSSL mailing 
list, random things people have written on the web, and of course, the 
source code (a lot!), I've been able to use OpenSSL, but it's been very 
slow and frustrating, and I curse the name of OpenSSL every day.

Besides the poor documentation, the other thing about OpenSSL is that it 
is definitely not "batteries included."  Now, I'm not expecting it to be 
some high-level https library like curl.  I intentionally wanted a 
low-level TLS library, because my job was to encapsulate a custom 
messaging protocol in TLS.  But still, OpenSSL is lacking in some things 
I would hope a low-level TLS library would have.  For instance, it 
doesn't have everything you need to validate certificates, and you need 
to write some of that code yourself.

One of the most glaring things OpenSSL is missing out-of-the-box is 
thread safety.  If you want OpenSSL to be threadsafe, you have to supply 
your own callback.  This is different than the approach taken by many 
other libraries (for example, libevent, or GnuTLS) which supply 
threading implementations for pthreads and Win32, and only require 
callbacks if you are on a more exotic operating system.  Not only is it 
annoying to have to supply this boilerplate code, but my bigger concern 
is that it makes it very tricky to use OpenSSL from more than one 
library in the same process.  Assuming that each library wants to be 
threadsafe, and wants to hide its use of OpenSSL as an implementation 
detail (rather than telling the user "you need to supply OpenSSL thread 
callbacks"), then that means each library needs to set the OpenSSL 
threading callbacks to point at its own implementation.  But since the 
OpenSSL threading callbacks are global, only one of them is going to 
"win".  Now, it's possible that everything will be okay, because whoever 
"wins" will just end up providing thread safety to everyone.  But, it 
seems kind of sketchy and scary, and I can imagine bad things happening, 
like if one library is initialized (and thus sets the OpenSSL callbacks) 
after another library is already using OpenSSL.

(One of the things I'm getting at in the previous paragraph is that 
OpenSSL seems to be written with the intention that it's only going to 
be used by the "main program", which a single person or organization is 
going to write.  OpenSSL doesn't seem to have in mind the possibility 
that it will be used by multiple, higher-level libraries which don't 
know anything about each other, but which are all used by a single 
program in a single address space.)

So, I think that OpenSSL could be made better by two things: (1) better 
documentation, and (2) a small "helper" library that sits on top of it 
and provides thread-safety callbacks, and other "missing" helper 
functions like certificate validation.  But, the helper library should 
be small, simple, and low-level enough that it would be possible to 
convince the high-level libraries (such as curl, libevent, etc.) to link 
against it, rather than each providing their own thread callbacks to 
OpenSSL.  I've felt some temptation to write such a library, if there 
are people besides me who think it is a good idea and would be 
interested in using it.

However, if you have a choice of what TLS library to use, you might be 
better off using a different one, such as GnuTLS.  GnuTLS has an 
absolutely wonderful manual; the contrast between OpenSSL's 
documentation and GnuTLS's documentation is like night and day! 
However, despite the atrocious documentation, I ended up picking OpenSSL 
over GnuTLS for my project (a closed-source project at work, not 
something I was doing on my own) for a couple of reasons:

(1) We wanted to use libevent, and libevent has an integration with 
OpenSSL.  If we'd used GnuTLS, we would have had to write our own 
integration between libevent and GnuTLS.

(2) GnuTLS is LGPL-licensed, which is normally not a problem for 
closed-source software.  However, we needed to support a wide variety of 
platforms, including iPhone, and we had some concern that the LGPL was 
not compatible with the terms of the iOS App Store.

For the most part, I would say that OpenSSL is not badly written, just 
badly documented.  I am not a cryptography expert (just a smart, 
experienced programmer, trying to use TLS) so I'm not in a particularly 
good position to judge the cryptographic merits of OpenSSL.  For the 
most part, it seems sound, although a couple of things have given me 
pause.  One is OPENSSL_cleanse, which overwrites memory with random 
data.  Every other cryptography library I've seen seems to be happy with 
just overwriting sensitive memory with zero.  I haven't seen any 
explanation of why OpenSSL believes that overwriting with random data is 
better than overwriting with zero.  In the absence of an explanation, it 
feels a bit cargo-cultish.

The other thing that bugged me a bit was in the infamous rand(3ssl) man 

        3.  The state should be very large.  If the RNG is being used
            to generate 4096 bit RSA keys, 2 2048 bit random strings
            are required (at a minimum).  If your RNG state only has
            128 bits, you are obviously limiting the search space to
            128 bits, not 2048.  I'm probably getting a little
            carried away on this last point but it does indicate that
            it may not be a bad idea to keep quite a lot of RNG
            state.  It should be easier to break a cipher than guess
            the RNG seed data.

This seems to contradict the advice given on Linux's random(4) man page:

        The  amount  of  seed material required to generate a crypto‐
        graphic key equals the effective key size of  the  key.   For
        example,  a 3072-bit RSA or Diffie-Hellman private key has an
        effective key size of 128 bits (it requires about 2^128 oper‐
        ations  to  break) so a key generator only needs 128 bits (16
        bytes) of seed material from /dev/random.

        While some safety margin above that minimum is reasonable, as
        a  guard  against  flaws  in  the CPRNG algorithm, no crypto‐
        graphic primitive available today can hope  to  promise  more
        than  256 bits of security, so if any program reads more than
        256 bits (32 bytes) from the kernel random pool  per  invoca‐
        tion,  or  per  reasonable reseed interval (not less than one
        minute), that should be taken as a sign that its cryptography
        is not skilfully implemented.

Anyway, sorry for this long semi-rant which went off on a few tangents, 
but I hope it answers your question of what the experience is like for 
someone new to OpenSSL.


More information about the cryptography mailing list