From 2095dd4c26d148928b9600b8316d4353767bd780 Mon Sep 17 00:00:00 2001 From: Scott Fleener Date: Mon, 6 Jan 2025 16:36:03 +0000 Subject: [PATCH] Add aws-lc-rs as optional rustls backend This has a few benefits. Primarily this gives us a reasonable path to creating FIPS-enabled builds on architectures other than x86-64, as well as a path away from using BoringSSL as a backend. Additionally, rustls has been using the aws-lc-rs library as the default backend for a little while now, so this gives us the opportunity to stay in line with the most widely used option in the ecosystem. Signed-off-by: Scott Fleener --- Cargo.lock | 103 ++++++++++++++++++- Cargo.toml | 1 - linkerd/meshtls/Cargo.toml | 3 + linkerd/meshtls/rustls/Cargo.toml | 5 +- linkerd/meshtls/rustls/src/backend.rs | 11 ++ linkerd/meshtls/rustls/src/backend/aws_lc.rs | 15 +++ linkerd/meshtls/rustls/src/backend/ring.rs | 15 +++ linkerd/meshtls/rustls/src/creds.rs | 17 ++- linkerd/meshtls/rustls/src/creds/receiver.rs | 24 ++--- linkerd/meshtls/rustls/src/lib.rs | 1 + linkerd2-proxy/Cargo.toml | 6 +- linkerd2-proxy/src/main.rs | 7 +- 12 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 linkerd/meshtls/rustls/src/backend.rs create mode 100644 linkerd/meshtls/rustls/src/backend/aws_lc.rs create mode 100644 linkerd/meshtls/rustls/src/backend/ring.rs diff --git a/Cargo.lock b/Cargo.lock index aa1287dcbe..0220659603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,6 +153,49 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "aws-lc-fips-sys" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59057b878509d88952425fe694a2806e468612bde2d71943f3cd8034935b5032" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", + "regex", +] + +[[package]] +name = "aws-lc-rs" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f409eb70b561706bf8abba8ca9c112729c481595893fd06a2dd9af8ed8441148" +dependencies = [ + "aws-lc-fips-sys", + "aws-lc-sys", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8478a5c29ead3f3be14aff8a202ad965cf7da6856860041bfca271becf8ba48b" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "axum" version = "0.6.20" @@ -251,6 +294,29 @@ dependencies = [ "syn", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.4.2", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -291,7 +357,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ceced5be0047c7c48d77599535fd7f0a81c1b0f0a1e97e7eece24c45022bb481" dependencies = [ - "bindgen", + "bindgen 0.66.1", "cmake", "fs_extra", "fslock", @@ -494,6 +560,12 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.13.0" @@ -889,6 +961,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "hostname" version = "0.3.1" @@ -3010,6 +3091,12 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -3427,6 +3514,7 @@ version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -3457,6 +3545,7 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -4222,6 +4311,18 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "widestring" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 5f65dfabc5..7a5a100162 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,7 +105,6 @@ hyper = { version = "0.14.32", default-features = false } prost = { version = "0.12" } prost-types = { version = "0.12" } tokio-rustls = { version = "0.26", default-features = false, features = [ - "ring", "logging", ] } tonic = { version = "0.10", default-features = false } diff --git a/linkerd/meshtls/Cargo.toml b/linkerd/meshtls/Cargo.toml index 7e67a36ac3..a02c1b7c12 100644 --- a/linkerd/meshtls/Cargo.toml +++ b/linkerd/meshtls/Cargo.toml @@ -8,6 +8,9 @@ publish = false [features] rustls = ["linkerd-meshtls-rustls", "__has_any_tls_impls"] +rustls-ring = ["rustls", "linkerd-meshtls-rustls/ring"] +rustls-aws-lc = ["rustls", "linkerd-meshtls-rustls/aws-lc"] +rustls-aws-lc-fips = ["rustls-aws-lc", "linkerd-meshtls-rustls/aws-lc-fips"] boring = ["linkerd-meshtls-boring", "__has_any_tls_impls"] boring-fips = ["boring", "linkerd-meshtls-boring/fips"] # Enabled if *any* TLS impl is enabled. diff --git a/linkerd/meshtls/rustls/Cargo.toml b/linkerd/meshtls/rustls/Cargo.toml index b13ec1455f..16960249ce 100644 --- a/linkerd/meshtls/rustls/Cargo.toml +++ b/linkerd/meshtls/rustls/Cargo.toml @@ -7,13 +7,16 @@ edition = "2018" publish = false [features] +ring = ["tokio-rustls/ring", "rustls-webpki/ring"] +aws-lc = ["tokio-rustls/aws-lc-rs", "rustls-webpki/aws_lc_rs"] +aws-lc-fips = ["aws-lc", "tokio-rustls/fips"] test-util = ["linkerd-tls-test-util"] [dependencies] futures = { version = "0.3", default-features = false } ring = { version = "0.17", features = ["std"] } rustls-pemfile = "2.2" -rustls-webpki = { version = "0.102.8", features = ["std"] } +rustls-webpki = { version = "0.102.8", default-features = false, features = ["std"] } thiserror = "2" tokio = { version = "1", features = ["macros", "rt", "sync"] } tokio-rustls = { workspace = true } diff --git a/linkerd/meshtls/rustls/src/backend.rs b/linkerd/meshtls/rustls/src/backend.rs new file mode 100644 index 0000000000..fa99fa7dfa --- /dev/null +++ b/linkerd/meshtls/rustls/src/backend.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "aws-lc")] +mod aws_lc; +#[cfg(feature = "ring")] +mod ring; + +#[cfg(feature = "aws-lc")] +pub use aws_lc::{default_provider, SUPPORTED_SIG_ALGS, TLS_SUPPORTED_CIPHERSUITES}; +#[cfg(all(not(feature = "aws-lc"), feature = "ring"))] +pub use ring::{default_provider, SUPPORTED_SIG_ALGS, TLS_SUPPORTED_CIPHERSUITES}; +#[cfg(all(not(feature = "aws-lc"), not(feature = "ring")))] +compile_error!("No rustls backend enabled. Enabled one of the \"ring\" or \"aws-lc\" features"); diff --git a/linkerd/meshtls/rustls/src/backend/aws_lc.rs b/linkerd/meshtls/rustls/src/backend/aws_lc.rs new file mode 100644 index 0000000000..7ec99ff60a --- /dev/null +++ b/linkerd/meshtls/rustls/src/backend/aws_lc.rs @@ -0,0 +1,15 @@ +pub use aws_lc_rs::default_provider; +use tokio_rustls::rustls::{ + self, + crypto::{aws_lc_rs, WebPkiSupportedAlgorithms}, +}; + +pub static TLS_SUPPORTED_CIPHERSUITES: &[rustls::SupportedCipherSuite] = + &[rustls::crypto::aws_lc_rs::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256]; +pub static SUPPORTED_SIG_ALGS: &WebPkiSupportedAlgorithms = &WebPkiSupportedAlgorithms { + all: &[webpki::aws_lc_rs::ECDSA_P256_SHA256], + mapping: &[( + crate::creds::params::SIGNATURE_ALG_RUSTLS_SCHEME, + &[webpki::aws_lc_rs::ECDSA_P256_SHA256], + )], +}; diff --git a/linkerd/meshtls/rustls/src/backend/ring.rs b/linkerd/meshtls/rustls/src/backend/ring.rs new file mode 100644 index 0000000000..cdce7f6f5c --- /dev/null +++ b/linkerd/meshtls/rustls/src/backend/ring.rs @@ -0,0 +1,15 @@ +pub use ring::default_provider; +use tokio_rustls::rustls::{ + self, + crypto::{ring, WebPkiSupportedAlgorithms}, +}; + +pub static TLS_SUPPORTED_CIPHERSUITES: &[rustls::SupportedCipherSuite] = + &[rustls::crypto::ring::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256]; +pub static SUPPORTED_SIG_ALGS: &WebPkiSupportedAlgorithms = &WebPkiSupportedAlgorithms { + all: &[webpki::ring::ECDSA_P256_SHA256], + mapping: &[( + crate::creds::params::SIGNATURE_ALG_RUSTLS_SCHEME, + &[webpki::ring::ECDSA_P256_SHA256], + )], +}; diff --git a/linkerd/meshtls/rustls/src/creds.rs b/linkerd/meshtls/rustls/src/creds.rs index cd0fe7f2c1..48614954e4 100644 --- a/linkerd/meshtls/rustls/src/creds.rs +++ b/linkerd/meshtls/rustls/src/creds.rs @@ -2,6 +2,8 @@ mod receiver; mod store; pub(crate) mod verify; +use crate::backend; + pub use self::{receiver::Receiver, store::Store}; use linkerd_dns_name as dns; use linkerd_error::Result; @@ -91,7 +93,7 @@ pub fn watch( } fn default_provider() -> CryptoProvider { - let mut provider = rustls::crypto::ring::default_provider(); + let mut provider = backend::default_provider(); provider.cipher_suites = params::TLS_SUPPORTED_CIPHERSUITES.to_vec(); provider } @@ -111,7 +113,8 @@ pub fn default_for_test() -> (Store, Receiver) { for_test(&linkerd_tls_test_util::FOO_NS1) } -mod params { +pub(crate) mod params { + use crate::backend; use tokio_rustls::rustls::{self, crypto::WebPkiSupportedAlgorithms}; // These must be kept in sync: @@ -121,14 +124,8 @@ mod params { rustls::SignatureScheme::ECDSA_NISTP256_SHA256; pub const SIGNATURE_ALG_RUSTLS_ALGORITHM: rustls::SignatureAlgorithm = rustls::SignatureAlgorithm::ECDSA; - pub static SUPPORTED_SIG_ALGS: &WebPkiSupportedAlgorithms = &WebPkiSupportedAlgorithms { - all: &[webpki::ring::ECDSA_P256_SHA256], - mapping: &[( - SIGNATURE_ALG_RUSTLS_SCHEME, - &[webpki::ring::ECDSA_P256_SHA256], - )], - }; + pub static SUPPORTED_SIG_ALGS: &WebPkiSupportedAlgorithms = backend::SUPPORTED_SIG_ALGS; pub static TLS_VERSIONS: &[&rustls::SupportedProtocolVersion] = &[&rustls::version::TLS13]; pub static TLS_SUPPORTED_CIPHERSUITES: &[rustls::SupportedCipherSuite] = - &[rustls::crypto::ring::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256]; + backend::TLS_SUPPORTED_CIPHERSUITES; } diff --git a/linkerd/meshtls/rustls/src/creds/receiver.rs b/linkerd/meshtls/rustls/src/creds/receiver.rs index fd451fbef8..2efe0cd6ea 100644 --- a/linkerd/meshtls/rustls/src/creds/receiver.rs +++ b/linkerd/meshtls/rustls/src/creds/receiver.rs @@ -70,13 +70,11 @@ mod tests { /// incoming handshakes, but that doesn't matter for these tests, where we /// don't actually do any TLS. fn empty_server_config() -> rustls::ServerConfig { - rustls::ServerConfig::builder_with_provider(Arc::new( - rustls::crypto::ring::default_provider(), - )) - .with_protocol_versions(rustls::ALL_VERSIONS) - .expect("client config must be valid") - .with_client_cert_verifier(Arc::new(rustls::server::NoClientAuth)) - .with_cert_resolver(Arc::new(rustls::server::ResolvesServerCertUsingSni::new())) + rustls::ServerConfig::builder_with_provider(Arc::new(crate::backend::default_provider())) + .with_protocol_versions(rustls::ALL_VERSIONS) + .expect("client config must be valid") + .with_client_cert_verifier(Arc::new(rustls::server::NoClientAuth)) + .with_cert_resolver(Arc::new(rustls::server::ResolvesServerCertUsingSni::new())) } /// Returns the simplest default rustls client config. @@ -85,13 +83,11 @@ mod tests { /// it doesn't trust any root certificates. However, that doesn't actually /// matter for these tests, which don't actually do TLS. fn empty_client_config() -> rustls::ClientConfig { - rustls::ClientConfig::builder_with_provider(Arc::new( - rustls::crypto::ring::default_provider(), - )) - .with_protocol_versions(rustls::ALL_VERSIONS) - .expect("client config must be valid") - .with_root_certificates(rustls::RootCertStore::empty()) - .with_no_client_auth() + rustls::ClientConfig::builder_with_provider(Arc::new(crate::backend::default_provider())) + .with_protocol_versions(rustls::ALL_VERSIONS) + .expect("client config must be valid") + .with_root_certificates(rustls::RootCertStore::empty()) + .with_no_client_auth() } #[tokio::test] diff --git a/linkerd/meshtls/rustls/src/lib.rs b/linkerd/meshtls/rustls/src/lib.rs index d533e1543a..1445d3a907 100644 --- a/linkerd/meshtls/rustls/src/lib.rs +++ b/linkerd/meshtls/rustls/src/lib.rs @@ -1,6 +1,7 @@ #![deny(rust_2018_idioms, clippy::disallowed_methods, clippy::disallowed_types)] #![forbid(unsafe_code)] +mod backend; mod client; pub mod creds; mod server; diff --git a/linkerd2-proxy/Cargo.toml b/linkerd2-proxy/Cargo.toml index a66a9f928c..7906fa1129 100644 --- a/linkerd2-proxy/Cargo.toml +++ b/linkerd2-proxy/Cargo.toml @@ -8,11 +8,13 @@ publish = false description = "The main proxy executable" [features] -default = ["multicore", "meshtls-rustls"] +default = ["multicore", "meshtls-rustls-ring"] multicore = ["tokio/rt-multi-thread", "num_cpus"] meshtls-boring = ["linkerd-meshtls/boring"] meshtls-boring-fips = ["linkerd-meshtls/boring-fips"] -meshtls-rustls = ["linkerd-meshtls/rustls"] +meshtls-rustls-ring = ["linkerd-meshtls/rustls-ring"] +meshtls-rustls-aws-lc = ["linkerd-meshtls/rustls-aws-lc"] +meshtls-rustls-aws-lc-fips = ["linkerd-meshtls/rustls-aws-lc-fips"] log-streaming = ["linkerd-app/log-streaming"] pprof = ["linkerd-app/pprof"] diff --git a/linkerd2-proxy/src/main.rs b/linkerd2-proxy/src/main.rs index f198d135e2..ccbbbfba25 100644 --- a/linkerd2-proxy/src/main.rs +++ b/linkerd2-proxy/src/main.rs @@ -6,7 +6,12 @@ // Emit a compile-time error if no TLS implementations are enabled. When adding // new implementations, add their feature flags here! -#[cfg(not(any(feature = "meshtls-boring", feature = "meshtls-rustls")))] +#[cfg(not(any( + feature = "meshtls-boring", + feature = "meshtls-rustls-ring", + feature = "meshtls-rustls-aws-lc", + feature = "meshtls-rustls-aws-lc-fips" +)))] compile_error!( "at least one of the following TLS implementations must be enabled: 'meshtls-boring', 'meshtls-rustls'" );