pub use s2n_quic_core::random::Generator;
pub trait Provider: 'static {
type Generator: 'static + Generator;
type Error: core::fmt::Display + Send + Sync;
fn start(self) -> Result<Self::Generator, Self::Error>;
}
pub use self::rand::Provider as Default;
impl_provider_utils!();
mod rand {
use core::convert::Infallible;
use rand::{
prelude::*,
rngs::{OsRng, ReseedingRng},
};
use rand_chacha::ChaChaCore;
use s2n_quic_core::random;
const RESEED_THRESHOLD: u64 = 1024 * 64;
#[derive(Debug, Default)]
pub struct Provider(Generator);
impl super::Provider for Provider {
type Generator = Generator;
type Error = Infallible;
fn start(self) -> Result<Self::Generator, Self::Error> {
Ok(self.0)
}
}
impl super::TryInto for Generator {
type Provider = Provider;
type Error = Infallible;
fn try_into(self) -> Result<Self::Provider, Self::Error> {
Ok(Provider(self))
}
}
#[derive(Debug)]
pub struct Generator {
public: ReseedingRng<ChaChaCore, OsRng>,
private: ReseedingRng<ChaChaCore, OsRng>,
}
impl Default for Generator {
fn default() -> Self {
Self {
public: build_rng(),
private: build_rng(),
}
}
}
fn build_rng() -> ReseedingRng<ChaChaCore, OsRng> {
ReseedingRng::<ChaChaCore, OsRng>::new(RESEED_THRESHOLD, OsRng)
.unwrap_or_else(|err| panic!("could not initialize random generator: {err}"))
}
impl random::Generator for Generator {
fn public_random_fill(&mut self, dest: &mut [u8]) {
self.public.fill_bytes(dest)
}
fn private_random_fill(&mut self, dest: &mut [u8]) {
self.private.fill_bytes(dest)
}
}
#[cfg(test)]
mod tests {
use s2n_quic_core::random::Generator;
#[test]
fn generator_test() {
let mut generator = super::Generator::default();
let mut dest_1 = [0; 20];
let mut dest_2 = [0; 20];
generator.public_random_fill(&mut dest_1);
generator.public_random_fill(&mut dest_2);
assert_ne!(dest_1, dest_2);
generator.private_random_fill(&mut dest_1);
generator.private_random_fill(&mut dest_2);
assert_ne!(dest_1, dest_2);
}
}
}