I'm limiting the ciphers that my webservice allows to only these TLS 1.x ciphers:
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_IDEA_CBC_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_RC4_128_SHA
Update in response to Dave Thompson's comment:
I now take the ciphers generated from this SO answer, in that order.
Because we currently use Delphi XE2/Indy 10.5.8.0/OpenSSL 1.0.2f I leave out the ECDHE ciphers, these are too cumbersome to implement with these software versions.
Also, we still allow TLS 1.0.
After the update to Delphi Seattle 10 we'll disallow TLS 1.0 and put the ECDHE ciphers back in.
This leaves:
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcc15)
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9f)
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x6b)
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x67)
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (0xc4)
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39)
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33)
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (0x88)
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (0x45)
Converted to OpenSSL names (according to Mapping OpenSSL cipher suite names to RFC names) these are:
DHE-RSA-CHACHA20-POLY1305
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-SHA256
DHE-RSA-AES128-SHA256
- cannot find the equivalent for 0xc4 - anyone? -
DHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA
DHE-RSA-CAMELLIA256-SHA
DHE-RSA-CAMELLIA128-SHA256
The order in which a server offers ciphers is important, but do I have control over this order? The CipherList is a string property containing these names concatenated with '+':
TIdServerIOHandlerSSLOpenSSL.SSLOptions.CipherList := 'DHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SH:DHE-RSA-AES128-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CAMELLIA128-SHA256';
If so, what is the recommended order?
Note that, since my webservice is the server, I have set SSLOptions.Mode := sslmServer
.
* These are the ones that the nmap script ssl-enum-ciphers grades with an 'A'
Is the order of cipher names in
TIdServerIOHandlerSSLOpenSSL.SSLOptions.CipherList
important?
Mostly Yes.
TLS does not specify who decides on the cipher. Conventionally, the server honors the client's preference. That is, the server will use the client's first preference if its available and enabled, or the client's second preference if its available and enabled, and so on.
Most libraries allow a server to override the behavior. For example, with OpenSSL, SSL_OP_CIPHER_SERVER_PREFERENCE
option. In this case, the server will match the server's first preference if the client advertises it, the server's second preference if the client advertises it, and so on.
For servers I control, I tune the cipher suite list and usually set SSL_OP_CIPHER_SERVER_PREFERENCE
because many clients don't pay attention to the details. They just throw the soup of cipher suites in the ClientHello hoping something sticks.
The order in which a server offers ciphers is important, but do I have control over this order?
Yes.
At the server, determine your order of cipher suites, and then set them with SSL_CTX_set_cipher_list
or SSL_set_cipher_list
. By setting the list, you ensure RC4-MD5
is not used even its the client's first choice (presuming you omit it). For maximum impact, also set SSL_OP_CIPHER_SERVER_PREFERENCE
context option.
Also see How do I disable a particular cipher suite in openssl? The context is OpenSSL, but it should give you an idea of where to go in Delphi.
(Comments): What's not clear to me from your answer: Does the CipherList property already signify an order? If I look at the underlying Delphi/Indy code I see that it is just a wrapper for external function
SSL_CTX_set_cipher_list : function(_para1: PSSL_CTX; const str: PAnsiChar): TIdC_INT cdecl = nil; in IdSSLOpenSSLHeaders.pas
If I am understanding Delphi properly, then I believe the answer is Yes, it does. But its probably using either (1) OpenSSL's default list, or (2) a Delphi default list. Both are probably something like "ALL:!EXP:!LOW"
or similar. In either case, you will want to tune it to suite your taste.
If you are interested in what the list looks like when its put on the wire, use Wireshark to inspect the ClientHello. Its easy to generate one with s_client
, and it shows you what OpenSSL's default cipher suite list looks like:
$ openssl s_client -connect www.ietf.org:443 -tls1 -servername www.ietf.org
And the corresponding Wireshark trace with 55 default cipher suites stuffed into it:
You can also improve your security posture and reduce the number of cipher suites with the -cipher
option and "HIGH:!aNULL:!MD5:!RC4"
. The cipher suite count will be reduced to about 35.
$ openssl s_client -connect www.ietf.org:443 -tls1 -servername www.ietf.org \
-cipher 'HIGH:!aNULL:!MD5:!RC4'
If you don't like TripleDES and Cameilla, then you can reduce it to about 20 cipher suites with:
$ openssl s_client -connect www.ietf.org:443 -tls1 -servername www.ietf.org \
-cipher 'HIGH:!aNULL:!MD5:!RC4:!3DES:!CAMELLIA'
Now, suppose a client is configured with only RC4-MD5
and a server is configured with only AES-GCM
. I.e., there's no intersection of cipher suites between client and server. In this case, you will get an error in OpenSSL. The error will be 0x1408A0C1, "no shared cipher suites". It will look something like this at the server:
140339533272744:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1353
For OpenSSL-based clients and server, you can determine the default cipher suite list with the "DEFAULT" string. That's literally what its called (check the ciphers(1)
man page).
There's 103 of them, which includes weak and wounded algorithms. In practice, you want to pair it down to 16 or so cipher suites you feel comfortable using (i.e., your security posture):
$ openssl ciphers -v 'DEFAULT' | cut -f 1 -d " " | wc -l
103
And:
$ openssl ciphers -v 'DEFAULT' | cut -f 1 -d " "
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-SHA384
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
SRP-DSS-AES-256-CBC-SHA
SRP-RSA-AES-256-CBC-SHA
SRP-AES-256-CBC-SHA
DH-DSS-AES256-GCM-SHA384
DHE-DSS-AES256-GCM-SHA384
DH-RSA-AES256-GCM-SHA384
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES256-SHA256
DHE-DSS-AES256-SHA256
DH-RSA-AES256-SHA256
DH-DSS-AES256-SHA256
DHE-RSA-AES256-SHA
DHE-DSS-AES256-SHA
DH-RSA-AES256-SHA
DH-DSS-AES256-SHA
DHE-RSA-CAMELLIA256-SHA
DHE-DSS-CAMELLIA256-SHA
DH-RSA-CAMELLIA256-SHA
DH-DSS-CAMELLIA256-SHA
ECDH-RSA-AES256-GCM-SHA384
ECDH-ECDSA-AES256-GCM-SHA384
ECDH-RSA-AES256-SHA384
ECDH-ECDSA-AES256-SHA384
ECDH-RSA-AES256-SHA
ECDH-ECDSA-AES256-SHA
AES256-GCM-SHA384
AES256-SHA256
AES256-SHA
CAMELLIA256-SHA
PSK-AES256-CBC-SHA
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
SRP-DSS-AES-128-CBC-SHA
SRP-RSA-AES-128-CBC-SHA
SRP-AES-128-CBC-SHA
DH-DSS-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DH-RSA-AES128-GCM-SHA256
DHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES128-SHA256
DHE-DSS-AES128-SHA256
DH-RSA-AES128-SHA256
DH-DSS-AES128-SHA256
DHE-RSA-AES128-SHA
DHE-DSS-AES128-SHA
DH-RSA-AES128-SHA
DH-DSS-AES128-SHA
DHE-RSA-SEED-SHA
DHE-DSS-SEED-SHA
DH-RSA-SEED-SHA
DH-DSS-SEED-SHA
DHE-RSA-CAMELLIA128-SHA
DHE-DSS-CAMELLIA128-SHA
DH-RSA-CAMELLIA128-SHA
DH-DSS-CAMELLIA128-SHA
ECDH-RSA-AES128-GCM-SHA256
ECDH-ECDSA-AES128-GCM-SHA256
ECDH-RSA-AES128-SHA256
ECDH-ECDSA-AES128-SHA256
ECDH-RSA-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES128-GCM-SHA256
AES128-SHA256
AES128-SHA
SEED-SHA
CAMELLIA128-SHA
IDEA-CBC-SHA
PSK-AES128-CBC-SHA
ECDHE-RSA-RC4-SHA
ECDHE-ECDSA-RC4-SHA
ECDH-RSA-RC4-SHA
ECDH-ECDSA-RC4-SHA
RC4-SHA
RC4-MD5
PSK-RC4-SHA
ECDHE-RSA-DES-CBC3-SHA
ECDHE-ECDSA-DES-CBC3-SHA
SRP-DSS-3DES-EDE-CBC-SHA
SRP-RSA-3DES-EDE-CBC-SHA
SRP-3DES-EDE-CBC-SHA
EDH-RSA-DES-CBC3-SHA
EDH-DSS-DES-CBC3-SHA
DH-RSA-DES-CBC3-SHA
DH-DSS-DES-CBC3-SHA
ECDH-RSA-DES-CBC3-SHA
ECDH-ECDSA-DES-CBC3-SHA
DES-CBC3-SHA
PSK-3DES-EDE-CBC-SHA
EDH-RSA-DES-CBC-SHA
EDH-DSS-DES-CBC-SHA
DH-RSA-DES-CBC-SHA
DH-DSS-DES-CBC-SHA
DES-CBC-SHA
Meta: not an answer to the question but response to comment. To 'really understand' SSL/TLS isn't really programming and is a big question that may be 'too broad' for SO. But some thoughts anyway:
The definitive guide to SSL/TLS as a standardized protocol, or really family of them, is of course the RFCs that define them, plus where applicable the external standards referenced by those RFCs (like FIPS 197 for AES, PKCS#1 for RSA, SECG1 for ECC, etc). Wikipedia has a good overview and (AFAICT) complete list of references.
If you just want a general understanding of what the pieces are and how they work (like RSA vs DHE vs ECDHE, and AES vs TDES or HMAC vs AEAD) Wikipedia is also good, and so is the canonical Q&As on security.SE
A middle gound might be Ivan Ristic's new 'Bulletproof' book; he's the guy behind the widely-used and well-regarded SSLLabs test and the book is linked from that homepage. I haven't read the actual book, but a few years ago he showed and discussed on his blog some of the material planned to go in the book and I thought that looked excellent.
Also, you are not implementing the standard directly; you are using an implementation that is a version of OpenSSL, and in today's software ecosystem OpenSSL can vary. First OpenSSL itself has a number of build (aka compile-time) options. And I know of Delphi only in outline and I don't know if the OpenSSL version you identify is provided with or for Delphi (or Indy?) or 'pulled in' from the OS or elsewhere, and in any case who built it with what options and possibly even modifications (patches). (For comparison, I commonly use RedHat-based and Debian-based Linuxes that backport patches so that a package identified as for example '1.0.1e' is usually different, sometimes significantly so, from other versions that are also identified as '1.0.1e'.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With