How should I proceed with upgrading to TLS 1.2?
To meet the technical requirements, its sufficient to use either OpenSSL 1.0.1 or 1.0.2. Both provide TLS 1.2, and both trivially provide SHA-256. (There are other hidden fulfillments, like OpenSSL 1.0.0 does not provide the full compliment of EC gear and the full compliment of TLS 1.2 cipher suites, but 1.0.1 and 1.0.2 does).
In your C-Code that uses OpenSSL, all you need to do for the SSL Context or Session:
/* Useless return value ??? */
SSL_library_init();
const SSL_METHOD* method = SSLv23_method();
if(NULL == method) handleFailure();
SSL_CTX* ctx = SSL_CTX_new(method);
if(ctx == NULL) handleFailure();
/* Cannot fail ??? */
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | \
SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
For Apache-like server configurations, use something like the following (mine includes +TLSv1 +TLSv1.1
):
# From my CentOS production server
SSLProtocol -all +TLSv1.2
You should probably tend to cipher suites, too. For that, in C-code:
const char CIHPHER_LIST[] = "HIGH:!aNULL:!RC4:!MD5"
/* Ensure at least one cipher suite is added, which indicates non-failure */
int rc = SSL_CTX_set_cipher_list(ctx, CIHPHER_LIST);
if(!(rc >= 1)) handleFailure();
And in an Apache-like configuration file:
# From my CentOS production server
SSLCipherSuite HIGH:!aNULL:!MD5:!RC4
If you want to avoid RSA key transport (TLS 1.3 is removing it), then:
SSLCipherSuite HIGH:!aNULL:!MD5:!RC4:!kRSA
When you remove RSA key transport, you are pretty much left with ephemeral key exchange protocols (modulo cipher suites like PSK and SRP).
If you want to explicitly use ephemeral key exchanges, then you will need something like kEECDH:kECDHE:kDHE:kEDH:!aNULL
. See openssl ciphers(1)
man page for more details.
I'm reading between the lines, but the TLS 1.2 requirement probably has something to do with authenticated encryption, and modes of operation like GCM. For that, use openssl ciphers(1)
again:
$ openssl ciphers -v 'HIGH:!aNULL' | grep GCM
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
DHE-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
AES256-GCM-SHA384 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
DHE-DSS-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD
ECDH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
AES128-GCM-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD
Or:
$ openssl ciphers -v 'HIGH:!aNULL' | grep GCM | grep -v "Kx=RSA" | cut -d " " -f 1
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-GCM-SHA384
DHE-DSS-AES256-GCM-SHA384
DHE-RSA-AES256-GCM-SHA384
ECDH-RSA-AES256-GCM-SHA384
ECDH-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES128-GCM-SHA256
ECDH-RSA-AES128-GCM-SHA256
ECDH-ECDSA-AES128-GCM-SHA256
Instead of specifying HIGH:!aNULL:!MD5:!RC4:!kRSA
, you can do the following:
const char CIPHER_LIST[] =
"ECDHE-RSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"DHE-DSS-AES256-GCM-SHA384:"
"DHE-RSA-AES256-GCM-SHA384:"
"ECDH-RSA-AES256-GCM-SHA384:"
"ECDH-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES128-GCM-SHA256:"
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"DHE-DSS-AES128-GCM-SHA256:"
"DHE-RSA-AES128-GCM-SHA256:"
"ECDH-RSA-AES128-GCM-SHA256:"
"ECDH-ECDSA-AES128-GCM-SHA256:"
/* Ensure at least one cipher suite is added, which indicates non-failure */
int rc = SSL_CTX_set_cipher_list(ctx, CIPHER_LIST);
if(!(rc >= 1)) handleFailure();
If you look at the AES256-GCM-SHA384
cipher suite, you'll see uses key transport (Kx=RSA
), so you may want to avoid it even though its TLS 1.2. Hece the reason for the grep -v
on it.
For completeness, Au=RSA
is fine. It just means the server uses its RSA key for signing only. And in practice, Au=DSS
is rarely used, so OpenSSL will remove the cipher suite if there's no DSS key.
Now, the hardship is probably getting a distro that provides the latest OpenSSL 1.0.2 and provides the long term support. My CentOS machines don't provide it, so I have to build it from sources, and then rebuild every library or program that depends upon OpenSSL while playing those stupid r-path
games.
In your case, that looks like Apache, PHP, Drupal, MySQL, phpAdmin (does anyone really use that when security is a concern :) and friends.