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 whether it sits inside a FIPS-validated boundary depends on the specific aws-lc-rs FIPS build behind it, 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 in Rust, in which “all protocol processing is in 100% memory-safe Rust,” and its post-quantum work is funded and stewarded in part through ISRG’s Prossimo memory-safety initiative. It runs 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, with a “choice of cryptography providers, including aws-lc-rs, ring and with several FIPS140-approved options.”
Source: rustls project, rustls.dev, for the memory-safety and pluggable-provider design; Josh Aas, ISRG Prossimo, “The Rustls TLS Library Adds Post-Quantum Key Exchange Support”, March 26, 2024, for ISRG’s Prossimo work on rustls and the post-quantum key exchange.
Because it’s a 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. The project puts the same point in its own words: “we learned from past protocol and implementation vulnerabilities to avoid repeating the same mistakes,” and Prossimo’s assessment is that “with the advancements made to Rustls over the last few years, we now see it as a viable, performant, and memory safe alternative to OpenSSL.” 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: rustls project, rustls.dev, for the memory-safety design statement; Josh Aas, ISRG Prossimo, “The Rustls TLS Library Adds Post-Quantum Key Exchange Support”, March 26, 2024, for the OpenSSL-alternative assessment; NVD, CVE-2014-0160 (Heartbleed), for the vulnerability itself. ⚠️ Neither rustls.dev nor the Prossimo post discusses Heartbleed, the aws-lc-rs backend boundary, or ISRG’s funding rationale; the Heartbleed comparison and the backend boundary are this guide’s analysis.
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 states its standardization status and its deployment status in the same breath: “X25519MLKEM768 is pre-standardization, but is now widely deployed, for example, by Chrome and Cloudflare.” It adds a practical caution rather than an experimental label: “You may see unexpected connection failures (such as tldr.fail).”
Source: rustls defaults manual, “About the post-quantum-secure key exchange X25519MLKEM768,” docs.rs/rustls (0.23.43, checked 2026-08-28), which also records the other half separately: “ML-KEM-768 was standardized by NIST in FIPS203.” The rustls-post-quantum crate docs carry none of this language; the word “experimental” there attaches to the aws-lc-rs-unstable ML-DSA feature.
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.43 (2026-07-29), the current release, still documents
prefer-post-quantumas enabled by default for the aws-lc-rs-backed provider: “prefer-post-quantum (enabled by default): for the aws-lc-rs-backed provider, prioritizes post-quantum secure key exchange by default (using X25519MLKEM768).”
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 (0.23.43, dated 29 July 2026 and listed as Latest on the releases page, checked 2026-08-28). Because docs.rs/rustls/latest is a moving target, that version and check date are recorded here rather than left implicit.
The rustls-post-quantum crate that originally delivered this is now a thin transitional shim. As the crate docs put it, “Before rustls 0.23.22, this crate additionally provided support for the ML-KEM key exchange (both ‘pure’ and hybrid variants), but these 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 now supplies a convenience CryptoProvider and the experimental aws-lc-rs-unstable ML-DSA feature rather than the key exchange.
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 |
| 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 | Depends on the build in front of you | group is pre-standardization; FIPS status depends on the specific aws-lc-rs FIPS build |
Source: rustls defaults manual, docs.rs/rustls, for the group being pre-standardization; AWS Security Blog, “AWS-LC FIPS 3.0”, for the aws-lc-rs FIPS path; docs.rs/rustls-post-quantum for the crate’s remaining surface; rustls release history, github.com/rustls/rustls/releases, for the version boundaries.
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.
Sources: rustls, rustls.dev, for rustls itself. The integration crates are documented by their own publishers: tokio-rustls, hyper-rustls, and reqwest’s rustls-tls feature, docs.rs/reqwest. ⚠️ Neither rustls.dev nor the Prossimo post names these consumers. 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’s FIPS status depends on the build, not on the group name.
X25519MLKEM768is itself pre-standardization, and AWS’s position is that with ML-KEM now NIST-approved, a hybrid pairing it with x25519 can run inside a FIPS-validated module, since “for hybrid key establishment in FIPS 140-approved mode, one component algorithm must be a NIST-approved mechanism.” AWS-LC FIPS 3.0 carries ML-KEM into a FIPS 140-3 submission, and as of that announcement it sits on the CMVP modules-in-process list rather than holding a 3.0 certificate. So the compliance question is whether the build in front of you is tied to a validated module. The full FIPS posture lives in AWS-LC.
Source: rustls defaults manual, docs.rs/rustls, for X25519MLKEM768 being pre-standardization; AWS Security Blog, “AWS-LC FIPS 3.0: first cryptographic library to include ML-KEM in FIPS 140-3 validation”, which states that “AWS-LC FIPS 3.0 has been added to the National Institute of Standards and Technology (NIST) Cryptographic Module Validation Program (CMVP) modules in process list” (it reserves “certified” for the earlier versions: “AWS-LC-FIPS 2.0, was certified in October 2024”), and that “by configuring your TLS cipher suite to use ML-KEM-768 and x25519 (draft-kwiatkowski-tls-ecdhe-mlkem), you can use x25519 within a FIPS-validated cryptographic module for the first time.”
The 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 group name settles nothing.
X25519MLKEM768is pre-standardization, and AWS’s position is that a hybrid pairing ML-KEM with x25519 can run inside a FIPS-validated module now that ML-KEM is NIST-approved. The check that matters is whether the actual aws-lc-rs build in use is tied to a 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? It depends on the build. X25519MLKEM768 is pre-standardization as a group, but AWS states that with ML-KEM NIST-approved, an ML-KEM-768 plus x25519 hybrid can run inside a FIPS-validated module. AWS-LC FIPS 3.0, the version carrying ML-KEM, sits on the CMVP modules-in-process list as of AWS’s announcement, so the deployment-specific check is whether the exact aws-lc-rs build in use is tied to a validated module. 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 the work I do.
Last verified 2026-07-26 · Updated 2026-08-25 · Maintained by Addie LaMarr, LaMarr Labs.