Skip to content

Commit 48f3f07

Browse files
get rid of the getrandom requirement
1 parent ca89eb1 commit 48f3f07

File tree

5 files changed

+86
-18
lines changed

5 files changed

+86
-18
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ p384 = { version = "0.13.0", default-features = false, features = ["pem", "ecdsa
3232
paste = { version = "1.0.14", default-features = false }
3333
pkcs8 = { version = "0.10.2", default-features = false, features = ["pem", "pkcs5"] }
3434
pki-types = { package = "rustls-pki-types", version = "1.0.1", default-features = false }
35-
rand_core = { version = "0.6.4", default-features = false, features = ["getrandom"] }
35+
rand_core = { version = "0.6.4", default-features = false }
3636
rsa = { version = "0.9.2", default-features = false, features = ["sha2"] }
3737
rustls = { version = "0.23.0", default-features = false }
3838
sec1 = { version = "0.7.3", default-features = false, features = ["pkcs8", "pem"] }
@@ -45,7 +45,7 @@ x25519-dalek = { version = "2", default-features = false }
4545
getrandom = { version = "0.2", features = ["custom"] } # workaround to build on no_std targets
4646

4747
[features]
48-
default = ["std", "tls12", "zeroize"]
48+
default = ["std", "tls12", "zeroize", "getrandom"]
4949
logging = ["rustls/logging"]
5050
tls12 = ["rustls/tls12"]
5151

@@ -57,3 +57,5 @@ std = ["alloc", "webpki/std", "pki-types/std", "rustls/std", "ed25519-dalek/std"
5757
# TODO: go through all of these to ensure to_vec etc. impls are exposed
5858
alloc = ["webpki/alloc", "pki-types/alloc", "aead/alloc", "ed25519-dalek/alloc"]
5959
zeroize = ["ed25519-dalek/zeroize", "x25519-dalek/zeroize"]
60+
61+
getrandom = ["alloc", "rand_core/getrandom"]

src/kx.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ impl crypto::SupportedKxGroup for X25519 {
1414
}
1515

1616
fn start(&self) -> Result<Box<dyn crypto::ActiveKeyExchange>, rustls::Error> {
17-
let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng);
17+
let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(crate::Provider);
1818
let pub_key = (&priv_key).into();
1919
Ok(Box::new(X25519KeyExchange { priv_key, pub_key }))
2020
}
@@ -60,7 +60,7 @@ macro_rules! impl_kx {
6060
}
6161

6262
fn start(&self) -> Result<Box<dyn crypto::ActiveKeyExchange>, rustls::Error> {
63-
let priv_key = $secret::random(&mut rand_core::OsRng);
63+
let priv_key = $secret::random(&mut crate::Provider);
6464
let pub_key: $public_key = (&priv_key).into();
6565
Ok(Box::new([<$name KeyExchange>] {
6666
priv_key,

src/lib.rs

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ compile_error!("Rustls currently does not support alloc-less environments");
3838
#[cfg(feature = "alloc")]
3939
extern crate alloc;
4040

41+
use core::{cell::OnceCell, fmt::Debug};
42+
4143
#[cfg(feature = "alloc")]
42-
use alloc::sync::Arc;
44+
use alloc::{boxed::Box, sync::Arc};
4345

46+
use rand_core::{CryptoRng, RngCore};
4447
use rustls::crypto::{
4548
CipherSuiteCommon, CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom,
4649
};
@@ -49,7 +52,7 @@ use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite};
4952
#[cfg(feature = "tls12")]
5053
use rustls::SignatureScheme;
5154

52-
#[derive(Debug)]
55+
#[derive(Debug, Clone)]
5356
pub struct Provider;
5457

5558
pub fn provider() -> CryptoProvider {
@@ -62,15 +65,76 @@ pub fn provider() -> CryptoProvider {
6265
}
6366
}
6467

68+
// TODO: switch to ThinBox once it is available
69+
#[cfg(feature = "alloc")]
70+
static mut RNG: OnceCell<Box<dyn RngCore + Send + Sync>> = OnceCell::new();
71+
72+
#[cfg(feature = "alloc")]
73+
fn get_rng_danger() -> &'static mut (dyn RngCore + Send + Sync) {
74+
#[cfg(feature = "getrandom")]
75+
#[allow(static_mut_refs)]
76+
// SAFETY: we only init the randomness source if the once cell was not initialized
77+
unsafe {
78+
// TODO: Add unlikely(...) later when it is stabilized for faster speculative branch
79+
if RNG.get().is_none() {
80+
// This would either set the randomness source or panic, in other word, infallible
81+
init_randomness_source(Box::new(rand_core::OsRng));
82+
}
83+
}
84+
85+
// SAFETY: If randomness source is not already set, the whole program panics due to the unwrap
86+
// UNSAFETY: If you have a memory corruption (whether stack or heap or not), this could
87+
#[allow(static_mut_refs)]
88+
unsafe {
89+
RNG.get_mut().expect("RNG was not set").as_mut()
90+
}
91+
}
92+
93+
// Initialize an RNG source, and panic if it was already set, which would only happen if two threads set the data at the same time.
94+
// This ensures the user would have to decide on the RNG source at the very beginning, likely the first function call in main and find way to provide entropy themselves
95+
// TIP: Use Box::from_raw to prevent having to do real heap allocation if you can assume your program to be single-threaded and your put RNG state as a global variable
96+
#[cfg(feature = "alloc")]
97+
pub fn init_randomness_source(rng: Box<dyn RngCore + Send + Sync>) {
98+
// SAFETY: If randomness source is already set, the whole program panics
99+
#[allow(static_mut_refs)]
100+
unsafe {
101+
if RNG.set(rng).is_err() {
102+
panic!("RNG was set twice")
103+
}
104+
}
105+
}
106+
107+
#[cfg(feature = "alloc")]
65108
impl SecureRandom for Provider {
66109
fn fill(&self, bytes: &mut [u8]) -> Result<(), GetRandomFailed> {
67-
use rand_core::RngCore;
68-
rand_core::OsRng
110+
get_rng_danger()
69111
.try_fill_bytes(bytes)
70112
.map_err(|_| GetRandomFailed)
71113
}
72114
}
73115

116+
#[cfg(feature = "alloc")]
117+
impl RngCore for Provider {
118+
fn next_u32(&mut self) -> u32 {
119+
get_rng_danger().next_u32()
120+
}
121+
122+
fn next_u64(&mut self) -> u64 {
123+
get_rng_danger().next_u64()
124+
}
125+
126+
fn fill_bytes(&mut self, dest: &mut [u8]) {
127+
get_rng_danger().fill_bytes(dest)
128+
}
129+
130+
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
131+
get_rng_danger().try_fill_bytes(dest)
132+
}
133+
}
134+
135+
#[cfg(feature = "alloc")]
136+
impl CryptoRng for Provider {}
137+
74138
impl KeyProvider for Provider {
75139
fn load_private_key(
76140
&self,
@@ -81,15 +145,15 @@ impl KeyProvider for Provider {
81145
}
82146

83147
#[cfg(feature = "tls12")]
84-
const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [
148+
pub const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [
85149
SignatureScheme::ECDSA_NISTP256_SHA256,
86150
SignatureScheme::ECDSA_NISTP384_SHA384,
87151
SignatureScheme::ECDSA_NISTP521_SHA512,
88152
SignatureScheme::ED25519,
89153
];
90154

91155
#[cfg(feature = "tls12")]
92-
const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [
156+
pub const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [
93157
SignatureScheme::RSA_PKCS1_SHA256,
94158
SignatureScheme::RSA_PKCS1_SHA384,
95159
SignatureScheme::RSA_PKCS1_SHA512,
@@ -190,21 +254,21 @@ pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
190254
});
191255

192256
#[cfg(feature = "tls12")]
193-
const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[
257+
pub const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[
194258
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
195259
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
196260
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
197261
];
198262

199263
#[cfg(feature = "tls12")]
200-
const TLS12_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!(
264+
pub const TLS12_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!(
201265
SupportedCipherSuite,
202266
TLS_ECDHE_ECDSA_SUITES,
203267
TLS_ECDHE_RSA_SUITES
204268
);
205269

206270
#[cfg(not(feature = "tls12"))]
207-
const TLS12_SUITES: &[SupportedCipherSuite] = &[];
271+
pub const TLS12_SUITES: &[SupportedCipherSuite] = &[];
208272

209273
pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
210274
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
@@ -230,7 +294,7 @@ pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
230294
quic: None,
231295
});
232296

233-
const TLS13_AES_SUITES: &[SupportedCipherSuite] =
297+
pub const TLS13_AES_SUITES: &[SupportedCipherSuite] =
234298
&[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384];
235299

236300
pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
@@ -245,13 +309,13 @@ pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
245309
quic: None,
246310
});
247311

248-
const TLS13_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!(
312+
pub const TLS13_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!(
249313
SupportedCipherSuite,
250314
TLS13_AES_SUITES,
251315
&[TLS13_CHACHA20_POLY1305_SHA256]
252316
);
253317

254-
static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!(
318+
pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!(
255319
SupportedCipherSuite,
256320
if cfg!(feature = "tls12") {
257321
TLS12_SUITES

src/sign.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
use alloc::{sync::Arc, vec::Vec};
33
use core::marker::PhantomData;
44

5+
use crate::Provider;
6+
57
use self::ecdsa::{EcdsaSigningKeyP256, EcdsaSigningKeyP384};
68
use self::eddsa::Ed25519SigningKey;
79
use self::rsa::RsaSigningKey;
@@ -29,7 +31,7 @@ where
2931
{
3032
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
3133
self.key
32-
.try_sign_with_rng(&mut rand_core::OsRng, message)
34+
.try_sign_with_rng(&mut Provider, message)
3335
.map_err(|_| rustls::Error::General("signing failed".into()))
3436
.map(|sig: S| sig.to_vec())
3537
}

0 commit comments

Comments
 (0)