max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
13 files changed,
+51 insertions,
-55 deletions
| @@ -781,29 +781,6 @@ | |||
| 781 | 781 | "zeroize", | |
| 782 | 782 | ] | |
| 783 | 783 | ||
| 784 | - | [[package]] | |
| 785 | - | name = "aws-lc-rs" | |
| 786 | - | version = "1.17.1" | |
| 787 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 788 | - | checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" | |
| 789 | - | dependencies = [ | |
| 790 | - | "aws-lc-sys", | |
| 791 | - | "zeroize", | |
| 792 | - | ] | |
| 793 | - | ||
| 794 | - | [[package]] | |
| 795 | - | name = "aws-lc-sys" | |
| 796 | - | version = "0.42.0" | |
| 797 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 798 | - | checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" | |
| 799 | - | dependencies = [ | |
| 800 | - | "cc", | |
| 801 | - | "cmake", | |
| 802 | - | "dunce", | |
| 803 | - | "fs_extra", | |
| 804 | - | "pkg-config", | |
| 805 | - | ] | |
| 806 | - | ||
| 807 | 784 | [[package]] | |
| 808 | 785 | name = "aws-runtime" | |
| 809 | 786 | version = "1.7.5" | |
| @@ -1705,15 +1682,6 @@ | |||
| 1705 | 1682 | "hashbrown 0.16.1", | |
| 1706 | 1683 | ] | |
| 1707 | 1684 | ||
| 1708 | - | [[package]] | |
| 1709 | - | name = "cmake" | |
| 1710 | - | version = "0.1.58" | |
| 1711 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1712 | - | checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" | |
| 1713 | - | dependencies = [ | |
| 1714 | - | "cc", | |
| 1715 | - | ] | |
| 1716 | - | ||
| 1717 | 1685 | [[package]] | |
| 1718 | 1686 | name = "cmov" | |
| 1719 | 1687 | version = "0.5.4" | |
| @@ -3062,12 +3030,6 @@ | |||
| 3062 | 3030 | "winapi", | |
| 3063 | 3031 | ] | |
| 3064 | 3032 | ||
| 3065 | - | [[package]] | |
| 3066 | - | name = "fs_extra" | |
| 3067 | - | version = "1.3.0" | |
| 3068 | - | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3069 | - | checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" | |
| 3070 | - | ||
| 3071 | 3033 | [[package]] | |
| 3072 | 3034 | name = "funty" | |
| 3073 | 3035 | version = "2.0.0" | |
| @@ -6601,7 +6563,6 @@ | |||
| 6601 | 6563 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6602 | 6564 | checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" | |
| 6603 | 6565 | dependencies = [ | |
| 6604 | - | "aws-lc-rs", | |
| 6605 | 6566 | "bytes", | |
| 6606 | 6567 | "getrandom 0.3.4", | |
| 6607 | 6568 | "lru-slab", | |
| @@ -7002,7 +6963,6 @@ | |||
| 7002 | 6963 | "mime", | |
| 7003 | 6964 | "percent-encoding", | |
| 7004 | 6965 | "pin-project-lite", | |
| 7005 | - | "quinn", | |
| 7006 | 6966 | "rustls", | |
| 7007 | 6967 | "rustls-pki-types", | |
| 7008 | 6968 | "rustls-platform-verifier", | |
| @@ -7203,7 +7163,6 @@ | |||
| 7203 | 7163 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 7204 | 7164 | checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" | |
| 7205 | 7165 | dependencies = [ | |
| 7206 | - | "aws-lc-rs", | |
| 7207 | 7166 | "log", | |
| 7208 | 7167 | "once_cell", | |
| 7209 | 7168 | "ring", | |
| @@ -7290,7 +7249,6 @@ | |||
| 7290 | 7249 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 7291 | 7250 | checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" | |
| 7292 | 7251 | dependencies = [ | |
| 7293 | - | "aws-lc-rs", | |
| 7294 | 7252 | "ring", | |
| 7295 | 7253 | "rustls-pki-types", | |
| 7296 | 7254 | "untrusted", |
| @@ -86,7 +86,7 @@ | |||
| 86 | 86 | # Security | |
| 87 | 87 | # Direct only so `crypto::install_default_crypto_provider` can name a provider; | |
| 88 | 88 | # every TLS client here reaches rustls transitively. | |
| 89 | - | rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs"] } | |
| 89 | + | rustls = { version = "0.23", default-features = false, features = ["ring"] } | |
| 90 | 90 | rand = "0.10" | |
| 91 | 91 | hmac = "0.13.0" | |
| 92 | 92 | sha1 = "0.11.0" | |
| @@ -164,7 +164,7 @@ | |||
| 164 | 164 | # reqwest's platform verifier elsewhere in the tree) and carries the `__hyper` | |
| 165 | 165 | # feature the client needs; the provider must be named separately or | |
| 166 | 166 | # async-stripe's connector.rs refuses to compile. | |
| 167 | - | async-stripe = { version = "1.0.0-rc.6", default-features = false, features = ["rustls-tls-native", "rustls-aws-lc-rs"] } | |
| 167 | + | async-stripe = { version = "1.0.0-rc.6", default-features = false, features = ["rustls-tls-native", "rustls-ring"] } | |
| 168 | 168 | async-stripe-shared = { version = "1.0.0-rc.6", features = ["deserialize"] } | |
| 169 | 169 | async-stripe-billing = { version = "1.0.0-rc.6", features = ["deserialize", "subscription", "billing_portal_session"] } | |
| 170 | 170 | async-stripe-checkout = { version = "1.0.0-rc.6", features = ["deserialize", "checkout_session"] } | |
| @@ -173,7 +173,16 @@ | |||
| 173 | 173 | async-stripe-payment = { version = "1.0.0-rc.6", features = ["deserialize"] } | |
| 174 | 174 | async-stripe-product = { version = "1.0.0-rc.6", features = ["deserialize", "product", "price"] } | |
| 175 | 175 | async-stripe-types = { version = "1.0.0-rc.6", features = ["deserialize"] } | |
| 176 | - | reqwest = { version = "0.13", features = ["json", "cookies", "form", "query"] } | |
| 176 | + | # reqwest 0.13's `rustls` feature is an alias for `__rustls-aws-lc-rs` and there | |
| 177 | + | # is no ring counterpart, so the default feature set is what would drag the C | |
| 178 | + | # backend back in. `rustls-no-provider` keeps the platform verifier and lets | |
| 179 | + | # `crypto::install_default_crypto_provider` supply ring; the rest of this list is | |
| 180 | + | # reqwest's own default set (`charset`, `http2`, `system-proxy`) restated, since | |
| 181 | + | # naming a TLS feature means turning defaults off. | |
| 182 | + | reqwest = { version = "0.13", default-features = false, features = [ | |
| 183 | + | "json", "cookies", "form", "query", | |
| 184 | + | "charset", "http2", "system-proxy", "rustls-no-provider", | |
| 185 | + | ] } | |
| 177 | 186 | urlencoding = "2.1.3" | |
| 178 | 187 | ||
| 179 | 188 | # URL parsing |
| @@ -9,16 +9,26 @@ | |||
| 9 | 9 | /// TLS connection. | |
| 10 | 10 | /// | |
| 11 | 11 | /// rustls 0.23 picks a provider from its own crate features, and refuses to | |
| 12 | - | /// guess when more than one is compiled in. Both are: `aws-lc-rs` arrives with | |
| 13 | - | /// rustls itself, `ring` through apple-codesign's signing stack. So the | |
| 14 | - | /// automatic path panics, and it panics lazily, at the first connector build | |
| 15 | - | /// rather than at startup. That put the failure on the Stripe path, which is | |
| 16 | - | /// the worst place to discover it. | |
| 12 | + | /// guess when more than one is compiled in. That refusal is a lazy panic at the | |
| 13 | + | /// first connector build rather than an error at startup, which once put the | |
| 14 | + | /// failure on the Stripe path — the worst place to discover it. Naming a | |
| 15 | + | /// provider here makes the choice explicit and moves any failure to process | |
| 16 | + | /// start. | |
| 17 | 17 | /// | |
| 18 | - | /// Naming a provider here makes the choice explicit and moves the failure to | |
| 19 | - | /// process start. Every other rustls consumer in the tree (reqwest via | |
| 20 | - | /// `rustls-platform-verifier`, the AWS SDK) selects its own provider directly | |
| 21 | - | /// and is unaffected either way. | |
| 18 | + | /// `ring` is the provider because the tree's standing choice is the most-Rust | |
| 19 | + | /// backend on offer (`rust_crypto` > `ring` > `aws-lc-rs`), and rustls does not | |
| 20 | + | /// offer `rust_crypto` at this layer. Keeping `aws-lc-rs` out matters beyond | |
| 21 | + | /// taste: it is a C backend, so it would put a C toolchain on the build path | |
| 22 | + | /// for every architecture built natively, and it is what stops miri from ever | |
| 23 | + | /// reaching a verdict here. | |
| 24 | + | /// | |
| 25 | + | /// reqwest depends on this call. It is declared `rustls-no-provider`, which is | |
| 26 | + | /// the only way to keep `aws-lc-rs` out of the graph — its `rustls` feature is | |
| 27 | + | /// a hard alias for `__rustls-aws-lc-rs`, and cargo unifies features, so one | |
| 28 | + | /// consumer asking for it puts the C backend in every binary here. The cost is | |
| 29 | + | /// that `reqwest::Client::builder().build()` panics outright when no provider | |
| 30 | + | /// is installed, so every client constructor in this crate calls this first | |
| 31 | + | /// rather than trusting boot order. The AWS SDK still selects its own. | |
| 22 | 32 | /// | |
| 23 | 33 | /// Idempotent: a second call is a no-op, so tests can call it per-case without | |
| 24 | 34 | /// racing. Not `expect`-ing the result is deliberate. `install_default` returns | |
| @@ -27,7 +37,7 @@ | |||
| 27 | 37 | /// | |
| 28 | 38 | /// [`CryptoProvider`]: rustls::crypto::CryptoProvider | |
| 29 | 39 | pub fn install_default_crypto_provider() { | |
| 30 | - | let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); | |
| 40 | + | let _ = rustls::crypto::ring::default_provider().install_default(); | |
| 31 | 41 | } | |
| 32 | 42 | ||
| 33 | 43 | /// Version-tagged prefix on an encrypted-at-rest TOTP secret. Its presence is |
| @@ -93,6 +93,10 @@ | |||
| 93 | 93 | impl MtClient { | |
| 94 | 94 | /// Create a new MT client with the given base URL and shared secret. | |
| 95 | 95 | pub fn new(base_url: String, secret: String) -> Self { | |
| 96 | + | // `build()` constructs the rustls connector, which reads the | |
| 97 | + | // process-wide provider and panics if none is installed. Idempotent. | |
| 98 | + | crate::crypto::install_default_crypto_provider(); | |
| 99 | + | ||
| 96 | 100 | let http = reqwest::Client::builder() | |
| 97 | 101 | .timeout(std::time::Duration::from_secs(5)) | |
| 98 | 102 | .connect_timeout(std::time::Duration::from_secs(3)) |
| @@ -31,6 +31,10 @@ | |||
| 31 | 31 | /// Build a client for `base_url`. `token`, when `Some`, is sent as a bearer | |
| 32 | 32 | /// token on every request (matching WAM's shared-secret auth). | |
| 33 | 33 | pub fn new(base_url: String, token: Option<String>) -> Self { | |
| 34 | + | // `build()` constructs the rustls connector, which reads the | |
| 35 | + | // process-wide provider and panics if none is installed. Idempotent. | |
| 36 | + | crate::crypto::install_default_crypto_provider(); | |
| 37 | + | ||
| 34 | 38 | let http = reqwest::Client::builder() | |
| 35 | 39 | .timeout(std::time::Duration::from_secs(5)) | |
| 36 | 40 | .connect_timeout(std::time::Duration::from_secs(3)) |
| @@ -17,6 +17,10 @@ | |||
| 17 | 17 | ||
| 18 | 18 | impl TestClient { | |
| 19 | 19 | fn new() -> Self { | |
| 20 | + | // reqwest is `rustls-no-provider`, so building a client without a | |
| 21 | + | // process-wide provider panics. Idempotent; see `crypto`'s own docs. | |
| 22 | + | makenotwork::crypto::install_default_crypto_provider(); | |
| 23 | + | ||
| 20 | 24 | TestClient { | |
| 21 | 25 | client: reqwest::Client::builder() | |
| 22 | 26 | .timeout(Duration::from_secs(10)) |
| @@ -360,6 +360,7 @@ | |||
| 360 | 360 | ||
| 361 | 361 | impl PostmarkTransport { | |
| 362 | 362 | fn new(config: EmailConfig, pool: Option<sqlx::PgPool>) -> Self { | |
| 363 | + | crate::crypto::install_default_crypto_provider(); | |
| 363 | 364 | let http_client = reqwest::Client::builder() | |
| 364 | 365 | .timeout(std::time::Duration::from_secs(10)) | |
| 365 | 366 | .build() |
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | /// call sites may still set a tighter per-request `.timeout()`, which wins. | |
| 14 | 14 | /// (Clients that need custom config, like Postmark and the PoM probe, keep their own.) | |
| 15 | 15 | pub static HTTP_CLIENT: std::sync::LazyLock<reqwest::Client> = std::sync::LazyLock::new(|| { | |
| 16 | + | crate::crypto::install_default_crypto_provider(); | |
| 16 | 17 | reqwest::Client::builder() | |
| 17 | 18 | .timeout(std::time::Duration::from_secs(10)) | |
| 18 | 19 | .build() |
| @@ -54,6 +54,7 @@ | |||
| 54 | 54 | async fn query_hash(sha256: &str, auth_key: &str) -> Result<LayerResult, String> { | |
| 55 | 55 | // Explicit request + connect timeouts (Perf-S2); a default client has neither. | |
| 56 | 56 | static CLIENT: std::sync::LazyLock<reqwest::Client> = std::sync::LazyLock::new(|| { | |
| 57 | + | crate::crypto::install_default_crypto_provider(); | |
| 57 | 58 | reqwest::Client::builder() | |
| 58 | 59 | .timeout(std::time::Duration::from_secs( | |
| 59 | 60 | crate::constants::SCAN_MALWAREBAZAAR_TIMEOUT_SECS, |
| @@ -63,6 +63,7 @@ | |||
| 63 | 63 | async fn query_hash(sha256: &str, api_key: &str) -> Result<LayerResult, String> { | |
| 64 | 64 | // Explicit request + connect timeouts (Perf-S2); a default client has neither. | |
| 65 | 65 | static CLIENT: std::sync::LazyLock<reqwest::Client> = std::sync::LazyLock::new(|| { | |
| 66 | + | crate::crypto::install_default_crypto_provider(); | |
| 66 | 67 | reqwest::Client::builder() | |
| 67 | 68 | .timeout(std::time::Duration::from_secs( | |
| 68 | 69 | crate::constants::SCAN_MALWAREBAZAAR_TIMEOUT_SECS, |
| @@ -124,6 +124,7 @@ | |||
| 124 | 124 | // so a hung host could block past the layer's own per-host timeout. Falls back | |
| 125 | 125 | // to a default client only if the builder somehow fails. | |
| 126 | 126 | static CLIENT: std::sync::LazyLock<reqwest::Client> = std::sync::LazyLock::new(|| { | |
| 127 | + | crate::crypto::install_default_crypto_provider(); | |
| 127 | 128 | reqwest::Client::builder() | |
| 128 | 129 | .timeout(Duration::from_secs( | |
| 129 | 130 | constants::SCAN_MALWAREBAZAAR_TIMEOUT_SECS, |