Abstract

You’re probably running a TLS configuration that the IETF says is “non-conformant”. But you didn’t do anything wrong.

In July, the IETF published a pair of RFCs that took away three of TLS 1.2’s key exchange methods and froze the rest of it. The phrase they used is MUST NOT, the strongest thing a specification is allowed to say. Nginx, Apache, and Windows Server all ship with those key exchanges turned on by default.

Nothing breaks tomorrow. But the list of things TLS 1.2 is allowed to do got shorter this summer, and it’s worth ten minutes to find out which side of the line you’re on.

What TLS 1.2 is, and what a key exchange is

TLS is the protocol behind the S in HTTPS. It makes a connection private and proves the server on the other end is the one you asked for. It’s also what your “SSL certificates” have really been doing ever since SSL was renamed TLS in 1999.

Before your browser and a server can trade encrypted data, they have to agree on a secret key. Getting that key to both ends, over a wire that the bad guys can record, is the key exchange. It happens in the TLS handshake at the very start of every connection.

The encryption in TLS 1.2 is still okay. The key exchange is what the IETF changed in July, because an attacker who can walk away with the key never has to break the encryption at all.

What the IETF changed in July

Two RFCs, published a day apart.

RFC 9851, “TLS 1.2 is in Feature Freeze,” published July 15 by Rich Salz and Nimrod Aviram. TLS 1.2 gets no new features, ever. The only changes that will be approved are urgent security fixes, new TLS exporter labels, and new ALPN protocol IDs. Everything else, including all post-quantum work, goes to TLS 1.3 and later versions exclusively. This one covers TLS only. DTLS, the UDP version, is explicitly out of scope.

RFC 10015, “Deprecating Obsolete Key Exchange Methods in TLS 1.2 and DTLS 1.2,” published July 16 by Nimrod Aviram. It’s a Proposed Standard and it updates 17 other RFCs, including the current best-practice document for running TLS. This is the one that reaches your configuration, and it comes after two things: the RSA key exchange, and most of the Diffie-Hellman family.

Nothing about this breaks your site today. No browser has announced a change. What it does is move these cipher suites from “old but permitted” to “using this makes you non-conformant,” which is the state a thing sits in for a few years right before vendors start removing it.

You MUST-NOT use the RSA key exchange

The RSA key exchange is how encryption worked before perfect forward secrecy, and it’s still the way most people picture it working. Your browser picks a secret, locks it with the server’s public key from its certificate, and sends it over. The server unlocks it with its private key, and both sides now share a secret.

The flaw is that the locked secret crosses the network, where anyone can record it and keep it. If that server’s private key ever leaks, five years from now, in a breach or a backup or a court order, every recorded conversation unlocks at once. Daniel Bleichenbacher found a practical attack on it in 1998. Nineteen years later, ROBOT showed the same attack still worked against Facebook and PayPal, because implementing the countermeasure correctly turned out to be very hard.

RFC 10015 ends the argument. Clients MUST NOT offer RSA cipher suites, and servers MUST NOT select them.

This is RSA the key exchange, not RSA the certificate. An RSA certificate is still fine, and so is an RSA signature. The name covers several unrelated things and only one of them just got banned.

Removing weak Diffie-Hellman

Diffie-Hellman fixes the problem RSA key exchange has. Both sides contribute a piece, the shared secret gets computed instead of transmitted, and nothing crossing the wire can be unlocked later. That’s the good idea. The trouble is the version TLS 1.2 shipped with.

Finite-field Diffie-Hellman, FFDH in its static form and FFDHE in its ephemeral one, aged poorly. TLS 1.2 doesn’t give a real way to agree on which parameters to use, so operators got stuck on 1024-bit primes that everybody shares. Logjam showed in 2015 that sharing primes lets an attacker do the expensive math once and then reuse it against everyone, and that connections could be pushed down to the deliberately weak parameters left over from 1990s export rules. The Raccoon attack added a timing side channel in 2020 against servers that reuse secrets instead of generating fresh ones.

Both forms are now MUST NOT, static and ephemeral alike. Two related things get the softer SHOULD NOT, meaning you had better have a good reason: static elliptic-curve Diffie-Hellman, and certificates that carry a fixed Diffie-Hellman key.

Ephemeral elliptic-curve Diffie-Hellman, the ECDHE you see in most modern cipher suite names, is untouched. That’s the one you’re supposed to be using.

Can I still use TLS 1.2?

Yes. TLS 1.2 with an ECDHE key exchange and a modern cipher is still secure, and RFC 10015 doesn’t say otherwise. But you do need to make sure the newly banned key exchanges aren’t allowed in your configuration.

These aren’t exotic settings somebody had to go turn on. They’re in the defaults. Nginx ships with a cipher list that pulls in dozens of finite-field Diffie-Hellman suites and a pile of RSA key exchange ones. Apache’s default does the same on a smaller scale. Windows Server 2022 enables TLS_RSA_WITH_AES_256_GCM_SHA384 and a pair of DHE suites out of the box.

I ran SSL Labs against our own site while writing this, expecting to use it as the clean example.

SSL Labs summary for www.certkit.io showing an overall rating of A

Grade A. Then I checked the cipher suites.

SSL Labs cipher suite list for www.certkit.io, showing three TLS_RSA suites under TLS 1.2

Three of the nine TLS 1.2 suites we offer start with TLS_RSA_. That’s the RSA key exchange, the one RFC 10015 says a server MUST NOT select. Our public website is non-conformant. (The CertKit app is great though.)

The fix is configuring your cipher list. For nginx:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;

For Apache:

SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off

For IIS, it’s the registry or a tool like IIS Crypto. Because Windows.

That’s the whole fix. No certificates to reissue, no new keys, no change to anything your CA does. A cipher list and a reload.

So when is TLS 1.2 end of life?

There’s no date, and there probably won’t be one. Setting one means owning the outage it causes, and no vendor or standards body wants that bill. What you get instead is subtraction, one capability at a time, until what’s left is TLS 1.3’s design with a much bigger pile of code behind it. TLS 1.0 was formally deprecated in 2021 and I still find it answering on production hosts. TLS 1.2 will go the same way, slowly, with no announcement, and one day you’ll notice a scanner flagging something that used to be fine.


CertKit is certificate lifecycle management for teams who want to know what they’re running.

Keep reading