TLS handshake is the first step in the process of establishing a secure TLS connection between a client and server. During a TLS handshake, both client and server exchange several parameters that would help each of them to ultimately establish a session key which is later used for symmetric encryption. If the cipher suite that is agreed upon by the client and server uses Diffie-Hellman key exchange algorithm, then during handshake, client and server also exchange additional parameters needed for the key exchange algorithm, commonly referred to as DH parameters. For a quick refresh on TLS handshake, see what-happens-in-a-tls-handshake
The motivation is to potentially prevent security breaches that might occur if the server is using DH key lengths that are considered insecure. In this post, we will examine how to to go about verifying what key length the TLS server is setup to use for DH parameters and how to tweak it if necessary.
Specifically, we will examine how to:
- list ciphers supported by the server
- determine the key length used by the server for DH parameters
- update DH parameters used by the server
List ciphers supported by the server
To list all ciphers the server supports, we could list all ciphers supported by OpenSSL and test each one against the server to check if it is supported.
List all ciphers supported by OpenSSL
openssl ciphers -v 'ALL:eNULL'
Check if a particular cipher is supported by the server using the s_client
command
openssl s_client -connect <server>:<port> -cipher <cipher>
where <server>
is the IP address or host name of the server, <port>
is the port at which the TLS server is running, and <cipher>
is the name of the cipher to test, returned from running the previous command.
It is also important to specify the desired TLS version to check against, e.g. -tlsv1_2
, to be sure and explicit about the TLS version being used for tests.
Alternatively, to list all ciphers supported by server, use nmap
nmap --script ssl-enum-ciphers -p
Determine the key length used by the server for DH parameters
We could again use s_client
command and look for a specific pattern that indicates the DH parameters being used.
openssl s_client -starttls smtp -crlf -connect <server>:<port> -cipher -tls1_2 2>/dev/null | grep "Server Temp Key"
where <server>
is the IP address or host name of the server and <port>
is the port at which the TLS server is running. The above command assumes the TLS server is a SMTP server and may need to be tweaked for other types of servers.
Here is a sample output from a SMTP server
openssl s_client -starttls smtp -crlf -connect 127.0.0.1:25 -cipher "DHE-RSA-AES128-SHA256" -tls1_2 2>/dev/null | grep "Server Temp Key" Server Temp Key: DH, 1024 bits
Notice the phrase DH
. The value that follows is the key length server used for DH parameters.
If the specified cipher does not use Diffie-Hellman key exchange, and hence does not need DH parameters during key exchange, then the phrase DH
would be missing from the output of this command.
openssl s_client -starttls smtp -crlf -connect 127.0.0.1:25 -cipher "ECDHE" -tls1_2 2>/dev/null | grep "Server Temp Key" Server Temp Key: X25519, 253 bits
Update DH parameters used by the server
To update DH parameters, look for language or framework support. For example, in Java it could be done through jdk.tls.ephemeralDHKeySize
system property, and in NodeJS it could be done through tls.connect
options.
If OpenSSL libraries are used, we have full flexibility, both to choose the key length and also the actual DH keys.
OpenSSL provides the dhparam
command to generate the DH keys.
openssl dhparam -C -2 -noout 4096
Integrate the generated code with OpenSSL’s SSL_CTX_set_tmp_dh or SSL_CTX_set_tmp_dh_callback. Note however that these two methods are set to be deprecated in OpenSSL 3.x where it is poised to become much more simpler by not having to setup any DH parameters explicitly.
Conclusion
If you are not able to tweak the DH parameters, a workaround is to use TLS 1.3 if that is feasible. In TLS 1.3, DH parameters are not user-defined so none of this is a concern. Another workaround is to force the connection, either through the client or server, to use a cipher that does not require Diffie-Hellman key exchange. Nevertheless the above approaches are good to have in the security toolbox of an application developer until TLS 1.3 becomes mainstream.
Happy secure coding!