How to disable Server Key Exchange from the code? How to disable Server Key Exchange from the code? curl curl

How to disable Server Key Exchange from the code?


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.


If your goal is to read decrypted application data from your OpenSSL application in Wireshark, do note that RSA private keys are not your only option, you can also pass a mapping to the (pre-)master secret. This functionality is not limited to SSL clients even though the use of SSLKEYLOGFILE is commonly found for those applications using NSS.

For a method to retrieve the pre-master key from OpenSSL client and server applications, see this Sec.SE post (does not require application changes). If you would like to embed such debugging functionality in your application, then you can do it more cleanly by setting a callback when the handshake completes. Example:

// converts bytes to hexvoid to_hex(unsigned char *dst, unsigned char *src, size_t len) {  unsigned char hex[] = "0123456789abcdef";  unsigned i;  for (i = 0; i < len; i++) {    unsigned char c = src[i];    *dst++ = hex[c >> 4];    *dst++ = hex[c & 0xf];  }  *dst = '\0';}static FILE *ssl_keylog;void info_callback(const SSL *ssl, int where, int ret) {  unsigned char rnd[SSL3_RANDOM_SIZE*2+1];  unsigned char pmk[SSL_MAX_MASTER_KEY_LENGTH*2+1];  // skip in case the session is invalid, or if it is not  // a Handshake Done notification.  if (!ssl || !ssl->session || !ssl->s3 || !(where & SSL_CB_HANDSHAKE_DONE)) {     return;  }  // convert bytes to hex  to_hex(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);  to_hex(pmk, ssl->session->master_key, ssl->session->master_key_length);  // write to SSL keylog file  fprintf(keylog_file, "CLIENT_RANDOM %s %s\n", rnd, pmk);}static void run(const char *service, const char *key_file,                const char *cert_file) {  SSL_CTX *ssl_ctx;  ...  ssl_ctx = create_ssl_ctx(key_file, cert_file);  if (!keylog_file) {    // open key log file if any.    keylog_file = fopen("premaster.txt", "a");  }  // register callback (for SSL objects, use SSL_set_info_callback instead)  SSL_CTX_set_info_callback(ssl_ctx, info_callback);  ...}


I would like to sniff the HTTP2 packet between the client-server using Wireshark.

For that, you usually refer to Wireshark and TLS on the Wireshark Wiki.


my Wireshark shows that the Server Key Exchange was sent by the server.

I believe the Serer Key Exchange message is always sent. I think about the best you will be able to do is suppress the Server Certificate message in the Server Hello. Do that by enabling only anonymous protocols. The anonymous protocols forgo server authentication, and will allow you to intercept the traffic.

I believe the cipher string you are looking for is "ADH:AECDH" or "aNULL" (usually, you explicitly state "!aNULL"). It needs to be available at both the client and the server. Finally, you can get of list of tokens at ciphers(3) OpenSSL man page.

Most clients categorically reject anonymous protocols, so it might be hard to actually get into that configuration (and have everything work).