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
--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users