C API for rustls::quic (client side), for QUIC stacks such as ngtcp2 (curl HTTP/3)

Open
#705 5 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
rust
Domain
api, security

Research direction

Review the proposed implementation on the quic branch of the reporter’s fork, especially librustls/src/quic.rs and the regenerated rustls.h, then compare its conventions with the README and CONTRIBUTING.md. The issue leaves API shape and traffic-secret handling open for maintainer input. A completed contribution should settle those choices and include the agreed client-side QUIC API with tests and documentation.

Written by the indexing model from the issue text.

Description

I would like to add a C API over rustls::quic (client side), so that QUIC stacks written in C can use Rustls for the TLS part of the handshake. A working implementation with tests is on the branch quic of my fork, one commit on top of main: https://github.com/marie-222/rustls-ffi/tree/quic (librustls/src/quic.rs and the regenerated rustls.h). cargo fmt --check, cargo clippy, cargo test and cargo check --no-default-features --features ring pass. I have not opened a PR, following CONTRIBUTING.md.

Why

curl builds its HTTP/3 on ngtcp2, whose TLS backends are OpenSSL (3.5+ / quictls / BoringSSL), GnuTLS and wolfSSL; there is no Rustls one. So curl --with-rustls cannot do HTTP/3, and Encrypted Client Hello, which curl only has through Rustls (OpenSSL 3.5 has no ECH API), cannot be combined with HTTP/3.

With this API and a small ngtcp2 crypto helper (HKDF/AEAD/header protection from OpenSSL's libcrypto, TLS from rustls-ffi), I have curl 8.23.0 doing HTTP/3, and ECH over HTTP/3, against public servers (cloudflare.com, www.google.com), and against a test server that sends a Retry and updates its keys during a 6 MiB download. The curl patch and the helper are in https://github.com/small-gear-lab/apt-packaging (the helper is derived from ngtcp2's quictls one; I may offer it to ngtcp2 separately).

The API

All on one new object, rustls_quic_connection, following the conventions of the README:

rustls_quic_client_connection_new(config, quic_version, server_name, alpn..., params..., &conn)
rustls_quic_connection_read_hs(conn, data, len)           // bytes of CRYPTO frames received
rustls_quic_connection_write_hs(conn, out, cap, &len, &keys)  // bytes to send; which keys are available after them
rustls_quic_connection_is_handshaking / _get_alert / _free
rustls_quic_connection_get_negotiated_ciphersuite
rustls_quic_connection_get_peer_transport_parameters
rustls_quic_connection_get_peer_certificate               // then rustls_certificate_get_der
rustls_quic_connection_get_secret(conn, kind, out, cap, &len)

Questions

  1. Traffic secrets. rustls::quic returns finished key objects and does not expose the secrets, but ngtcp2 (and other stacks) derive their own packet keys from secrets (ngtcp2_crypto_derive_and_install_rx/tx_key). I take them from the key log: the connection works on a copy of the ClientConfig whose key_log keeps this connection's secrets and forwards every line to the config's own key log. It works, and I checked (with a test) that a secret is available from the moment the handshake bytes that give it have been read, which is before write_hs reports that level's keys. But it relies on the key log. Would you rather expose the secrets (or the raw material of quic::Keys) from rustls::quic, or is the key log route acceptable for the C API?
  2. Shape. I used a new object rather than extending rustls_connection, because rustls::quic::ClientConnection is a different type. Is that what you would want? Naming (rustls_quic_*) and the "NOT_FOUND vs NULL" choices follow the README as I read it; I will change them to whatever you prefer.
  3. Scope. Client side only for now, no 0-RTT or session resumption (a client ticket cannot be serialized with the public API of rustls, so I may ask about that separately in the rustls repository).

I am happy to adapt the API, add tests or documentation, or split it, before a PR.

Dominant language
Rust
Stars
171
Forks
45
Avg merge
16h 43m
Merged PRs (30d)
18

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rustls/rustls-ffi

All issues in rustls/rustls-ffi

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.