TL;DR
ML-DSA-65 at TLS 1.3 is production-ready today. Hybrid KEM (X25519MLKEM768) too. Both have no measurable penalty over classical at WAN RTT.
SLH-DSA cannot be served over TLS yet with any public stack I tested. The crypto and X.509 layers work; the TLS integration layer isn't shipping.
When ecosystem support has layers, "shipping" the algorithm doesn't mean "shipping" the deployment.
What I set out to do
Six weeks ago I started pqc-bench to answer a specific question: how much does post-quantum TLS 1.3 cost me, in milliseconds, at scales and distances that match a real deployment? The project was going to be five phases of measurement ending with a cert-size × WAN RTT scenario built around SLH-DSA's 17 kB signature forcing an extra round-trip through TCP's initial congestion window.
The last phase didn't produce measurements. It produced a different kind of finding. This post ties it to the four that worked.
The four phases that worked
Phase 1 — fresh handshake latency, same-AZ. X25519MLKEM768 vs X25519. Delta: 0.3 ms per handshake. Below the noise floor of ±1 ms RTT variance on a c7g.large same-AZ. The hybrid KEM extension is cheap.
Phase 2 — session resumption plus payload sweep (100 B / 10 kB / 100 kB). Classical and PQ statistically identical at every percentile post-resumption. The 1 MB arm had to be dropped — not because of crypto, because the instance's NIC saturated at 200 req/s × 1 MB ≈ 1.6 Gbps. I noted it for Phase 3's methodology and moved on.
Phase 3 — cert chain size × WAN RTT across three regions. ECDSA, RSA-2048, ML-DSA-65 × us-east-1, us-west-2, ap-northeast-1. Headline: cert-chain-size differences are statistically invisible at WAN RTT because TCP's initial congestion window (14.6 kB) absorbs the whole ML-DSA-65 chain in one round-trip. The only measurable delta — 1.5 ms — appeared at same-AZ ~1 ms RTT, where every tenth of a millisecond is visible. I also reran the 1 MB payload at 20 req/s and confirmed Phase 2's 1 MB failure was 100% NIC saturation, no crypto effect.
Phase 4 Part 1 — SLH-DSA at WAN RTT. Planned as the clean counterexample: 17 kB signature → ~20 kB cert chain → one extra round-trip. Tested the premise; the ecosystem couldn't run the experiment.
The three layers
Phase 4's finding fits in one picture.
TLS support for a signature algorithm has three layers, and all three have to arrive together before a deployment is possible:
Cryptographic primitives. openssl genpkey, sign, verify.
X.509 encoding. OIDs recognised when parsing cert ASN.1.
TLS protocol integration. SSL_CTX_use_certificate accepts the cert, ClientHello's signature_algorithms extension advertises the type, CertificateVerify is signed with it.
OpenSSL 3.5.2 has all three for ML-DSA. For SLH-DSA, it has layers 1 and 2 only. oqs-provider 0.12.0-dev doesn't fill the TLS gap — it deferred SLH-DSA to OpenSSL's default provider now that 3.5.2 has native support, and the default provider doesn't reach layer 3. The hand-off left a hole nobody owns right now.
What you can deploy today
| You want to… | Status |
|---|---|
| Serve ML-DSA-65 cert over TLS 1.3 | ✓ Production-ready, OpenSSL 3.5.0+ |
| Serve SLH-DSA cert over TLS 1.3 | ✗ Not with any public stack I tested |
| Sign JWT / firmware / packages with SLH-DSA | ✓ OpenSSL 3.5.2 keygen + sign work |
| Use hybrid KEM (X25519MLKEM768) in TLS 1.3 | ✓ OpenSSL 3.5.0+, both ends |
| Store an SLH-DSA cert in a certificate store | ✓ X.509 layer accepts it |
| Negotiate PQ cert selection via SNI | ✓ If the cert is ML-DSA |
What the series taught me
Three things I'll carry into the next two projects.
"Measurable" is a hypothesis. Phase 1 and Phase 3 both predicted measurable PQ overhead at the chosen scale, and both got noise. That's a less-sexy finding, but it's the useful one for the people who have to decide whether to deploy: ML-DSA is cheap enough that the decision is "yes, when you're ready," not "yes, if you can afford the latency."
Infrastructure limits dominate crypto costs more often than crypto costs dominate anything. Phase 2's 1 MB payload failure wasn't about PQ. It was about a $0.14/hr instance pegging its NIC at 1.6 Gbps. The methodology note that caught it was more informative than any signature-algorithm observation in the whole series. Pick instance sizes that make the crypto, not the network, the bottleneck — otherwise you're measuring the wrong thing.
"Supported" has layers. Phase 4's lesson is the one I'll keep closest. OIDs, TLS codepoints, keygen implementations, and TLS handshake integrations are four different things that have to ship together before a deployment is possible. "SLH-DSA is in OpenSSL 3.5" is correct at the first two layers and misleading at the third.
What's next
A GitHub Actions cron builds the latest OpenSSL 3.5.x and oqs-provider main on the 1st of each month and checks openssl list -tls-signature-algorithms for SLH-DSA entries. Running log at the tracking issue. The day it reports "yes," Phase 6 of pqc-bench measures what Phase 4 was supposed to.
The series' underlying lesson — that "support" has layers that can arrive separately — becomes the core of Project 1 of the trilogy: PQC-Probe, a scanner that reports what a given host supports across SSH and TLS, in both vanilla and experimental PQ stacks. When those answers differ, that gap is actionable.
Thanks for following along, five posts in. The repo is at pqc-bench and pqc-bench-slh-dsa. The data, the terraform, the user-data scripts, and the full logs of every failure mode are all there. Fork what's useful.
Follow for Part 6 — the SLH-DSA measurements, whenever the ecosystem catches up.











![Vulnerability Report: GO-2026-6809 [Breakdown]](https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh5kit0pveftlapz0el96.png)


