up:: In the Protocols MOC
rustls
rustls is a memory-safe TLS library written in Rust that implements TLS 1.2 and TLS 1.3, and it ships the hybrid post-quantum key exchange group X25519MLKEM768 by default through its cryptographic backend. It’s built as a safer replacement for the C-based TLS stacks that a client or server would otherwise link against, like OpenSSL, and it delegates all the actual cryptography to a pluggable backend called a CryptoProvider, whose default is aws-lc-rs, the Rust binding of AWS’s AWS-LC libcrypto. The reason rustls matters so much for the quantum transition is that it’s one of the earliest production TLS stacks where an application inherits harvest-now-decrypt-later protection by upgrading a dependency and confirming a couple of settings, rather than rewriting its crypto layer.
The short version:
- rustls is the memory-safe TLS library for the Rust ecosystem, and it delegates cryptography to a swappable
CryptoProviderbackend, so its post-quantum posture comes from the backend it links, not from primitives it implements itself. - Its default backend, aws-lc-rs, provides ML-KEM, and rustls exposes the hybrid group
X25519MLKEM768that pairs classical X25519 with ML-KEM-768. - Since rustls 0.23.27 (May 2025) the
prefer-post-quantumfeature is on by default, so a default-built, aws-lc-rs-backed rustls offers and prioritizes the hybrid group with no code change. - The gain is confidentiality, meaning the key exchange. Certificate authentication in the default path is still classical RSA or ECDSA, so post-quantum identity trails post-quantum key exchange the same way it does everywhere else.
- rustls’s default hybrid group is labeled pre-standardization and experimental, so it sits outside any FIPS-validated boundary today, which is the one caveat a regulated deployment has to hold onto.
Picture rustls as a car chassis and the CryptoProvider as the engine you bolt into it. The chassis is the TLS protocol machinery: the handshake state machine, the record layer, the memory-safe plumbing that rustls guarantees. The engine is the cryptography, and rustls lets you drop in one of two: aws-lc-rs, which carries the post-quantum parts, or ring, which doesn’t. Going quantum-safe on key exchange is a matter of using the engine that has the new part and moving it to the front of the preference list, which is why the change reads as a dependency bump rather than a rebuild.
What is rustls?
rustls is an independent TLS implementation written from scratch in Rust, funded and stewarded in part through ISRG’s Prossimo memory-safety initiative (the same nonprofit behind Let’s Encrypt). It’s the de facto memory-safe TLS stack for the Rust world, running in the same client and server roles a C TLS library would fill. The design choice that shapes everything about its post-quantum story is that rustls doesn’t implement low-level cryptographic primitives at all. It composes over a pluggable backend, so the algorithms available to a rustls application are whatever its chosen CryptoProvider supplies.
Source: rustls project, rustls.dev; ISRG Prossimo, “A Memory Safe TLS Library Achieves Post-Quantum Key Exchange”.
Because it’s a fresh Rust codebase rather than a fork of a C stack, rustls doesn’t inherit an existing library’s algorithm surface or its decades of memory-safety debt. The most consequential security property here is a category absence: the buffer-overflow and out-of-bounds-read class that produced OpenSSL’s Heartbleed (CVE-2014-0160) is structurally excluded from rustls’s own TLS-state-machine code, because safe Rust rejects that class at compile time. That’s the core reason ISRG funds it. Memory safety covers rustls’s own code, and not necessarily every line of the C-derived aws-lc-rs backend it links, which is a boundary worth keeping straight.
Source: NVD, CVE-2014-0160 (Heartbleed); ISRG Prossimo, memorysafety.org.
Where does cryptography live in rustls?
Cryptography in rustls lives entirely inside a CryptoProvider, the trait that supplies the cipher suites, key exchange groups, and signature verification a rustls connection uses. rustls ships with two:
- aws-lc-rs, the default provider. It’s the Rust binding of AWS-LC, AWS’s BoringSSL-derived libcrypto, and it’s the backend that carries ML-KEM and the hybrid key exchange group. It also has a FIPS build mode tied to the AWS-LC FIPS module.
- ring, the alternative provider. It’s a well-regarded Rust crypto library, and it does not carry the same post-quantum or FIPS surface that aws-lc-rs does.
Source: rustls, “Cryptography providers”; rustls defaults manual, docs.rs/rustls.
This matters for the transition because the backend is a genuine architectural lever. An organization that needs post-quantum key exchange, or a FIPS-mode build, chooses aws-lc-rs, and that choice is a Cargo.toml feature and provider decision rather than a rewrite of application code. It also means the same rustls version can be quantum-safe on key exchange or not, depending purely on which provider is compiled in and how it’s configured. The library capability and the deployed capability are two different claims, and confirming the second is the real work.
How does rustls go post-quantum?
rustls goes post-quantum through the aws-lc-rs backend, which exposes X25519MLKEM768, the hybrid group that runs a classical X25519 key agreement and a post-quantum ML-KEM-768 key encapsulation together in one TLS 1.3 handshake and derives the session key from both. This is the same group Chrome, Cloudflare, and AWS deploy, and the protocol mechanics are covered in TLS 1.3 Hybrid Key Exchange and Hybrid Cryptography. The rustls documentation is explicit about its standardization status: “ML-KEM-768 was standardized by NIST in FIPS 203. However, X25519MLKEM768 is pre-standardization, so you should treat this as experimental.”
Source: rustls-post-quantum crate, docs.rs/rustls-post-quantum.
The delivery moved from a bolt-on crate to an integrated near-default across the 0.23.x release line, and the default-priority behavior shifted in a way worth pinning down precisely:
- rustls 0.23.22 (2025-01-30) first shipped
X25519MLKEM768support through the aws-lc-rs provider. The release states it was “supported by default, but offered at a low algorithm negotiation priority.” The same release introduced theprefer-post-quantumfeature to reorder the key-exchange preferences so the hybrid group becomes most-preferred, and at that point the feature was opt-in. - rustls 0.23.27 (2025-05-05) added
prefer-post-quantumto the crate’s default features under the note “Prefer post-quantum key exchange algorithms by default.” From this release onward, a default-built, aws-lc-rs-backed rustls offers and prioritizes the hybrid group with zero code change. - rustls 0.23.37 (2026-02-24) added ML-KEM-1024 key exchange, extending the post-quantum surface to the higher parameter set.
- rustls 0.23.41 (2026-06-22), the current release, still documents
prefer-post-quantumas enabled by default for the aws-lc-rs-backed provider.
Sources: rustls, 0.23.22 release notes; rustls, 0.23.27 release notes; rustls, 0.23.37 release notes; rustls crate feature list, docs.rs/rustls.
The rustls-post-quantum crate that originally delivered this is now a thin transitional shim. As the crate docs put it, “In rustls 0.23.22 and later … ML-KEM key exchange (both ‘pure’ and hybrid variants) have been moved to the rustls crate itself.” So a project on a current rustls gets the hybrid group from the core crate and the aws-lc-rs provider directly, and the separate crate exists mainly to ease the transition for code that referenced it.
Source: docs.rs/rustls-post-quantum.
The table below is the current post-quantum surface at a glance.
| PQC capability | Status in rustls | Where it lives |
|---|---|---|
Hybrid key exchange X25519MLKEM768 | Shipped, prioritized by default | aws-lc-rs provider; default since 0.23.27, labeled pre-standardization / experimental |
| Pure (non-hybrid) ML-KEM-768 key exchange | Shipped | aws-lc-rs provider |
| ML-KEM-1024 key exchange | Shipped (added 0.23.37) | aws-lc-rs provider |
| PQC signatures (ML-DSA) | Experimental, unstable feature only | aws-lc-rs-unstable; not in the default authentication path |
| SLH-DSA / FN-DSA | Not confirmed against primary source | None documented |
| FIPS-validated PQC boundary | Not through the default hybrid group | group is pre-standardization; aws-lc-rs FIPS build is a separate story |
Source: docs.rs/rustls-post-quantum; rustls release history, github.com/rustls/rustls/releases.
How do you enable post-quantum key exchange in rustls?
For most Rust projects, enabling post-quantum key exchange is a dependency question with three checks rather than a coding task. The steps, in order:
- Pin rustls at 0.23.27 or later. On any pin at or after 0.23.27 with default features and the aws-lc-rs provider, the hybrid group is prioritized automatically. On 0.23.22 through 0.23.26 the group is present but low-priority unless you turn on
prefer-post-quantum. Before 0.23.22 the group is absent from the core crate. Confirm the exact pin inCargo.lockagainst these boundaries. - Confirm the aws-lc-rs provider is the one compiled in. aws-lc-rs is the default, but a project that explicitly selected the
ringprovider does not get the post-quantum group, because ring doesn’t carry ML-KEM. Switching back to aws-lc-rs is a feature and provider change, not an application rewrite. - Confirm the
prefer-post-quantumdefault feature is still enabled. If a project disabled default features for its own reasons, the hybrid group can be available but not highest-priority, which is exactly the case the rustls defaults manual describes when it says the group is present but not top of the preference order.
Source: rustls defaults manual, docs.rs/rustls; 0.23.27 release notes.
The step that separates a real deployment from a paper one is verifying on the wire. “The library supports it” and “this endpoint actually negotiated it” are different claims, because hybrid can silently not happen: if the peer doesn’t support X25519MLKEM768, or a middlebox on the path drops the larger handshake, the negotiation falls back to a classical group and the connection still succeeds without post-quantum protection. The ground truth is the negotiated group in a packet capture of the handshake, and watching the handshake-failure rate as you roll out is the tell for the oversized-ClientHello middlebox problem that affects every stack shipping this group, rustls included. That deployment trap is covered in depth in TLS 1.3 Hybrid Key Exchange.
What is rustls’s place in the Rust ecosystem?
rustls is the TLS substrate for a growing part of the Rust server and client world, and most applications reach it through an integration crate rather than directly. The common consumers include tokio-rustls for async TLS on the Tokio runtime, hyper-rustls for HTTP, and HTTP clients like reqwest that can select rustls as their TLS backend. Any deployment surface built on those, HTTP clients and servers, reverse proxies, API gateways, service meshes, and internal service-to-service traffic, inherits rustls’s quantum-transition timeline.
Source: rustls, rustls.dev; ISRG Prossimo, memorysafety.org. Downstream-dependency details vary by project and should be read from each consuming crate’s own manifest.
The migration consequence is unusually favorable compared with the wider ecosystem. Because rustls moved early, adding the hybrid group and then promoting it to a default, a large class of Rust services gains hybrid post-quantum key agreement by bumping the rustls version and confirming the backend and feature, rather than re-architecting the crypto layer. That’s the clean end of Crypto-Agility: the design was already agile enough that the new algorithm arrived as a configuration state rather than a project. It’s a useful contrast to a vendor-controlled or slow-to-validate library, where the same gain waits on someone else’s release schedule.
What does rustls’s post-quantum support not cover?
rustls’s post-quantum support covers key exchange, and it deliberately leaves two things for later timelines: authentication and FIPS validation. Both are load-bearing for a regulated deployment.
- Authentication stays classical by default. The server still proves its identity with a certificate signed by RSA or ECDSA, and a quantum computer running Shor’s algorithm breaks those signatures too. rustls exposes ML-DSA signing only behind an unstable feature (
aws-lc-rs-unstable), described as experimental and outside the default authentication path. So a rustls connection can useX25519MLKEM768for its keys while presenting a fully classical certificate, which is the normal state of a 2026 deployment. This is the HNDL versus Non-HNDL split: key exchange is the harvest-urgent half and ships first, while certificate signatures are the real-time-forgery half and follow on a slower track. - The default hybrid group is outside any FIPS boundary.
X25519MLKEM768is pre-standardization, so it can’t serve as a FIPS-validated key-establishment artifact regardless of how it’s built. Separately, aws-lc-rs can be built in FIPS mode against the AWS-LC FIPS module, and AWS-LC has since reached a FIPS 140-3 validation that includes ML-KEM (AWS-LC FIPS 3.x). Even so, a validated module carrying ML-KEM is a different claim from the specific rustls plus aws-lc-rs build in front of you being that validated FIPS build, and that pairing is what a compliance gate actually checks. The full FIPS posture lives in AWS-LC.
Source: docs.rs/rustls-post-quantum; AWS Security Blog, “AWS-LC FIPS 3.0: first cryptographic library to include ML-KEM in FIPS 140-3 validation”.
The honest summary is that rustls delivers post-quantum confidentiality well ahead of post-quantum identity and well ahead of the validation paperwork. A CBOM has to inventory those planes separately, or it will mark a key-exchange-migrated rustls server “done” while its certificate is still classically forgeable and its FIPS story is still pending.
Common misconceptions
- “rustls implements its own cryptography.” It doesn’t. rustls implements the TLS protocol and delegates all cryptography to a
CryptoProviderbackend, so its algorithm surface, including post-quantum, is whatever aws-lc-rs or ring supplies. Its post-quantum capability comes from aws-lc-rs providing ML-KEM. - “Enabling the hybrid group makes my TLS fully post-quantum.” It makes the confidentiality plane post-quantum. The certificate that authenticates the server is still signed with classical RSA or ECDSA, so the identity remains quantum-forgeable until PKI migrates. Confidentiality and authentication move on separate schedules.
- “The ring backend gives me post-quantum too.” The post-quantum and FIPS surface lives in aws-lc-rs. A project that selected ring for its
CryptoProviderdoes not getX25519MLKEM768, and moving to aws-lc-rs is the fix. - “rustls’s hybrid group is FIPS-compliant.” The default hybrid group is pre-standardization and sits outside any FIPS-validated boundary. The aws-lc-rs FIPS build is a separate path, and even there the check is whether the actual build in use is tied to the validated module.
- “I still need the separate rustls-post-quantum crate.” Since 0.23.22 the ML-KEM key exchange, both pure and hybrid, moved into the core rustls crate, and the standalone crate is now a thin transitional shim. A current project gets the group from core rustls plus the aws-lc-rs provider.
- “Memory-safe Rust means rustls can’t have security bugs.” Memory safety structurally excludes the Heartbleed-class buffer bugs from rustls’s own code, and that’s a real and large win. The advisories rustls has published have been availability-class issues like denial-of-service on malformed input, so the library still gets security releases worth tracking.
Questions people ask
Does rustls support post-quantum cryptography? Yes, for key exchange. rustls ships the hybrid group X25519MLKEM768 (classical X25519 plus ML-KEM-768) through its default aws-lc-rs backend, and since 0.23.27 it’s prioritized by default. Post-quantum signatures exist only behind an experimental unstable feature, so certificate authentication in the default path is still classical.
Do I have to rewrite my Rust app to enable it? No. For a project already on rustls with the aws-lc-rs backend and default features, upgrading to 0.23.27 or later gets you the prioritized hybrid group with no code change. The work is confirming the version pin, the backend, and the feature, then verifying real sessions negotiate it.
What’s the rustls-post-quantum crate, and do I still need it? It’s the crate that originally delivered ML-KEM key exchange to rustls. As of 0.23.22 that functionality moved into the core rustls crate, and rustls-post-quantum became a thin transitional shim. A current project gets the hybrid group from core rustls plus the aws-lc-rs provider, so most code can drop the direct dependency on the separate crate.
Which backend do I need, aws-lc-rs or ring? aws-lc-rs, the default. It’s the Rust binding of AWS-LC and the backend that carries ML-KEM and the hybrid group, plus the FIPS build path. The ring backend doesn’t carry the same post-quantum or FIPS surface, so a project that needs PQC and selected ring has to switch providers.
Is rustls’s post-quantum key exchange FIPS-validated? The default hybrid group is not, because X25519MLKEM768 is pre-standardization and outside any FIPS boundary. aws-lc-rs can be built in FIPS mode against the AWS-LC FIPS module, and AWS-LC now holds a FIPS 140-3 validation that includes ML-KEM, but the deployment-specific check is whether the exact aws-lc-rs build in use is that validated FIPS build. See AWS-LC.
Does rustls give me post-quantum certificate authentication too? Not in the default path. ML-DSA signing exists only behind the aws-lc-rs-unstable experimental feature, so the certificates rustls presents and verifies are still signed with classical RSA or ECDSA. Post-quantum confidentiality ships well ahead of post-quantum identity, which is the pattern across the whole ecosystem.
What rustls version do I need for post-quantum by default? 0.23.27 (May 2025) or later, with default features and the aws-lc-rs backend, gives the prioritized hybrid group automatically. Versions 0.23.22 through 0.23.26 carry the group but at low priority unless you enable prefer-post-quantum. Anything before 0.23.22 doesn’t have the group in the core crate.
Does turning on the hybrid group guarantee it’s actually used? No. If the peer doesn’t support X25519MLKEM768, or a middlebox on the path can’t carry the larger handshake, the connection falls back to a classical group and still succeeds without post-quantum protection. You confirm the negotiated group from a packet capture on real traffic, not from the fact that the option was enabled.
Everything here is the map, given freely. When your team needs its Rust TLS surface, versions, backends, and actual on-the-wire negotiation, assessed for a real hybrid rollout, that’s what an alignment briefing is for.
Last verified 2026-07-09 · Maintained by Addie LaMarr, LaMarr Labs.