diff --git a/Cargo.lock b/Cargo.lock index 3e1d73e..6db4472 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -684,7 +684,7 @@ checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" [[package]] name = "rustls-rustcrypto" -version = "0.0.1-alpha" +version = "0.0.2-alpha" dependencies = [ "aead", "aes-gcm", @@ -694,7 +694,6 @@ dependencies = [ "digest", "ecdsa", "ed25519-dalek", - "getrandom", "hmac", "p256", "p384", @@ -879,13 +878,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -894,45 +894,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "x25519-dalek" diff --git a/Cargo.toml b/Cargo.toml index 6ff6103..8796370 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ categories = ["cryptography", "no-std"] keywords = ["rustls", "tls"] edition = "2021" rust-version = "1.75" -resolver = "1" # Hack to enable the `custom` feature of `getrandom` # Ensure all dependencies + feats are mapped to crate features for correct usage # default features often have std breaking no_std and potentially other unwanted @@ -32,7 +31,7 @@ p384 = { version = "0.13.0", default-features = false, features = ["pem", "ecdsa paste = { version = "1.0.14", default-features = false } pkcs8 = { version = "0.10.2", default-features = false, features = ["pem", "pkcs5"] } pki-types = { package = "rustls-pki-types", version = "1.0.1", default-features = false } -rand_core = { version = "0.6.4", default-features = false, features = ["getrandom"] } +rand_core = { version = "0.6.4", default-features = false } rsa = { version = "0.9.2", default-features = false, features = ["sha2"] } rustls = { version = "0.23.0", default-features = false } sec1 = { version = "0.7.3", default-features = false, features = ["pkcs8", "pem"] } @@ -41,11 +40,8 @@ signature = { version = "2.1.0", default-features = false } webpki = { package = "rustls-webpki", version = "0.102.0", default-features = false } x25519-dalek = { version = "2", default-features = false } -[dev-dependencies] -getrandom = { version = "0.2", features = ["custom"] } # workaround to build on no_std targets - [features] -default = ["std", "tls12", "zeroize"] +default = ["std", "tls12", "zeroize", "getrandom"] logging = ["rustls/logging"] tls12 = ["rustls/tls12"] @@ -57,3 +53,5 @@ std = ["alloc", "webpki/std", "pki-types/std", "rustls/std", "ed25519-dalek/std" # TODO: go through all of these to ensure to_vec etc. impls are exposed alloc = ["webpki/alloc", "pki-types/alloc", "aead/alloc", "ed25519-dalek/alloc"] zeroize = ["ed25519-dalek/zeroize", "x25519-dalek/zeroize"] + +getrandom = ["rand_core/getrandom"] \ No newline at end of file diff --git a/src/kx.rs b/src/kx.rs index 66341f2..b1fa7f0 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -14,7 +14,7 @@ impl crypto::SupportedKxGroup for X25519 { } fn start(&self) -> Result, rustls::Error> { - let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng); + let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(crate::CryptoProviderRng); let pub_key = (&priv_key).into(); Ok(Box::new(X25519KeyExchange { priv_key, pub_key })) } @@ -60,7 +60,7 @@ macro_rules! impl_kx { } fn start(&self) -> Result, rustls::Error> { - let priv_key = $secret::random(&mut rand_core::OsRng); + let priv_key = $secret::random(&mut crate::CryptoProviderRng); let pub_key: $public_key = (&priv_key).into(); Ok(Box::new([<$name KeyExchange>] { priv_key, diff --git a/src/lib.rs b/src/lib.rs index 1b108b8..4468d46 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,39 +38,86 @@ compile_error!("Rustls currently does not support alloc-less environments"); #[cfg(feature = "alloc")] extern crate alloc; +use core::fmt::Debug; + +use core::num::NonZeroU32; + #[cfg(feature = "alloc")] use alloc::sync::Arc; -use rustls::crypto::{ - CipherSuiteCommon, CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom, -}; +use rand_core::{CryptoRng, RngCore}; +use rustls::crypto::{CipherSuiteCommon, CryptoProvider, KeyProvider, SecureRandom}; use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; #[cfg(feature = "tls12")] use rustls::SignatureScheme; +#[cfg(feature = "getrandom")] +use rustls::crypto::GetRandomFailed; + +#[derive(Debug, Clone)] +pub(crate) struct CryptoProviderRng; + +impl RngCore for CryptoProviderRng { + fn next_u32(&mut self) -> u32 { + let mut limbs: [u8; 4] = [0; 4]; + self.fill_bytes(&mut limbs); + u32::from_ne_bytes(limbs) + } + + fn next_u64(&mut self) -> u64 { + let mut limbs: [u8; 8] = [0; 8]; + self.fill_bytes(&mut limbs); + u64::from_ne_bytes(limbs) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.try_fill_bytes(dest) + .expect("random bytes should be filled") + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { + CryptoProvider::get_default() + .expect("provider should be set") + .secure_random + .fill(dest) + .map_err(|_| unsafe { NonZeroU32::new_unchecked(1).into() }) + } +} + +impl CryptoRng for CryptoProviderRng {} + #[derive(Debug)] +#[cfg(feature = "getrandom")] +struct OsRngSecureRandom; + +#[cfg(feature = "getrandom")] +impl SecureRandom for OsRngSecureRandom { + fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> { + rand_core::OsRng + .try_fill_bytes(buf) + .map_err(|_| GetRandomFailed) + } +} + +#[derive(Debug, Clone)] pub struct Provider; +#[cfg(feature = "getrandom")] pub fn provider() -> CryptoProvider { + provider_with_rng(&OsRngSecureRandom) +} + +pub fn provider_with_rng(rng: &'static dyn SecureRandom) -> CryptoProvider { CryptoProvider { cipher_suites: ALL_CIPHER_SUITES.to_vec(), kx_groups: kx::ALL_KX_GROUPS.to_vec(), signature_verification_algorithms: verify::ALGORITHMS, - secure_random: &Provider, + secure_random: rng, key_provider: &Provider, } } -impl SecureRandom for Provider { - fn fill(&self, bytes: &mut [u8]) -> Result<(), GetRandomFailed> { - use rand_core::RngCore; - rand_core::OsRng - .try_fill_bytes(bytes) - .map_err(|_| GetRandomFailed) - } -} - impl KeyProvider for Provider { fn load_private_key( &self, @@ -81,7 +128,7 @@ impl KeyProvider for Provider { } #[cfg(feature = "tls12")] -const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ +pub const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ SignatureScheme::ECDSA_NISTP256_SHA256, SignatureScheme::ECDSA_NISTP384_SHA384, SignatureScheme::ECDSA_NISTP521_SHA512, @@ -89,7 +136,7 @@ const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ ]; #[cfg(feature = "tls12")] -const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [ +pub const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [ SignatureScheme::RSA_PKCS1_SHA256, SignatureScheme::RSA_PKCS1_SHA384, SignatureScheme::RSA_PKCS1_SHA512, @@ -141,7 +188,7 @@ pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = }); #[cfg(feature = "tls12")] -const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ +pub const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, @@ -190,21 +237,21 @@ pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = }); #[cfg(feature = "tls12")] -const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ +pub const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, ]; #[cfg(feature = "tls12")] -const TLS12_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( +pub const TLS12_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( SupportedCipherSuite, TLS_ECDHE_ECDSA_SUITES, TLS_ECDHE_RSA_SUITES ); #[cfg(not(feature = "tls12"))] -const TLS12_SUITES: &[SupportedCipherSuite] = &[]; +pub const TLS12_SUITES: &[SupportedCipherSuite] = &[]; pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { @@ -230,7 +277,7 @@ pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = quic: None, }); -const TLS13_AES_SUITES: &[SupportedCipherSuite] = +pub const TLS13_AES_SUITES: &[SupportedCipherSuite] = &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384]; pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = @@ -245,13 +292,13 @@ pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = quic: None, }); -const TLS13_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( +pub const TLS13_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( SupportedCipherSuite, TLS13_AES_SUITES, &[TLS13_CHACHA20_POLY1305_SHA256] ); -static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( +pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( SupportedCipherSuite, if cfg!(feature = "tls12") { TLS12_SUITES diff --git a/src/sign.rs b/src/sign.rs index e6109f5..deadef4 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -29,7 +29,7 @@ where { fn sign(&self, message: &[u8]) -> Result, Error> { self.key - .try_sign_with_rng(&mut rand_core::OsRng, message) + .try_sign_with_rng(&mut crate::CryptoProviderRng, message) .map_err(|_| rustls::Error::General("signing failed".into())) .map(|sig: S| sig.to_vec()) } diff --git a/src/verify.rs b/src/verify.rs index 2043b64..513587c 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -8,7 +8,7 @@ use self::rsa::{ RSA_PSS_SHA512, }; -pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { +pub const ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { all: &[ ECDSA_P256_SHA256, ECDSA_P256_SHA384,