[openssl-users] Authentication over ECDHE

Jakob Bohm jb-openssl at wisemo.com
Sat Dec 29 15:53:25 UTC 2018


On 29/12/2018 14:19, C.Wehrmeyer wrote:
> I don't have access to the actual testing environments until Wednesday 
> next year, so I've had to create a private account.
>
> > Which version of OpenSSL is this? (I don't remember if you said this
> > already).
>
> I'm not entirely sure, but I *think* it's 1.1.0.
>
> =====================================================================
>
> OK, so I've been reading the mails before going to sleep and spent 
> some time thinking and researching about this, and I've come to a 
> conclusion: OpenSSL is a goddamn mess, SSL_clear() is pretty much 
> superfluous, and as such shouldn't exist.
>
> Why? Well, to quote Viktor here:
>
> > DO NOT reuse the same SSL handle for multiple connections,
>
> And that is fricking bullshit. Not the quote itself or the suggestion 
> - it's unlikely you had anything to do with the actual code - but the 
> way things have been thought through (or rather, have not been thought 
> through) by the library devs. I've written highly scalable libraries 
> in the past before, and one thing you always want to do there is to 
> trim fat. And "object allocation and initialisation" is something that 
> you very much want to trim fat of, not only for obvious reasons such 
> as malloc() and free() (or whatever OpenSSL uses as wrappers) being 
> complexity monsters, but also for cache reasons (loading different 
> cache line hurts performance). That's why you usually have functions 
> like XXX_clear() or XXX_reset(), which do exactly that - prepare an 
> object for another usage. memset() (or the OpenSSL equivalent of a 
> secure memset) your allocated resources. I don't really see the 
> problem here.
>
> Now add to that the fact that OpenSSL has been moving towards making 
> its structures opaque, thus falling into the same trap that Microsoft 
> has with COM and DirectX, and you can kind of see why, if you can't 
> really determine anymore WHERE your object is going to be stored, you 
> at least want to keep reusing it. This is not PHP, where people 
> allocate memory all willy-nilly, or C++, where people don't even have 
> shame anymore to use std::vector<std::strings> str_array instead of 
> good old static const char*const str_array[] while expecting things to 
> be made faster by invisible memory pools (and horribly failing at it), 
> but C, where you want to think about each step quite carefully.
>
> Then OpenSSL even provides an SSL_clear function which is advertised 
> like this:
>
> > SSL_clear - reset SSL object to allow another connection
>
> , and then, only later, in a big warning block, decides to tell the 
> reader that this function only works when the stars align quite 
> correctly and you've sacrificed at least two virgins, because:
>
> > The reset operation however keeps several settings of the last
> > sessions
>
> Then, as the documentation suggests, I read the entry for 
> SSL_get_session:
>
> > The ssl session contains all information required to re-establish the
> > connection without a full handshake for SSL versions up to and
> > including TLSv1.2. In TLSv1.3 the same is true, but sessions are
> > established after the main handshake has occurred.
>
> And at this point it all falls apart. From my understanding OpenSSL 
> keeps a session cache for servers so that key exchanges and protocol 
> handshakes can be avoided. Problem is, *we're using ECDHE, where the 
> last E stands for "ephemeral"*. In simple English: throw away the keys 
> after you're done, we want to have forward secrecy. And then OpenSSL 
> keeps a fresh copy of those for everyone who happened to be logged on 
> at this point. Heartbleed apparently wasn't enough of a warning. Oh, 
> but lets move everything to the heap so that it's more secure there now.
>
> I don't want to reuse a session with ephemeral keys; I want to reuse 
> an object that is supposed to already have resources allocated for 
> doing its job, as is indicated by the documentation of this function 
> except for a small note at the end that tells you that the devs didn't 
> really think about what "ephemeral" means.
>
The session caching in the SSL and TLS protocols is to skip the
expensive key exchange when reconnecting within a few seconds,
as is extremely common with web browsers opening up to 8 parallel
connections to each server.

There is hopefully a configuration option to tell the OpenSSL server
end SSL_CTX to not do this, just as there should (for multi-process
web servers) be an option to hand the state storage over to the web
server application for inter-process sharing in whatever the web
server application (and its configuration) deems secure.

> Creating a new SSL object (EVEN FROM AN EXISTING SSL_CTX object) entails:
>
> - allocating the memory for the object itself on the heap (via 
> OPENSSL_zalloc)
> - creating and managing a new lock for the object, and who knows for 
> much more subobjects
> - creating a duplicate of the cipher suite stack (which isn't even a 
> flat copy, but something that can cause the code to call 
> OPENSSL_malloc *twice* in the worst case)
> - creating a duplicate of the certificates (which I don't even use, 
> but that doesn't stop the code of ssl_cert_dup() to call 
> OPENSSL_zalloc *in its very first line!*)
> - setting up a bunch of callbacks
> - copying 32 bytes for a sid_ctx
> - creating an X509_VERIFY_PARAM object (*which calls OPENSSL_zalloc 
> again*) as well as creating a deep copy of the SSL_CTX's parameter via 
> X509_VERIFY_PARAM_inherit(), with Thor knows how many copies hidden in 
> all those *set* and *deep_copy* routines
> - copying EC point formats from the context - deep again, of course, 
> at least that's what OPENSSL_memdup() makes me think
> - copying supported group informations, and of course deep again!
> - deep-copying an ALPN object
> - SSL_clear()-ing the object (no, really!)
> - deep-copying a CRYPTO_EX_DATA object via CRYPTO_new_ex_data ... at 
> this point, is anyone surprised here that timing attacks against 
> crypto are *still* so successful? Because I'm not. Not at all.
>
> I didn't bother looking up what freeing entails - it's obvious to 
> anyone at this point that OpenSSL is a severe victim of feature creep, 
> that its memory allocation scheme is a mess, and long story short: I 
> will NOT free a perfectly fine object just because of incompetent 
> devs' chutzpah expecting their users to allocate memory dynamically en 
> mass for no goddamn reason whenever a new connection comes in. Fix 
> your goddamn code.
>
> And don't give me any "trust us, we're experienced programmers" 
> bullshit. I've *seen* ssl/record/ssl3_record.c:
>
> > static const unsigned char ssl3_pad_1[48] = {
> >     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
> >     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
> >     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
> >     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
> >     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
> >     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
> > };
> > static const unsigned char ssl3_pad_2[48] = {
> >     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
> >     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
> >     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
> >     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
> >     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
> >     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
> > };
>
> What's wrong with that, you ask? Let me show you how I'd have done that:
>
> > static const unsigned char ssl3_pad_1[] =
> > {
> >     "66666666"
> >     "66666666"
> >     "66666666"
> >     "66666666"
> >     "66666666"
> >     "66666666"
> > };
> >
> > static const unsigned char*ssl3_pad_2[] =
> > {
> >     "\\\\\\\\\\\\\\\\"
> >     "\\\\\\\\\\\\\\\\"
> >     "\\\\\\\\\\\\\\\\"
> >     "\\\\\\\\\\\\\\\\"
> >     "\\\\\\\\\\\\\\\\"
> >     "\\\\\\\\\\\\\\\\"
> > };
>
> So, no. I don't trust anyone. Especially not this mess of a code.

Well, these two latter arrays look like a stray copy of the HMAC
constants "ipad" and "opad", which (while looking like ASCII), are
defined as exact hex constants even on a non-ASCII machine, such
as PDP-11 or an IBM mainframe.

I wonder if those constants are actually still used somewhere in
the SSL3 code, or if they have been properly replaced by calls to
the HMAC implementation in libcrypto.

Enjoy

Jakob
-- 
Jakob Bohm, CIO, Partner, WiseMo A/S.  https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark.  Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded



More information about the openssl-users mailing list