diff --git a/twilight-gateway/Cargo.toml b/twilight-gateway/Cargo.toml index 862fdc463e..b9f892291e 100644 --- a/twilight-gateway/Cargo.toml +++ b/twilight-gateway/Cargo.toml @@ -21,7 +21,7 @@ futures-sink = { default-features = false, features = ["std"], version = "0.3" } serde = { default-features = false, features = ["derive"], version = "1" } serde_json = { default-features = false, features = ["std"], version = "1" } tokio = { default-features = false, features = ["net", "rt", "sync", "time"], version = "1.19" } -tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.7" } +tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.10" } tracing = { default-features = false, features = ["std", "attributes"], version = "0.1" } twilight-gateway-queue = { default-features = false, path = "../twilight-gateway-queue", version = "0.16.0-rc.1" } twilight-model = { default-features = false, path = "../twilight-model", version = "0.16.0-rc.1" } @@ -44,10 +44,14 @@ tokio-stream = { default-features = false, version = "0.1" } tracing-subscriber = { default-features = false, features = ["fmt", "tracing-log"], version = "0.3" } [features] -default = ["rustls-native-roots", "twilight-http", "zlib-stock"] +default = ["rustls-platform-verifier", "rustls-ring", "twilight-http", "zlib-stock"] native-tls = ["tokio-websockets/native-tls", "tokio-websockets/openssl"] -rustls-native-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-native-roots"] -rustls-webpki-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-webpki-roots"] +rustls-platform-verifier = ["tokio-websockets/rustls-platform-verifier"] +rustls-native-roots = ["tokio-websockets/rustls-native-roots"] +rustls-webpki-roots = ["tokio-websockets/rustls-webpki-roots"] +rustls-ring = ["tokio-websockets/ring"] +rustls-aws_lc_rs = ["tokio-websockets/aws_lc_rs"] +rustls-aws-lc-rs = ["rustls-aws_lc_rs"] # Alias for convenience, underscores are preferred in the rustls stack zlib-simd = ["dep:flate2", "flate2?/zlib-ng"] zlib-stock = ["dep:flate2", "flate2?/zlib"] diff --git a/twilight-gateway/README.md b/twilight-gateway/README.md index 111a401b7f..e01e9eadcb 100644 --- a/twilight-gateway/README.md +++ b/twilight-gateway/README.md @@ -23,9 +23,17 @@ from a `Fn(ShardId, ConfigBuilder) -> Config` closure, with the help of the events * TLS (mutually exclusive) * `native-tls`: platform's native TLS implementation via [`native-tls`] - * `rustls-native-roots` (*default*): [`rustls`] using native root certificates + * `rustls-native-roots`: [`rustls`] using native root certificates + * `rustls-platform-verifier` (*default*): [`rustls`] using operating system's + certificate facilities via [`rustls-platform-verifier`] * `rustls-webpki-roots`: [`rustls`] using [`webpki-roots`] for root certificates, useful for `scratch` containers +* Crypto providers (required with [`rustls`]) + * `rustls-ring` (*default*): [`ring`] as the crypto provider, recommended for + compatibility + * `rustls-aws_lc_rs`: [`aws-lc-rs`] as the crypto provider, recommended for + performance and widely used platforms + * none of the above: install your own via [`CryptoProvider::install_default`] * `twilight-http` (*default*): enable the `stream::create_recommended` function * Zlib (mutually exclusive) * `zlib-stock` (*default*): [`flate2`]'s stock zlib implementation @@ -104,9 +112,13 @@ async fn runner(mut shard: Shard) { There are a few additional examples located in the [repository][github examples link]. +[`CryptoProvider::install_default`]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#method.install_default +[`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs [`flate2`]: https://crates.io/crates/flate2 [`native-tls`]: https://crates.io/crates/native-tls +[`ring`]: https://crates.io/crates/ring [`rustls`]: https://crates.io/crates/rustls +[`rustls-platform-verifier`]: https://crates.io/crates/rustls-platform-verifier [`serde_json`]: https://crates.io/crates/serde_json [`simd-json`]: https://crates.io/crates/simd-json [`webpki-roots`]: https://crates.io/crates/webpki-roots diff --git a/twilight-gateway/src/shard.rs b/twilight-gateway/src/shard.rs index 0800295444..e6fc1f2aec 100644 --- a/twilight-gateway/src/shard.rs +++ b/twilight-gateway/src/shard.rs @@ -24,6 +24,7 @@ use serde::{de::DeserializeOwned, Deserialize}; #[cfg(any( feature = "native-tls", feature = "rustls-native-roots", + feature = "rustls-platform-verifier", feature = "rustls-webpki-roots" ))] use std::io::ErrorKind as IoErrorKind; @@ -916,6 +917,7 @@ impl Stream for Shard { #[cfg(any( feature = "native-tls", feature = "rustls-native-roots", + feature = "rustls-platform-verifier", feature = "rustls-webpki-roots" ))] Some(Err(WebsocketError::Io(e))) diff --git a/twilight-http/Cargo.toml b/twilight-http/Cargo.toml index d2f6240d9e..1c7717fe83 100644 --- a/twilight-http/Cargo.toml +++ b/twilight-http/Cargo.toml @@ -19,10 +19,11 @@ http = { default-features = false, version = "1" } http-body-util = { default-features = false, version = "0.1" } hyper = { default-features = false, version = "1" } hyper-util = { default-features = false, features = ["client-legacy", "http1", "http2", "tokio"], version = "0.1.2" } -hyper-rustls = { default-features = false, optional = true, features = ["http1", "http2", "ring"], version = "0.26" } +hyper-rustls = { default-features = false, optional = true, features = ["http1", "http2"], version = "0.27.3" } hyper-tls = { default-features = false, optional = true, features = ["alpn"], version = "0.6" } hyper-hickory = { default-features = false, optional = true, version = "0.7" } percent-encoding = { default-features = false, version = "2" } +rustls = { default-features = false, optional = true, version = "0.23" } serde = { default-features = false, features = ["derive"], version = "1" } serde_json = { default-features = false, features = ["std"], version = "1" } tokio = { default-features = false, features = ["sync", "time"], version = "1.0" } @@ -36,12 +37,16 @@ brotli-decompressor = { default-features = false, features = ["std"], optional = simd-json = { default-features = false, features = ["serde_impl", "swar-number-parsing"], optional = true, version = ">=0.4, <0.14" } [features] -default = ["decompression", "rustls-native-roots"] +default = ["decompression", "rustls-platform-verifier", "rustls-ring"] decompression = ["dep:brotli-decompressor"] -native-tls = ["dep:hyper-tls"] -rustls-native-roots = ["dep:hyper-rustls", "hyper-rustls?/native-tokio"] -rustls-webpki-roots = ["dep:hyper-rustls", "hyper-rustls?/webpki-tokio"] hickory = ["dep:hyper-hickory"] +native-tls = ["dep:hyper-tls"] +rustls-platform-verifier = ["dep:hyper-rustls", "dep:rustls", "hyper-rustls?/rustls-platform-verifier"] +rustls-native-roots = ["dep:hyper-rustls", "dep:rustls", "hyper-rustls?/native-tokio"] +rustls-webpki-roots = ["dep:hyper-rustls", "dep:rustls", "hyper-rustls?/webpki-tokio"] +rustls-ring = ["hyper-rustls?/ring"] +rustls-aws_lc_rs = ["hyper-rustls?/aws-lc-rs"] +rustls-aws-lc-rs = ["rustls-aws_lc_rs"] # Alias for convenience, underscores are preferred in the rustls stack [dev-dependencies] serde_test = { default-features = false, version = "1" } diff --git a/twilight-http/README.md b/twilight-http/README.md index 71326e04f8..18ca87b94e 100644 --- a/twilight-http/README.md +++ b/twilight-http/README.md @@ -11,6 +11,27 @@ repository][github examples link]. ## Features +### Crypto provider + +Using [`rustls`] for TLS requires configuring a crypto provider via crate +features or manually installing a global default. The default is `rustls-ring`. + +#### `rustls-ring` + +The `rustls-ring` feature will enable the use of [`ring`] as the crypto +provider. This is recommended for platform compatibility. + +#### `rustls-aws_lc_rs` + +The `rustls-aws_lc_rs` feature will enable the use of [`aws-lc-rs`] as the +crypto provider. This is recommended for performance and on widely used +platforms. + +#### Manual installation + +If none of the other crypto providers are enabled, a custom one must be +installed by the application using [`CryptoProvider::install_default`]. + ### Decompression The `decompression` feature enables brotli decompression support via the [`brotli`] crate. @@ -53,7 +74,7 @@ twilight-http = { default-features = false, features = ["rustls-native-roots", " Discord's API is HTTPS only. `twilight-http` has features to enable HTTPS connectivity with [`hyper`]. These -features are mutually exclusive. `rustls-native-roots` is enabled by default. +features are mutually exclusive. `rustls-platform-verifier` is enabled by default. #### `native-tls` @@ -70,7 +91,13 @@ twilight-http = { default-features = false, features = ["native"], version = "0. The `rustls-native-roots` feature uses a HTTPS connector provided by [`hyper-rustls`], which uses [`rustls`] as the TLS backend, and enables its `native-tokio` feature, which uses [`rustls-native-certs`] -for root certificates. +for root certificates. This requires configuring a crypto provider. + +#### `rustls-platform-verifier` + +The `rustls-platform-verifier` feature uses a HTTPS connector provided by [`hyper-rustls`], which uses +[`rustls`] as the TLS backend, and enables its [`rustls-platform-verifier`] feature, which uses +[`rustls-platform-verifier`] for certificate validation. This requires configuring a crypto provider. This is enabled by default. @@ -78,7 +105,7 @@ This is enabled by default. The `rustls-webpki-roots` feature uses a HTTPS connector provided by [`hyper-rustls`], which uses [`rustls`] as the TLS backend, and enables its `webpki-tokio` feature, which uses [`webpki-roots`] -for root certificates. +for root certificates. This requires configuring a crypto provider. This should be preferred over `rustls-native-roots` in Docker containers based on `scratch`. @@ -88,13 +115,17 @@ The `hickory` feature enables [`hyper-hickory`], which replaces the default `GaiResolver` in [`hyper`]. [`hyper-hickory`] instead provides a fully async DNS resolver on the application level. +[`CryptoProvider::install_default`]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#method.install_default +[`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs [`brotli`]: https://github.com/dropbox/rust-brotli [`hyper`]: https://crates.io/crates/hyper [`hyper-hickory`]: https://crates.io/crates/hyper-hickory [`hyper-rustls`]: https://crates.io/crates/hyper-rustls [`hyper-tls`]: https://crates.io/crates/hyper-tls +[`ring`]: https://crates.io/crates/ring [`rustls`]: https://crates.io/crates/rustls [`rustls-native-certs`]: https://crates.io/crates/rustls-native-certs +[`rustls-platform-verifier`]: https://crates.io/crates/rustls-platform-verifier [`serde_json`]: https://crates.io/crates/serde_json [`simd-json`]: https://crates.io/crates/simd-json [`webpki-roots`]: https://crates.io/crates/webpki-roots diff --git a/twilight-http/src/client/connector.rs b/twilight-http/src/client/connector.rs index 1f04dfbef9..3e5b245238 100644 --- a/twilight-http/src/client/connector.rs +++ b/twilight-http/src/client/connector.rs @@ -1,12 +1,20 @@ //! HTTP connectors with different features. /// HTTPS connector using `rustls` as a TLS backend. -#[cfg(any(feature = "rustls-native-roots", feature = "rustls-webpki-roots"))] +#[cfg(any( + feature = "rustls-native-roots", + feature = "rustls-platform-verifier", + feature = "rustls-webpki-roots" +))] type HttpsConnector = hyper_rustls::HttpsConnector; /// HTTPS connector using `hyper-tls` as a TLS backend. #[cfg(all( feature = "native-tls", - not(any(feature = "rustls-native-roots", feature = "rustls-webpki-roots")) + not(any( + feature = "rustls-native-roots", + feature = "rustls-platform-verifier", + feature = "rustls-webpki-roots" + )) ))] type HttpsConnector = hyper_tls::HttpsConnector; @@ -21,13 +29,15 @@ type HttpConnector = hyper_util::client::legacy::connect::HttpConnector; #[cfg(any( feature = "native-tls", feature = "rustls-native-roots", - feature = "rustls-webpki-roots" + feature = "rustls-platform-verifier", + feature = "rustls-webpki-roots", ))] pub type Connector = HttpsConnector; /// Re-exported generic connector for use in the client. #[cfg(not(any( feature = "native-tls", feature = "rustls-native-roots", + feature = "rustls-platform-verifier", feature = "rustls-webpki-roots" )))] pub type Connector = HttpConnector; @@ -41,24 +51,59 @@ pub fn create() -> Connector { connector.enforce_http(false); - #[cfg(feature = "rustls-native-roots")] - let connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_native_roots() - .expect("no native root certificates found") - .https_or_http() - .enable_http1() - .enable_http2() - .wrap_connector(connector); - #[cfg(all(feature = "rustls-webpki-roots", not(feature = "rustls-native-roots")))] - let connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_webpki_roots() - .https_or_http() - .enable_http1() - .enable_http2() - .wrap_connector(connector); + #[cfg(any( + feature = "rustls-native-roots", + feature = "rustls-platform-verifier", + feature = "rustls-webpki-roots" + ))] + let connector = { + #[cfg(not(any(feature = "rustls-ring", feature = "rustls-aws_lc_rs")))] + let crypto_provider = rustls::crypto::CryptoProvider::get_default() + .expect("No default crypto provider installed or configured via crate features") + .clone(); + #[cfg(feature = "rustls-aws_lc_rs")] + let crypto_provider = rustls::crypto::aws_lc_rs::default_provider(); + #[cfg(all(feature = "rustls-ring", not(feature = "rustls-aws_lc_rs")))] + let crypto_provider = rustls::crypto::ring::default_provider(); + + #[cfg(all( + feature = "rustls-native-roots", + not(feature = "rustls-platform-verifier") + ))] + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_provider_and_native_roots(crypto_provider) + .expect("no native roots found") + .https_or_http() + .enable_http1() + .enable_http2() + .wrap_connector(connector); + #[cfg(feature = "rustls-platform-verifier")] + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_provider_and_platform_verifier(crypto_provider) + .expect("no usable cipher suites in crypto provider") + .https_or_http() + .enable_http1() + .enable_http2() + .wrap_connector(connector); + #[cfg(all( + feature = "rustls-webpki-roots", + not(any(feature = "rustls-native-roots", feature = "rustls-platform-verifier")) + ))] + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_provider_and_webpki_roots(crypto_provider) + .expect("no usable cipher suites in crypto provider") + .https_or_http() + .enable_http1() + .enable_http2() + .wrap_connector(connector); + + connector + }; + #[cfg(all( feature = "native-tls", not(feature = "rustls-native-roots"), + not(feature = "rustls-platform-verifier"), not(feature = "rustls-webpki-roots") ))] let connector = hyper_tls::HttpsConnector::new_with_connector(connector); diff --git a/twilight-lavalink/Cargo.toml b/twilight-lavalink/Cargo.toml index 9bab2dfb32..b119ec96a0 100644 --- a/twilight-lavalink/Cargo.toml +++ b/twilight-lavalink/Cargo.toml @@ -20,7 +20,7 @@ http = { default-features = false, version = "1" } serde = { default-features = false, features = ["derive", "std"], version = "1" } serde_json = { default-features = false, features = ["std"], version = "1" } tokio = { default-features = false, features = ["macros", "net", "rt", "sync", "time"], version = "1.0" } -tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.7" } +tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.10" } tracing = { default-features = false, features = ["std", "attributes"], version = "0.1" } twilight-model = { default-features = false, path = "../twilight-model", version = "0.16.0-rc.1" } @@ -37,11 +37,15 @@ twilight-gateway = { default-features = false, features = ["rustls-native-roots" twilight-http = { default-features = false, features = ["rustls-native-roots"], path = "../twilight-http", version = "0.16.0-rc.1" } [features] -default = ["http-support", "rustls-native-roots"] +default = ["http-support", "rustls-platform-verifier", "rustls-ring"] http-support = ["dep:percent-encoding"] native-tls = ["tokio-websockets/native-tls", "tokio-websockets/openssl"] -rustls-native-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-native-roots"] -rustls-webpki-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-webpki-roots"] +rustls-platform-verifier = ["tokio-websockets/rustls-platform-verifier"] +rustls-native-roots = ["tokio-websockets/rustls-native-roots"] +rustls-webpki-roots = ["tokio-websockets/rustls-webpki-roots"] +rustls-ring = ["tokio-websockets/ring"] +rustls-aws_lc_rs = ["tokio-websockets/aws_lc_rs"] +rustls-aws-lc-rs = ["rustls-aws_lc_rs"] # Alias for convenience, underscores are preferred in the rustls stack [package.metadata.docs.rs] all-features = true diff --git a/twilight-lavalink/README.md b/twilight-lavalink/README.md index 3800e077ba..b76a5e284c 100644 --- a/twilight-lavalink/README.md +++ b/twilight-lavalink/README.md @@ -20,11 +20,32 @@ with every Voice State Update and Voice Server Update you receive. The `http-support` feature adds support for the `http` module to return request types from the [`http`] crate. This is enabled by default. +### Crypto provider + +Using [`rustls`] for TLS requires configuring a crypto provider via crate +features or manually installing a global default. The default is `rustls-ring`. + +#### `rustls-ring` + +The `rustls-ring` feature will enable the use of [`ring`] as the crypto +provider. This is recommended for platform compatibility. + +#### `rustls-aws_lc_rs` + +The `rustls-aws_lc_rs` feature will enable the use of [`aws-lc-rs`] as the +crypto provider. This is recommended for performance and on widely used +platforms. + +#### Manual installation + +If none of the other crypto providers are enabled, a custom one must be +installed by the application using [`CryptoProvider::install_default`]. + ### TLS `twilight-lavalink` has features to enable [`tokio-websockets`]' TLS -features. These features are mutually exclusive. `rustls-native-roots` is enabled by -default. +features. These features are mutually exclusive. `rustls-platform-verifier` is +enabled by default. #### `native-tls` @@ -41,6 +62,13 @@ twilight-lavalink = { default-features = false, features = ["native-tls"], versi The `rustls-native-roots` feature enables [`tokio-websockets`]' `rustls-native-roots` feature, which uses [`rustls`] as the TLS backend and [`rustls-native-certs`] for root certificates. +This requires configuring a crypto provider. + +#### `rustls-platform-verifier` + +The `rustls-platform-verifier` feature enables [`tokio-websockets`]' `rustls-platform-verifier` +feature, which uses [`rustls`] as the TLS backend and [`rustls-platform-verifier`] for +certificate validation. This requires configuring a crypto provider. This is enabled by default. @@ -48,6 +76,7 @@ This is enabled by default. The `rustls-webpki-roots` feature enables [`tokio-websockets`]' `rustls-webpki-roots` feature, which uses [`rustls`] as the TLS backend and [`webpki-roots`] for root certificates. +This requires configuring a crypto provider. This should be preferred over `rustls-native-roots` in Docker containers based on `scratch`. @@ -104,9 +133,13 @@ There is also an example of a basic bot located in the [root of the `twilight` repository][github examples link]. [Lavalink]: https://github.com/freyacodes/Lavalink +[`CryptoProvider::install_default`]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#method.install_default +[`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs [`http`]: https://crates.io/crates/http +[`ring`]: https://crates.io/crates/ring [`rustls`]: https://crates.io/crates/rustls [`rustls-native-certs`]: https://crates.io/crates/rustls-native-certs +[`rustls-platform-verifier`]: https://crates.io/crates/rustls-platform-verifier [`tokio-websockets`]: https://crates.io/crates/tokio-websockets [`webpki-roots`]: https://crates.io/crates/webpki-roots [client]: Lavalink