One year of FIPS 203
NIST finalised FIPS 203 — Module-Lattice-Based Key Encapsulation Mechanism, better known as ML-KEM — in August 2024. The standard derives from CRYSTALS-Kyber and replaces classical Diffie-Hellman in any handshake that needs to resist a future quantum adversary harvesting today. Twelve months on, the rollout story is no longer “is the algorithm ready” — it is “is your cryptographic module validated against it, and what changes if not.”
The validation cliff
If your stack lives inside a regulated environment — RBI-regulated banks, SEBI-regulated brokers, SDF-class SaaS under DPDP, anything procured by the Government of India — your cryptographic primitives almost certainly need to come from a FIPS 140-3 validated module. Until ML-KEM lands inside such a module, you cannot legally use it for the controls it was designed for, regardless of how good the open-source implementation is.
The Cryptographic Module Validation Programme (CMVP) queue, last we checked, has 80+ modules in the IUT (Implementation Under Test) state with ML-KEM in scope. The headline implementations — OpenSSL 3.5, BoringSSL, AWS-LC, wolfSSL — have all submitted. Validated revisions land at a rate of about 6-8 per month. Pragmatic estimate: by Q4 2026 every mainstream crypto module in your stack will have an ML-KEM-validated build available. The window from validation to your operating-system vendor packaging it is another 3-6 months.
The hybrid is the answer, not ML-KEM alone
| Mode | What it gives you | Posture |
|---|---|---|
| Classical only (e.g. x25519) | Today’s security; vulnerable to harvest-now-decrypt-later | Acceptable only for short-lived secrets |
| Hybrid (X25519MLKEM768) | Both classical and PQ; secure if either survives | Recommended for new deployments through ~2030 |
| Pure PQ (ML-KEM alone) | PQ resistance, no defence if ML-KEM is broken cryptanalytically | Premature — wait for >3 years of community vetting |
Pure-ML-KEM deployments are still risky for the same reason switching to any one new primitive is — if a structural break is found in lattice problems over the next decade, you are unprotected. Hybrid kex composes ML-KEM with a classical primitive so a break in either still leaves the session secure. This is what TLS 1.3’s X25519MLKEM768 codepoint and OpenSSH 9.9+’s default kex algorithm both do.
Test it yourself in 10 minutes
OpenSSL 3.5 ships ML-KEM support without provider plumbing. On a system with the binary installed (or in a fresh Docker container — docker run -it openssl/openssl:3.5), the following walkthrough shows you what a hybrid handshake looks like end to end.
# Generate a server cert
openssl req -x509 -newkey ec:<(openssl ecparam -name prime256v1) \
-keyout key.pem -out cert.pem -days 30 -nodes -subj "/CN=localhost"
# Start a server that prefers the hybrid kex
openssl s_server -accept 4433 -cert cert.pem -key key.pem \
-groups X25519MLKEM768:x25519 -tls1_3 -www &
# Connect; capture the negotiated kex
openssl s_client -connect localhost:4433 \
-groups X25519MLKEM768:x25519 -tls1_3 2>/dev/null \
| grep -E "Server Temp Key|Cipher"
# Server Temp Key: X25519MLKEM768, 1216 bits
# New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
The 1216-bit “temp key” size is the giveaway: a classical x25519 handshake would report 253 bits. The hybrid mode concatenates the two shared secrets, then runs them through HKDF to derive the actual session keys. The wire format adds about 1.2 KB to the TLS ServerHello compared to a classical x25519 handshake — measurable but not material for any session that lives longer than the handshake itself.
To see it on the wire, run tcpdump -w /tmp/tls.pcap port 4433 in another shell while the s_client runs, then open in Wireshark. The Key Share extension in the ClientHello will list group 0x11ec (X25519MLKEM768) and 0x001d (x25519). The ServerHello picks one and echoes back its public key. The new key shares are noticeably larger than the classical ones — roughly 1200 bytes vs 32.
Where the standard is silent
FIPS 203 covers key encapsulation. It does not cover signatures — that is FIPS 204 (ML-DSA, from Dilithium) and FIPS 205 (SLH-DSA, from SPHINCS+). The signature story is materially harder because PKI hierarchies live for decades and re-issuing certificates across an estate is a slow operation. Most Indian CAs are tracking it; none have offered a production ML-DSA certificate yet. CCA’s licensed CA list is the place to watch for the first commercial deployments.
FIPS 203 also does not cover S/MIME, signed firmware, code signing, or any of the long-lived signature use cases that PKI underpins. Treat the kex migration (relatively fast, low risk) as Phase 1 and the signature migration (slow, high coordination cost) as a multi-year Phase 2 starting in 2027.
What an Indian bank should be doing now
- Inventory every TLS-terminating product in the estate. Note the OpenSSL/BoringSSL version each ships with. This list is the migration spine.
- Identify long-lived ciphertext storage: archived email, offsite backups, audit log buckets. These are the harvest-now-decrypt-later targets, not your active TLS sessions.
- For new procurements, add a “supports X25519MLKEM768 hybrid kex on a path to FIPS 140-3 ML-KEM validation” clause to RFPs.
- Run a tabletop on the “store-now, decrypt-in-2032” threat. The point is not to panic; it is to write the risk down and assign a programme owner.
A worked migration: load balancer in front of a core banking app
A realistic Indian-bank scenario. A core-banking app sits behind an F5 or NGINX load balancer terminating TLS. Internal traffic is mTLS to the app. Customers connect over the public internet to the LB.
The minimal viable migration:
- Upgrade the LB to a build with X25519MLKEM768 support — NGINX 1.27 with OpenSSL 3.5, or F5 17.5+. Verify with
openssl s_client -groups X25519MLKEM768 -connect lb.example.bank:443. A working handshake confirms support. - Set the LB to offer X25519MLKEM768 but accept x25519 as fallback. Order matters:
ssl_ecdh_curve X25519MLKEM768:x25519; - Watch the metric: the proportion of connections that negotiate hybrid kex. In May 2026, Chrome 124+, Firefox 130+, and recent iOS Safari builds all support it. Expect 35-55% of mobile traffic to land on hybrid within a week.
- Do nothing else for two months. Watch error rates. There is no downside to the older clients — they fall through to x25519 silently.
- When FIPS validation lands on your LB’s crypto module, swap to the validated build. The protocol behaviour does not change; the compliance posture does.
Total migration cost: one LB config push and a metric to watch. The reason teams stall is not technical — it is the perceived risk of touching crypto in a regulated estate. The fallback semantics of TLS make this materially less risky than it feels.
References
- RingSafe Academy module: Quantum-Safe Cryptography Readiness
- RingSafe Academy track: Cryptography & PKI
- RingSafe Academy track: Quantum Computing for Security Practitioners
- NIST FIPS 203 — Module-Lattice-Based Key-Encapsulation Mechanism Standard
Get a free attack-surface review
We check what an attacker would see about your business — leaked credentials, exposed services, dark-web mentions. 30 minutes, no obligation.