Skip to content

Add rustls-ring feature, probe CA paths for static rustls builds - #687

Open
CarloTUM wants to merge 2 commits into
sagebind:mainfrom
CarloTUM:rustls-ring
Open

CarloTUM wants to merge 2 commits into
sagebind:mainfrom
CarloTUM:rustls-ring

Conversation

@CarloTUM

@CarloTUM CarloTUM commented Oct 10, 2026 •

Copy link
Copy Markdown

Two small changes for people who build libcurl statically on the rustls backend.

1. rustls-ring: rustls on ring instead of aws-lc-rs

rustls-ffi defaults to aws-lc-rs, which needs cmake and a C/C++ toolchain for the target at build time, and seeds its RNG from CPU jitter at startup. On a slow ARM core that seeding costs hundreds of milliseconds of CPU per process, which matters for short-lived programs. Measured on a Cortex-A53 (Orange Pi Zero 2W, Debian 13), one GET https:// per process, CPU time:

build HTTPS per process
rustls + static-curl (aws-lc, jitter entropy on) 433 ms
rustls + static-curl, AWS_LC_SYS_NO_JITTER_ENTROPY=1 at build time 21 ms
rustls-ring + static-curl 28 ms

The env var is a workaround one has to know about; ring builds with cargo alone (no cmake, which also makes a static musl cross build a one-liner) and has no startup cost.

rustls-ring selects rustls-ffi's ring feature. To make that possible, rustls-ffi's default features are turned off in curl-sys and the existing rustls feature enables them explicitly (aws-lc-rs, prefer-post-quantum), so current rustls users get exactly the provider they had. The C side is the same for both features.

cargo tree --no-default-features --features rustls-ring,static-curl contains no aws-lc-rs or cmake.

2. Probe for CA paths on static rustls builds

With static-curl the bundled libcurl has no compiled-in CA bundle path. For OpenSSL the crate probes the system certificate locations with openssl-probe and sets CURLOPT_CAINFO/CURLOPT_CAPATH on every handle; the rustls backend was left out, although it reads its roots from the same options. libcurl only falls back to rustls' platform verifier when CURLSSLOPT_NATIVE_CA is set, and without either it builds a client config with no verifier. So rustls + static-curl failed every HTTPS request unless the program set cainfo itself:

SSL connect error (35): failed to build client config: no server certificate verifier was configured on the client config builder

This runs the probe for the rustls backends as well. It is a separate commit, since it is an independent fix for the existing rustls feature.

Tested

On Linux x86_64, with static-curl:

  • --features rustls-ring: examples/https fetches https://example.com, cargo test passes.
  • --features rustls (aws-lc): examples/https fetches https://example.com.
  • --features rustls-ring without the second commit: examples/https fails with the error above.

rustls-ffi defaults to aws-lc-rs, which needs cmake (and a C/C++
toolchain for the target) at build time and seeds its RNG from CPU
jitter at startup. The jitter seeding alone costs hundreds of
milliseconds of CPU per process on slow ARM cores, which matters for
short-lived programs; the cmake requirement makes cross-compiling, for
example to a static musl target, harder than it needs to be.

`rustls-ring` selects rustls-ffi's `ring` feature instead. ring is
pure Rust plus assembly, builds with cargo alone, and has no startup
cost.

rustls-ffi's default features are now off in curl-sys and the `rustls`
feature enables them explicitly (`aws-lc-rs` and
`prefer-post-quantum`), so existing `rustls` users get exactly the
provider they had before. The C side is the same for both features, so
`rustls-ring` compiles the same vtls backend.
With `static-curl`, the bundled libcurl has no compiled-in CA bundle
path. For OpenSSL the crate handles that by probing the system
certificate locations with openssl-probe and setting CURLOPT_CAINFO /
CURLOPT_CAPATH on every easy handle. The rustls backend was left out,
although it reads its roots from the same options: libcurl only falls
back to rustls' platform verifier when CURLSSLOPT_NATIVE_CA is set,
and without either it builds a client config with no verifier at all.

A `rustls` + `static-curl` build therefore failed every HTTPS request
unless the program set `cainfo` itself:

    SSL connect error (35): failed to build client config: no server
    certificate verifier was configured on the client config builder

Run the probe for the rustls backends as well. With it the `https`
example works on both `rustls` and `rustls-ring` with `static-curl`.
CarloTUM added a commit to CarloTUM/curlite-bench that referenced this pull request Oct 11, 2026
The rustls-ring feature is sagebind/curl-rust#687; the minimal feature
(an HTTP(S)-only libcurl, used by build-lean.sh) is not proposed
upstream and lives on the fork branch rustls-ring-minimal. Both come in
through [patch.crates-io] pinned to a commit, which drops the 801
vendored files and makes it clear which numbers depend on what.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant