mirror of https://github.com/ctz/rustls
crypto: CryptoProvider is-a SecureRandom -> has-a
In preparation for moving to a struct based model where a `CryptoProvider` has a `&'static dyn SecureRandom` field, this commit splits the `SecureRandom` trait from the `CryptoProvider` trait. In its place `CryptoProvider` gets a `secure_random(&self)` fn that acts as a stand-in for what will be a field in the struct based approach.
This commit is contained in:
parent
53ed597fa1
commit
3b5cf17ade
|
@ -38,6 +38,10 @@ impl rustls::crypto::CryptoProvider for Provider {
|
|||
fn signature_verification_algorithms(&self) -> rustls::crypto::WebPkiSupportedAlgorithms {
|
||||
verify::ALGORITHMS
|
||||
}
|
||||
|
||||
fn secure_random(&self) -> &'static dyn rustls::crypto::SecureRandom {
|
||||
&Self
|
||||
}
|
||||
}
|
||||
|
||||
impl rustls::crypto::SecureRandom for Provider {
|
||||
|
|
|
@ -121,7 +121,7 @@ pub(super) fn start_handshake(
|
|||
// we're doing an abbreviated handshake. See section 3.4 in
|
||||
// RFC5077.
|
||||
if !inner.ticket().is_empty() {
|
||||
inner.session_id = SessionId::random(config.provider)?;
|
||||
inner.session_id = SessionId::random(config.provider.secure_random())?;
|
||||
}
|
||||
session_id = Some(inner.session_id);
|
||||
}
|
||||
|
@ -137,10 +137,10 @@ pub(super) fn start_handshake(
|
|||
Some(session_id) => session_id,
|
||||
None if cx.common.is_quic() => SessionId::empty(),
|
||||
None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
|
||||
None => SessionId::random(config.provider)?,
|
||||
None => SessionId::random(config.provider.secure_random())?,
|
||||
};
|
||||
|
||||
let random = Random::new(config.provider)?;
|
||||
let random = Random::new(config.provider.secure_random())?;
|
||||
|
||||
Ok(emit_client_hello_for_retry(
|
||||
transcript_buffer,
|
||||
|
|
|
@ -60,6 +60,10 @@ impl CryptoProvider for AwsLcRs {
|
|||
fn signature_verification_algorithms(&self) -> WebPkiSupportedAlgorithms {
|
||||
SUPPORTED_SIG_ALGS
|
||||
}
|
||||
|
||||
fn secure_random(&self) -> &'static dyn SecureRandom {
|
||||
&Self
|
||||
}
|
||||
}
|
||||
|
||||
impl SecureRandom for AwsLcRs {
|
||||
|
|
|
@ -100,11 +100,7 @@ pub use crate::msgs::handshake::KeyExchangeAlgorithm;
|
|||
/// #[derive(Debug)]
|
||||
/// struct HsmKeyLoader;
|
||||
///
|
||||
/// impl rustls::crypto::CryptoProvider for HsmKeyLoader {
|
||||
/// fn fill_random(&self, buf: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
|
||||
/// RING.fill(buf)
|
||||
/// }
|
||||
///
|
||||
/// impl rustls::crypto::CryptoProvider for HsmKeyLoader {///
|
||||
/// fn default_cipher_suites(&self) -> &'static [rustls::SupportedCipherSuite] {
|
||||
/// RING.default_cipher_suites()
|
||||
/// }
|
||||
|
@ -120,6 +116,16 @@ pub use crate::msgs::handshake::KeyExchangeAlgorithm;
|
|||
/// fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
|
||||
/// fictious_hsm_api::load_private_key(key_der)
|
||||
/// }
|
||||
///
|
||||
/// fn secure_random(&self) -> &'static dyn rustls::crypto::SecureRandom {
|
||||
/// &HsmKeyLoader
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl rustls::crypto::SecureRandom for HsmKeyLoader {
|
||||
/// fn fill(&self, buf: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
|
||||
/// RING.secure_random().fill(buf)
|
||||
/// }
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
|
@ -152,7 +158,7 @@ pub use crate::msgs::handshake::KeyExchangeAlgorithm;
|
|||
/// [provider-example/]: https://github.com/rustls/rustls/tree/main/provider-example/
|
||||
/// [rust-crypto]: https://github.com/rustcrypto
|
||||
/// [dalek-cryptography]: https://github.com/dalek-cryptography
|
||||
pub trait CryptoProvider: SecureRandom + Send + Sync + Debug + 'static {
|
||||
pub trait CryptoProvider: Send + Sync + Debug + 'static {
|
||||
/// Provide a safe set of cipher suites that can be used as the defaults.
|
||||
///
|
||||
/// This is used by [`crate::ConfigBuilder::with_safe_defaults()`] and
|
||||
|
@ -197,6 +203,9 @@ pub trait CryptoProvider: SecureRandom + Send + Sync + Debug + 'static {
|
|||
/// [`crate::server::WebPkiClientVerifier::builder_with_provider()`] and
|
||||
/// [`crate::client::WebPkiServerVerifier::builder_with_provider()`].
|
||||
fn signature_verification_algorithms(&self) -> WebPkiSupportedAlgorithms;
|
||||
|
||||
/// Return a source of cryptographically secure randomness.
|
||||
fn secure_random(&self) -> &'static dyn SecureRandom;
|
||||
}
|
||||
|
||||
/// A source of cryptographically secure randomness.
|
||||
|
|
|
@ -55,6 +55,10 @@ impl CryptoProvider for Ring {
|
|||
fn signature_verification_algorithms(&self) -> WebPkiSupportedAlgorithms {
|
||||
SUPPORTED_SIG_ALGS
|
||||
}
|
||||
|
||||
fn secure_random(&self) -> &'static dyn SecureRandom {
|
||||
&Self
|
||||
}
|
||||
}
|
||||
|
||||
impl SecureRandom for Ring {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#[cfg(feature = "tls12")]
|
||||
use crate::crypto::ActiveKeyExchange;
|
||||
use crate::crypto::CryptoProvider;
|
||||
use crate::crypto::SecureRandom;
|
||||
use crate::enums::{CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme};
|
||||
use crate::error::InvalidMessage;
|
||||
#[cfg(feature = "logging")]
|
||||
|
@ -97,11 +97,9 @@ impl Codec for Random {
|
|||
}
|
||||
|
||||
impl Random {
|
||||
pub(crate) fn new(
|
||||
provider: &'static dyn CryptoProvider,
|
||||
) -> Result<Self, rand::GetRandomFailed> {
|
||||
pub(crate) fn new(secure_random: &dyn SecureRandom) -> Result<Self, rand::GetRandomFailed> {
|
||||
let mut data = [0u8; 32];
|
||||
provider.fill(&mut data)?;
|
||||
secure_random.fill(&mut data)?;
|
||||
Ok(Self(data))
|
||||
}
|
||||
}
|
||||
|
@ -165,9 +163,9 @@ impl Codec for SessionId {
|
|||
}
|
||||
|
||||
impl SessionId {
|
||||
pub fn random(provider: &'static dyn CryptoProvider) -> Result<Self, rand::GetRandomFailed> {
|
||||
pub fn random(secure_random: &dyn SecureRandom) -> Result<Self, rand::GetRandomFailed> {
|
||||
let mut data = [0u8; 32];
|
||||
provider.fill(&mut data)?;
|
||||
secure_random.fill(&mut data)?;
|
||||
Ok(Self { data, len: 32 })
|
||||
}
|
||||
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
//! The single place where we generate random material for our own use.
|
||||
|
||||
use crate::crypto::CryptoProvider;
|
||||
use crate::crypto::SecureRandom;
|
||||
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// Make a [`Vec<u8>`] of the given size containing random material.
|
||||
pub(crate) fn random_vec(
|
||||
provider: &dyn CryptoProvider,
|
||||
secure_random: &dyn SecureRandom,
|
||||
len: usize,
|
||||
) -> Result<Vec<u8>, GetRandomFailed> {
|
||||
let mut v = vec![0; len];
|
||||
provider.fill(&mut v)?;
|
||||
secure_random.fill(&mut v)?;
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
/// Return a uniformly random [`u32`].
|
||||
pub(crate) fn random_u32(provider: &dyn CryptoProvider) -> Result<u32, GetRandomFailed> {
|
||||
pub(crate) fn random_u32(secure_random: &dyn SecureRandom) -> Result<u32, GetRandomFailed> {
|
||||
let mut buf = [0u8; 4];
|
||||
provider.fill(&mut buf)?;
|
||||
secure_random.fill(&mut buf)?;
|
||||
Ok(u32::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
|
|
|
@ -384,8 +384,10 @@ impl ExpectClientHello {
|
|||
};
|
||||
|
||||
// Save their Random.
|
||||
let randoms =
|
||||
ConnectionRandoms::new(client_hello.random, Random::new(self.config.provider)?);
|
||||
let randoms = ConnectionRandoms::new(
|
||||
client_hello.random,
|
||||
Random::new(self.config.provider.secure_random())?,
|
||||
);
|
||||
match suite {
|
||||
SupportedCipherSuite::Tls13(suite) => tls13::CompleteClientHelloHandling {
|
||||
config: self.config,
|
||||
|
|
|
@ -209,7 +209,7 @@ mod client_hello {
|
|||
if !self.config.session_storage.can_cache() {
|
||||
self.session_id = SessionId::empty();
|
||||
} else if self.session_id.is_empty() && !ticket_received {
|
||||
self.session_id = SessionId::random(self.config.provider)?;
|
||||
self.session_id = SessionId::random(self.config.provider.secure_random())?;
|
||||
}
|
||||
|
||||
self.send_ticket = emit_server_hello(
|
||||
|
|
|
@ -1085,8 +1085,9 @@ impl ExpectFinished {
|
|||
key_schedule: &KeyScheduleTraffic,
|
||||
config: &ServerConfig,
|
||||
) -> Result<(), Error> {
|
||||
let nonce = rand::random_vec(config.provider, 32)?;
|
||||
let age_add = rand::random_u32(config.provider)?;
|
||||
let secure_random = config.provider.secure_random();
|
||||
let nonce = rand::random_vec(secure_random, 32)?;
|
||||
let age_add = rand::random_u32(secure_random)?;
|
||||
let plain = get_server_session_value(
|
||||
transcript,
|
||||
suite,
|
||||
|
@ -1106,7 +1107,7 @@ impl ExpectFinished {
|
|||
};
|
||||
(ticket, config.ticketer.lifetime())
|
||||
} else {
|
||||
let id = rand::random_vec(config.provider, 32)?;
|
||||
let id = rand::random_vec(secure_random, 32)?;
|
||||
let stored = config
|
||||
.session_storage
|
||||
.put(id.clone(), plain);
|
||||
|
|
|
@ -4104,7 +4104,10 @@ mod test_quic {
|
|||
use rustls::{CipherSuite, HandshakeType, SignatureScheme};
|
||||
|
||||
let mut random = [0; 32];
|
||||
PROVIDER.fill(&mut random).unwrap();
|
||||
PROVIDER
|
||||
.secure_random()
|
||||
.fill(&mut random)
|
||||
.unwrap();
|
||||
let random = Random::from(random);
|
||||
|
||||
let rng = ring::rand::SystemRandom::new();
|
||||
|
@ -4118,7 +4121,7 @@ mod test_quic {
|
|||
payload: HandshakePayload::ClientHello(ClientHelloPayload {
|
||||
client_version: ProtocolVersion::TLSv1_3,
|
||||
random,
|
||||
session_id: SessionId::random(PROVIDER).unwrap(),
|
||||
session_id: SessionId::random(PROVIDER.secure_random()).unwrap(),
|
||||
cipher_suites: vec![CipherSuite::TLS13_AES_128_GCM_SHA256],
|
||||
compression_methods: vec![Compression::Null],
|
||||
extensions: vec![
|
||||
|
@ -4158,7 +4161,10 @@ mod test_quic {
|
|||
use rustls::{CipherSuite, HandshakeType, SignatureScheme};
|
||||
|
||||
let mut random = [0; 32];
|
||||
PROVIDER.fill(&mut random).unwrap();
|
||||
PROVIDER
|
||||
.secure_random()
|
||||
.fill(&mut random)
|
||||
.unwrap();
|
||||
let random = Random::from(random);
|
||||
|
||||
let rng = ring::rand::SystemRandom::new();
|
||||
|
@ -4179,7 +4185,7 @@ mod test_quic {
|
|||
payload: HandshakePayload::ClientHello(ClientHelloPayload {
|
||||
client_version: ProtocolVersion::TLSv1_2,
|
||||
random,
|
||||
session_id: SessionId::random(PROVIDER).unwrap(),
|
||||
session_id: SessionId::random(PROVIDER.secure_random()).unwrap(),
|
||||
cipher_suites: vec![CipherSuite::TLS13_AES_128_GCM_SHA256],
|
||||
compression_methods: vec![Compression::Null],
|
||||
extensions: vec![
|
||||
|
@ -4575,7 +4581,7 @@ fn test_client_sends_helloretryrequest() {
|
|||
#[test]
|
||||
fn test_client_rejects_hrr_with_varied_session_id() {
|
||||
use rustls::internal::msgs::handshake::SessionId;
|
||||
let different_session_id = SessionId::random(PROVIDER).unwrap();
|
||||
let different_session_id = SessionId::random(PROVIDER.secure_random()).unwrap();
|
||||
|
||||
let assert_client_sends_hello_with_secp384 = |msg: &mut Message| -> Altered {
|
||||
if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload {
|
||||
|
@ -5503,8 +5509,7 @@ fn test_explicit_provider_selection() {
|
|||
struct FaultyRandomProvider {
|
||||
parent: &'static dyn rustls::crypto::CryptoProvider,
|
||||
|
||||
// when empty, `fill_random` requests return `GetRandomFailed`
|
||||
rand_queue: Mutex<&'static [u8]>,
|
||||
random: &'static dyn rustls::crypto::SecureRandom,
|
||||
}
|
||||
|
||||
impl rustls::crypto::CryptoProvider for FaultyRandomProvider {
|
||||
|
@ -5527,9 +5532,19 @@ impl rustls::crypto::CryptoProvider for FaultyRandomProvider {
|
|||
self.parent
|
||||
.signature_verification_algorithms()
|
||||
}
|
||||
|
||||
fn secure_random(&self) -> &'static dyn rustls::crypto::SecureRandom {
|
||||
self.random
|
||||
}
|
||||
}
|
||||
|
||||
impl rustls::crypto::SecureRandom for FaultyRandomProvider {
|
||||
#[derive(Debug)]
|
||||
struct FaultyRandom {
|
||||
// when empty, `fill_random` requests return `GetRandomFailed`
|
||||
rand_queue: Mutex<&'static [u8]>,
|
||||
}
|
||||
|
||||
impl rustls::crypto::SecureRandom for FaultyRandom {
|
||||
fn fill(&self, output: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
|
||||
let mut queue = self.rand_queue.lock().unwrap();
|
||||
|
||||
|
@ -5552,9 +5567,12 @@ impl rustls::crypto::SecureRandom for FaultyRandomProvider {
|
|||
|
||||
#[test]
|
||||
fn test_client_construction_fails_if_random_source_fails_in_first_request() {
|
||||
static FAULTY_RANDOM: FaultyRandom = FaultyRandom {
|
||||
rand_queue: Mutex::new(b""),
|
||||
};
|
||||
static TEST_PROVIDER: FaultyRandomProvider = FaultyRandomProvider {
|
||||
parent: PROVIDER,
|
||||
rand_queue: Mutex::new(b""),
|
||||
random: &FAULTY_RANDOM,
|
||||
};
|
||||
|
||||
let client_config = finish_client_config(
|
||||
|
@ -5570,9 +5588,12 @@ fn test_client_construction_fails_if_random_source_fails_in_first_request() {
|
|||
|
||||
#[test]
|
||||
fn test_client_construction_fails_if_random_source_fails_in_second_request() {
|
||||
static FAULTY_RANDOM: FaultyRandom = FaultyRandom {
|
||||
rand_queue: Mutex::new(b"nice random number generator huh"),
|
||||
};
|
||||
static TEST_PROVIDER: FaultyRandomProvider = FaultyRandomProvider {
|
||||
parent: PROVIDER,
|
||||
rand_queue: Mutex::new(b"nice random number generator huh"),
|
||||
random: &FAULTY_RANDOM,
|
||||
};
|
||||
|
||||
let client_config = finish_client_config(
|
||||
|
@ -5588,13 +5609,16 @@ fn test_client_construction_fails_if_random_source_fails_in_second_request() {
|
|||
|
||||
#[test]
|
||||
fn test_client_construction_requires_64_bytes_of_random_material() {
|
||||
static TEST_PROVIDER: FaultyRandomProvider = FaultyRandomProvider {
|
||||
parent: PROVIDER,
|
||||
static FAULTY_RANDOM: FaultyRandom = FaultyRandom {
|
||||
rand_queue: Mutex::new(
|
||||
b"nice random number generator !!!\
|
||||
it's really not very good is it?",
|
||||
it's really not very good is it?",
|
||||
),
|
||||
};
|
||||
static TEST_PROVIDER: FaultyRandomProvider = FaultyRandomProvider {
|
||||
parent: PROVIDER,
|
||||
random: &FAULTY_RANDOM,
|
||||
};
|
||||
|
||||
let client_config = finish_client_config(
|
||||
KeyType::Rsa,
|
||||
|
|
Loading…
Reference in New Issue