Search code examples
curlopensslhttp2nghttp2

How to disable Server Key Exchange from the code?


I run an HTTP2 server example (libevent-server.c) from nghttp2 on Ubuntu 15.04. I would like to sniff the HTTP2 packet between the client-server using Wireshark.

I don't use any web browser as the client, so the tips on how to read HTTP2 message in Wireshark explained here is not applicable to my project. I use libcurl.

Since the HTTP2 packet is the application layer inside TLS, Wireshark must know how to decrypt it; hence, I followed the guide from here to supply Wireshark with the key. However the guide warns that, "If the server sends a ServerKeyExchange message, you will not be able to decrypt the data." Unfortunately, my Wireshark shows that the Server Key Exchange was sent by the server.

The following is a snippet of libevent-server.c code:

 SSL_load_error_strings();
 SSL_library_init();
 OpenSSL_add_all_algorithms();
 OPENSSL_config(NULL);

I have recompiled the code after changing OPENSSL_config(NULL) to OPENSSL_no_config() but the Server Key Exchange was still sent.

How can I disable the Server Key Exchange?


Solution

  • As the page you link to explains almost correctly, for Wireshark (or any other passive eavesdropper) to decrypt the SSL/TLS handshake must use plain RSA keyexchange, NOT any of the Diffie-Hellman options (DHE or ECDHE in practice) or "ephemeral" RSA. (The "almost" is that it says "RSA keys have been used to encrypt the data". In fact RSA keyexchange uses the server RSA key to encrypt the premaster secret, which goes through extensive transformation to produce the multiple keys used to encrypt and authenticate the data.)

    In practice DHE or ECDHE are the problem. These ciphersuites provide what is called Perfect Forward Secrecy which means that even if an eavesdropper captures and logs your communications and later compromises the server key they can't use it retroactively decrypt the logged encrypted data. Although these suites have existed and mostly been supported a long time, post-Snowden lots more people (browser and other application and middleware makers, sysadmins, network admins, CISOs and auditors, etc) placed lots more emphasis on using them.

    "Ephemeral RSA" keyexchange is used only for some of the long-obsolete "EXPORT" ciphersuites in SSL/TLS. These were already known to be insecure since about 1995 and most people who care have prohibited using them a long time, or at least prioritizing nonbroken suites over them, although the FREAK researchers a few months ago found something like 5% of (I think a sample of) public servers still supporting them (which enabled their attack to work). Last I checked OpenSSL still enables them by default, but at lowest priority.

    Answer: So you should configure your client (here curl with --ciphers) or your server (call SSL_[CTX_]set_cipher_list) -- or both if you like -- to remove ephemeral suites DEFAULT:!EDH:!EECDH:!EXPORT or directly require "plain" RSA RSA:!EXPORT:!eNULL:!SSLv2.

    Which brings up another option: if you only need to examine traffic between an OpenSSL-based client and server you control, as here, you can use a null-encryption suite. These are designed to be insecure, basically for testing purposes or possibly very severe legal/external restrictions that were seen as imaginable back in the 1990s, and not supported by many implementations; they are supported by OpenSSL but disabled by default, and not enabled even in ALL which you might logically expect to include them. To get them you must explicitly specify eNULL (better eNULL+RSA) or the very counterintuitive COMPLEMENTOFALL. Then you can read the data in Wireshark without decrypting.