Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion quest/m1/quic-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ side by side and fix any name or signature that still differs, and check

## Required

- [Crypto](/quest/m1/quic-api/crypto.md) - crypto traits sealed to rustls, concrete peer identity and handshake data
- [Waits](/quest/m1/quic-api/waits.md) - moq-quic owns every wait as a `poll_*` on `&kio::Waiter`, deleting `StreamEvent` and the drivers' and qmux's waiter tables
- [Poll forms](/quest/m1/quic-api/poll.md) - both drivers' waits poll as `&self, &kio::Waiter` forwards to moq-quic, the async forms wrap them, and `send::Finished` is a future
- [Native WebTransport](/quest/m1/quic-api/native-web.md) - `quic::web` in both crates implements moq-net's poll traits, deleting the generic `web_transport_trait` adapters and the dependency on it
Expand Down
41 changes: 0 additions & 41 deletions quest/m1/quic-api/crypto.md

This file was deleted.

4 changes: 0 additions & 4 deletions quest/m2/rind/transport.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,3 @@ Decided with the maintainer on 2026-10-26; see the
Public API: moq-tokio's and moq-quic's `aws-lc-rs` and `ring` features are
removed (breaking; migrate by dropping them, since rind is always on).
Unsupported CPUs now fail at startup. Wire: none.

## Required

- [moq-quic's crypto is rustls](/quest/m1/quic-api/crypto.md) - the sealed crypto surface rind plugs into, without the per-provider gates
10 changes: 3 additions & 7 deletions rs/moq-quic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ features = ["rustls-aws-lc-rs", "ring"]

[features]
default = ["ring"]
aws-lc-rs = ["dep:aws-lc-rs", "aws-lc-rs?/aws-lc-sys", "aws-lc-rs?/prebuilt-nasm", "dep:rustls", "rustls/aws-lc-rs"]
aws-lc-rs = ["dep:aws-lc-rs", "aws-lc-rs?/aws-lc-sys", "aws-lc-rs?/prebuilt-nasm", "rustls/aws-lc-rs"]
# Enable rustls with the aws-lc-rs crypto provider.
rustls-aws-lc-rs = ["aws-lc-rs"]
ring = ["dep:ring", "dep:rustls", "rustls/ring"]
ring = ["dep:ring", "rustls/ring"]
# Enable qlog support
qlog = ["dep:qlog"]
# The sans-IO QMux connection, which runs the stream state machine over a reliable, ordered
Expand All @@ -29,10 +29,6 @@ mux = []
# driver that runs QUIC on kio's simulator. Hidden from the docs; meant for
# dev-dependencies.
sim = []
# Internal (PRIVATE!) features used to aid testing.
# Don't rely on these whatsoever. They may disappear at any time.

__rustls-post-quantum-test = []

# Exposes the `fuzz/` harness's target bodies, and the plaintext crypto the connection
# target and the benches run on, through the hidden `fuzz` module. ring keys the endpoint's
Expand All @@ -54,7 +50,7 @@ qlog = { version = "0.18", optional = true }
rand = { workspace = true }
ring = { version = "0.17", optional = true }
rustc-hash = { workspace = true }
rustls = { version = "0.23.5", default-features = false, features = ["std"], optional = true }
rustls = { version = "0.23.5", default-features = false, features = ["std"] }
slab = { workspace = true }
thiserror = { workspace = true }
tinyvec = { version = "1.1", features = ["alloc"] }
Expand Down
13 changes: 13 additions & 0 deletions rs/moq-quic/MIGRATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ How to update your code for each breaking change, newest first.

## Unreleased

### Crypto is sealed to rustls ([#7028](https://github.com/moq-dev/moq/pull/7028))

Build configs with `client::Config::new(Arc::new(rustls_client))` and `server::Config::new(Arc::new(rustls_server))`; both are infallible.
`crypto::rustls::QuicClientConfig`, `QuicServerConfig`, their `TryFrom` and `with_initial`, and `NoInitialCipherSuite` are gone, as are the public `client::Config::crypto` and `server::Config::crypto` fields.
A custom crypto implementation is no longer supported: the `crypto` traits, `Keys`, and `KeyPair` are crate-private.
Replace `conn.crypto_session().handshake_data()` and its downcast to `crypto::rustls::HandshakeData` with `conn.handshake_data()`, which returns `Option<crypto::HandshakeData>`.
Its `protocol` field is now `alpn`, and `protocol_version` and `cipher_suite` are dropped.
Replace `crypto_session().peer_identity()` and its downcast with `conn.peer_identity()`, which returns `Option<Vec<CertificateDer<'static>>>`.
`Connection::export_keying_material` and `transport_parameters` are no longer public.
A rustls config without TLS 1.3 or the AES-128-GCM-SHA256 suite now fails each connection: the client's connect returns `ConnectError::Tls`, and the server closes the connection or drops its Initial.
`ConnectError` no longer implements `Eq`.
rustls is a required dependency; the `ring` and `aws-lc-rs` features pick only the provider.

### An evicted stream fails `received_reset` ([#7624](https://github.com/moq-dev/moq/pull/7624))

`recv::Stream::received_reset` returns `Err(Error::Evicted)` for a stream evicted to free a stuck receive window, until the application stops it, rather than `Err(Error::Closed)`.
Expand Down
4 changes: 2 additions & 2 deletions rs/moq-quic/benches/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,13 +643,13 @@ fn transport(receive_window: VarInt, send_window: u64, probe: bool) -> transport
}

fn server_config(receive_window: VarInt) -> server::Config {
let mut config = server::Config::new(Arc::new(Plaintext));
let mut config = Plaintext::server();
config.transport = transport(receive_window, SEND_WINDOW, false);
config
}

fn client_config(send_window: u64, probe: bool) -> client::Config {
let mut config = client::Config::new(Arc::new(Plaintext));
let mut config = Plaintext::client();
config.transport = transport(VarInt::MAX, send_window, probe);
config
}
Expand Down
21 changes: 15 additions & 6 deletions rs/moq-quic/src/config/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct Config {
pub transport: transport::Config,

/// Cryptographic configuration to use
pub crypto: Arc<dyn crypto::ClientConfig>,
pub(crate) crypto: Arc<dyn crypto::ClientConfig>,

/// QUIC protocol version to use
pub version: Version,
Expand All @@ -35,8 +35,8 @@ pub struct Config {
}

impl Config {
/// Dial with `crypto` and the default settings
pub fn new(crypto: Arc<dyn crypto::ClientConfig>) -> Self {
/// Dial with any crypto, such as the fuzz target's plaintext
pub(crate) fn from_crypto(crypto: Arc<dyn crypto::ClientConfig>) -> Self {
Self {
transport: transport::Config::default(),
crypto,
Expand All @@ -49,13 +49,22 @@ impl Config {

#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
impl Config {
/// Run the handshake with `tls` and the default settings
///
/// The config must enable TLS 1.3, or connecting fails with [`ConnectError::Tls`].
/// Early data stays off: if `tls` enables it, the connection uses a copy that does not.
///
/// [`ConnectError::Tls`]: crate::endpoint::ConnectError::Tls
pub fn new(tls: Arc<rustls::ClientConfig>) -> Self {
Self::from_crypto(Arc::new(QuicClientConfig::new(tls)))
}

/// Dial trusting the specified trust anchors
pub fn with_root_certificates(
roots: Arc<rustls::RootCertStore>,
) -> Result<Self, rustls::client::VerifierBuilderError> {
Ok(Self::new(Arc::new(QuicClientConfig::new(
WebPkiServerVerifier::builder_with_provider(roots, configured_provider()).build()?,
))))
let verifier = WebPkiServerVerifier::builder_with_provider(roots, configured_provider()).build()?;
Ok(Self::new(Arc::new(QuicClientConfig::inner(verifier))))
}
}

Expand Down
18 changes: 12 additions & 6 deletions rs/moq-quic/src/config/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ pub struct Config {
pub transport: transport::Config,

/// TLS configuration used for incoming connections
///
/// Must be set to use TLS 1.3 only.
pub crypto: Arc<dyn crypto::ServerConfig>,
pub(crate) crypto: Arc<dyn crypto::ServerConfig>,

/// Configuration for sending and handling validation tokens
pub validation_token: validation_token::Config,
Expand Down Expand Up @@ -94,8 +92,16 @@ pub struct Config {

#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
impl Config {
/// Serve `crypto` with the default settings and a random handshake token key
pub fn new(crypto: Arc<dyn crypto::ServerConfig>) -> Self {
/// Run the handshake with `tls`, with the default settings and a random handshake token key
///
/// The config must enable TLS 1.3, or every incoming connection fails its handshake.
/// Early data stays off: if `tls` accepts it, the connection uses a copy that does not.
pub fn new(tls: Arc<rustls::ServerConfig>) -> Self {
Self::from_crypto(Arc::new(QuicServerConfig::new(tls)))
}

/// Serve any crypto, such as the fuzz target's plaintext
pub(crate) fn from_crypto(crypto: Arc<dyn crypto::ServerConfig>) -> Self {
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::hkdf;
use rand::Rng;
Expand Down Expand Up @@ -127,7 +133,7 @@ impl Config {
cert_chain: Vec<CertificateDer<'static>>,
key: PrivateKeyDer<'static>,
) -> Result<Self, rustls::Error> {
Ok(Self::new(Arc::new(QuicServerConfig::new(cert_chain, key)?)))
Ok(Self::new(Arc::new(QuicServerConfig::inner(cert_chain, key)?)))
}
}

Expand Down
25 changes: 22 additions & 3 deletions rs/moq-quic/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,9 +1535,28 @@ impl Connection {
self.update_keys(None, false);
}

/// Get a session reference
pub fn crypto_session(&self) -> &dyn crypto::Session {
&*self.crypto
/// What the handshake negotiated, once the connection emits [`Event::HandshakeDataReady`]
pub fn handshake_data(&self) -> Option<crypto::HandshakeData> {
self.crypto.handshake_data()
}

/// The certificate chain the peer presented, end entity first, if it presented one
///
/// Complete only once the handshake finishes, signaled by [`Event::Connected`].
pub fn peer_identity(&self) -> Option<Vec<rustls::pki_types::CertificateDer<'static>>> {
self.crypto.peer_identity()
}

/// Fill `output` with keying material exported from the TLS session (RFC 5705), using
/// `label` and `context` for domain separation
#[cfg(test)]
pub(crate) fn export_keying_material(
&self,
output: &mut [u8],
label: &[u8],
context: &[u8],
) -> Result<(), crypto::ExportKeyingMaterialError> {
self.crypto.export_keying_material(output, label, context)
}

/// Whether the connection is in the process of being established
Expand Down
Loading
Loading