From 6bbaa1b12a123125a04618b32532940e2c34fb2a Mon Sep 17 00:00:00 2001 From: CarloTUM Date: Sat, 10 Oct 2026 22:45:30 +0200 Subject: [PATCH 1/2] Add rustls-ring feature: rustls backend 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. 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. --- Cargo.toml | 1 + README.md | 3 +++ curl-sys/Cargo.toml | 4 +++- curl-sys/build.rs | 2 +- curl-sys/lib.rs | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc46a6e66..b66acf35e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ mesalink = ["curl-sys/mesalink"] # MesaLink TLS backend http2 = ["curl-sys/http2"] spnego = ["curl-sys/spnego"] rustls = ["curl-sys/rustls"] +rustls-ring = ["curl-sys/rustls-ring"] static-curl = ["curl-sys/static-curl"] apple-sectrust = ["ssl", "static-curl", "curl-sys/apple-sectrust"] static-ssl = ["curl-sys/static-ssl"] diff --git a/README.md b/README.md index d0911bea9..2175e21c4 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,8 @@ with various Cargo features: Note that Rustls support is experimental within Curl itself and may have significant bugs, so we don't offer any sort of stability guarantee with this feature. +- `rustls-ring`: Like `rustls`, but with [ring] as the crypto provider instead of aws-lc-rs. ring needs no cmake at build time and no CPU jitter entropy seeding at startup, which makes it the better fit for cross-compiled and short-lived programs. Disabled by default. + - `http2`: Enable HTTP/2 support via libnghttp2. Disabled by default. - `static-curl`: Use a bundled libcurl version and statically link to it. Disabled by default. - `apple-sectrust`: Use Apple SecTrust for certificate verification with bundled libcurl and OpenSSL on Apple platforms. Implies `ssl` and `static-curl`. Disabled by default. @@ -183,5 +185,6 @@ details. [libcurl]: https://curl.haxx.se/libcurl/ [OpenSSL]: https://www.openssl.org/ [Rustls]: https://github.com/ctz/rustls +[ring]: https://github.com/briansmith/ring [Schannel]: https://docs.microsoft.com/en-us/windows/win32/com/schannel [Secure Transport]: https://developer.apple.com/documentation/security/secure_transport diff --git a/curl-sys/Cargo.toml b/curl-sys/Cargo.toml index b6663832c..8b8a8e7ec 100644 --- a/curl-sys/Cargo.toml +++ b/curl-sys/Cargo.toml @@ -29,6 +29,7 @@ libnghttp2-sys = { optional = true, version = "0.1.3" } version = "0.15" optional = true features = ["no_log_capture"] +default-features = false [target.'cfg(all(unix))'.dependencies] openssl-sys = { workspace = true, optional = true } @@ -48,7 +49,8 @@ default = ["ssl"] ssl = ["openssl-sys"] http2 = ["libnghttp2-sys"] mesalink = [] -rustls = ["rustls-ffi"] +rustls = ["rustls-ffi", "rustls-ffi/aws-lc-rs", "rustls-ffi/prefer-post-quantum"] +rustls-ring = ["rustls-ffi", "rustls-ffi/ring"] static-curl = [] apple-sectrust = ["ssl", "static-curl"] windows-static-ssl = [] diff --git a/curl-sys/build.rs b/curl-sys/build.rs index 7d028d410..9eb5faf1f 100644 --- a/curl-sys/build.rs +++ b/curl-sys/build.rs @@ -350,7 +350,7 @@ fn main() { // Configure TLS backend. Since Cargo does not support mutually exclusive // features, make sure we only compile one vtls. - if cfg!(feature = "rustls") { + if cfg!(any(feature = "rustls", feature = "rustls-ring")) { cfg.define("USE_RUSTLS", None) .file("curl/lib/vtls/cipher_suite.c") .file("curl/lib/vtls/rustls.c") diff --git a/curl-sys/lib.rs b/curl-sys/lib.rs index 5e5b10c28..ea89febc5 100644 --- a/curl-sys/lib.rs +++ b/curl-sys/lib.rs @@ -8,7 +8,7 @@ extern crate libnghttp2_sys; extern crate libz_sys; #[cfg(link_openssl)] extern crate openssl_sys; -#[cfg(feature = "rustls")] +#[cfg(any(feature = "rustls", feature = "rustls-ring"))] extern crate rustls_ffi; use libc::c_ulong; From 3162984405a80039963707495a3f144b7a65f17d Mon Sep 17 00:00:00 2001 From: CarloTUM Date: Sat, 10 Oct 2026 22:45:30 +0200 Subject: [PATCH 2/2] Probe for CA certificate paths on static rustls builds too 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`. --- Cargo.toml | 4 ++-- build.rs | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b66acf35e..67e61401f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,8 +49,8 @@ ssl = ["openssl-sys", "openssl-probe", "curl-sys/ssl"] # OpenSSL/system TLS back mesalink = ["curl-sys/mesalink"] # MesaLink TLS backend http2 = ["curl-sys/http2"] spnego = ["curl-sys/spnego"] -rustls = ["curl-sys/rustls"] -rustls-ring = ["curl-sys/rustls-ring"] +rustls = ["curl-sys/rustls", "openssl-probe"] +rustls-ring = ["curl-sys/rustls-ring", "openssl-probe"] static-curl = ["curl-sys/static-curl"] apple-sectrust = ["ssl", "static-curl", "curl-sys/apple-sectrust"] static-ssl = ["curl-sys/static-ssl"] diff --git a/build.rs b/build.rs index adfa73ef3..d0f9bb216 100644 --- a/build.rs +++ b/build.rs @@ -20,7 +20,14 @@ fn main() { Err(_) => false, }; - if use_openssl { + // libcurl's rustls backend loads its roots from CURLOPT_CAINFO / CAPATH as + // well (it only uses the platform verifier when CURLSSLOPT_NATIVE_CA is + // set), so a static build on rustls needs the probe as much as one on + // OpenSSL. + let use_rustls = env::var_os("CARGO_FEATURE_RUSTLS").is_some() + || env::var_os("CARGO_FEATURE_RUSTLS_RING").is_some(); + + if use_openssl || use_rustls { let apple_sectrust = env::var_os("CARGO_FEATURE_APPLE_SECTRUST").is_some() && env::var("CARGO_CFG_TARGET_VENDOR").ok().as_deref() == Some("apple");