Netfuture/tlsinterposer

Does not enable DHE for unaware applications

Closed this issue · 8 comments

Thanks for your work on tlsinterposer and the helpful articles about implementing it with several applications.

In using tlsinterposer with ejabberd and a client that does not send any ECDHE ciphers but a few DHE ciphers (Pidgin), I think I have found a few problems. Adding tlsinterposer with default cipher settings changed the chosen ciphersuite from TLS_RSA_WITH_AES_256_CBC_SHA to TLS_RSA_WITH_RC4_128_SHA. This seems like a weaker one, right? Is it? If so, maybe the default list should be adjusted -- or perhaps it would be fixed by the below.

I think I figured out why it doesn't choose DHE even though both client and server include it in their cipher lists -- ejabberd apparently doesn't set any DH parameters. I was able to get a DHE cipher by adding
SSL_CTX_set_tmp_dh_callback(ctx, NULL);
in tlsinterposer's SSL_CTX_new() (passing null because the actual value is overridden by tlsinterposer.) I am not sure if this is good in general -- for example, how does it interact if the application calls SSL_CTX_set_tmp_dh()? What is the purpose of the DH params stuff added by #3 -- just to ensure there are some DH params available (apparently doesn't work, if the application never sets DH params), or to ensure certain secure params are used?

I did a complete refactoring and it seems to work at least for ejabberd. Can you try with v1.2.0 again?

I've just tried v1.2.1 and it works. Thanks!

I found a small issue with the log timestamp though, and sent a pull request that fixed it for me.

I may have spoken too soon. After applying the update to my Courier-IMAP server, I found that the chosen cipher was downgraded to DHE-RSA-AES256-SHA instead of ECDHE-RSA-AES256-SHA, which it had been before. So, the DHE issue for ejabberd was fixed but there is a new ECDHE issue for Courier-IMAP.

I used git-bisect to narrow the change down to d81129e, the refactoring commit. I don't fully understand it, but I think the problem is the (interposer_opt_clr & SSL_OP_SINGLE_DH_USE) != 0 conditional in the overridden SSL_CTX_new. It looks inverted to me. I changed it to (interposer_opt_set & SSL_OP_SINGLE_DH_USE) != 0 ("set" instead of "clr") and ECDHE started working again in Courier-IMAP. I think (interposer_opt_clr & SSL_OP_SINGLE_DH_USE) != SSL_OP_SINGLE_DH_USE would also work, but I haven't tested.

I chose this after reasoning through the tlsinterposer code for the -ecdhe option, but I don't understand why SSL_OP_SINGLE_DH_USE is being used this way. The OpenSSL documentation says "The server will always generate a new DH key during the negotiation, when the DH parameters are supplied via callback and/or when the SSL_OP_SINGLE_DH_USE option of SSL_CTX_set_options(3) is set." Since we set a callback in our SSL_CTX_new this option is apparently redundant (unless the target application manages to clear the callback.) Also, it does not seem to apply to ECDH parameters -- there is a SSL_OP_SINGLE_ECDH_USE in <openssl/ssl.h> that applies to ECDH, so I don't understand why it's being used to determine ECDHE behavior.

I'm certainly not an expert, so am I missing something? There could be some interaction between application code and SSL_OP_SINGLE_DH_USE that I am not thinking about.

It's hard to find documentation on SSL_OP_SINGLE_ECDH_USE, but I found this paper that describes OpenSSL's default behavior as an optimized but less-secure "ephemeral-static ECDH", and says that "the key pair is ephemeral for each application instance and not (necessarily) per
handshake instance" without the option, and this code from Dovecot that says it improves forward secrecy.

It looks like we should always enable both the DH and ECDH single-use options for greater security. Maybe we can omit the DH one if it is implied by setting a callback. What do you think? Thanks.

Thanks for reading the documentation. I was under the (apparently false) impression that SSL_OP_SINGLE_DH_USE was related to ECDHE. So yes, indeed, the application code does not make sense. With the inverted condition, Courier IMAP does again connect with ECDHE?

Can you try 3de153b?

I just tried with d56b9c9 (current master) and it works.

Have you considered adding SSL_OP_SINGLE_ECDH_USE as a sticky option? Enabling the option causes a new ECDH keypair to be generated per connection, rather than a static one per context. This paper shows how omitting the option can lead to key recovery by an attacker, given the existence of another bug (that has been fixed now.) I am not sure how critical it is now, or what the cost is. nginx uses it, so I guess it doesn't degrade performance too much. I just tested on my own system and the connection works, so I will probably leave it on.

Also, would you like some test cases? I am thinking of writing a simple test server in C, and running it with various options in a script to make sure they behave as expected.

The paper sounds pretty scary, almost like another Heartbleed problem. I'm considering adding it as the default with an option to revert to per-context ECDHE. What do you think?

A test case would be greatly appreciated, at least for the basic testing. Some weirder things like interactions with ejabberd are hard to test, though. If you have a test case, could you make a pull request for the patch? Thanks!

Yeah, I think SSL_OP_SINGLE_ECDH_USE should be enabled by default, and a tlsinterposer flag to disable it might be nice too (although I probably wouldn't use it personally.)

By the way, I don't know if you know this, but I've just found how to test ejabberd: with a command like openssl s_client -connect chat.facebook.com:5222 -starttls xmpp. This does the TLS transition through the XMPP protocol before the normal TLS handshake. I was looking at the starttls flag earlier, but the xmpp option is not documented in my man page. From searching around online, I see that it's apparently a bit fragile (mine goes into an infinite waiting loop if I give the wrong hostname, which causes the server to return an XML error that the openssl utility doesn't parse correctly), but anyway it works well enough for my server.

I thought about adding this functionality to OpenSSL and thereby found the code as well. Seems to be little known…

Single use: I agree. Will add code for that in the next few days.

Am 09.07.2014 um 21:11 schrieb Joey Hewitt notifications@github.com:

Yeah, I think SSL_OP_SINGLE_ECDH_USE should be enabled by default, and a tlsinterposer flag to disable it might be nice too (although I probably wouldn't use it personally.)

By the way, I don't know if you know this, but I've just found how to test ejabberd: with a command like openssl s_client -connect chat.facebook.com:5222 -starttls xmpp. This does the TLS transition through the XMPP protocol before the normal TLS handshake. I was looking at the starttls flag earlier, but the xmpp option is not documented in my man page. From searching around online, I see that it's apparently a bit fragile (mine goes into an infinite waiting loop if I give the wrong hostname, which causes the server to return an XML error that the openssl utility doesn't parse correctly), but anyway it works well enough for my server.


Reply to this email directly or view it on GitHub.