extern crate alloc;
#[cfg(feature = "std")]
use alloc::sync::Arc;
use rand_chacha::ChaCha20Rng;
use rand_core::{RngCore, SeedableRng};
pub trait CryptoRng {
fn fill_bytes(&mut self, dest: &mut [u8]);
}
pub struct TeeRng {
inner: ChaCha20Rng,
}
impl TeeRng {
pub fn new() -> Self {
Self {
inner: ChaCha20Rng::seed_from_u64(0),
}
}
pub fn seed_from_u64(seed: u64) -> Self {
Self {
inner: ChaCha20Rng::seed_from_u64(seed),
}
}
pub fn seed_from_bytes(seed: &[u8; 32]) -> Self {
Self {
inner: ChaCha20Rng::from_seed(*seed),
}
}
}
impl Default for TeeRng {
fn default() -> Self {
Self::new()
}
}
impl CryptoRng for TeeRng {
fn fill_bytes(&mut self, dest: &mut [u8]) {
RngCore::fill_bytes(self, dest);
}
}
impl rand_core_0_10::TryRng for TeeRng {
type Error = core::convert::Infallible;
fn try_next_u32(&mut self) -> core::result::Result<u32, Self::Error> {
Ok(self.inner.next_u32())
}
fn try_next_u64(&mut self) -> core::result::Result<u64, Self::Error> {
Ok(self.inner.next_u64())
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), Self::Error> {
self.inner.fill_bytes(dest);
Ok(())
}
}
impl rand_core_0_10::TryCryptoRng for TeeRng {}
impl rand_core::CryptoRng for TeeRng {}
pub struct DynCryptoRng<'a>(pub &'a mut dyn CryptoRng);
impl RngCore for DynCryptoRng<'_> {
fn next_u32(&mut self) -> u32 {
let mut buf = [0u8; 4];
self.fill_bytes(&mut buf);
u32::from_le_bytes(buf)
}
fn next_u64(&mut self) -> u64 {
let mut buf = [0u8; 8];
self.fill_bytes(&mut buf);
u64::from_le_bytes(buf)
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.0.fill_bytes(dest);
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl rand_core::CryptoRng for DynCryptoRng<'_> {}
impl rand_core_0_10::TryRng for DynCryptoRng<'_> {
type Error = core::convert::Infallible;
fn try_next_u32(&mut self) -> core::result::Result<u32, Self::Error> {
Ok(self.next_u32())
}
fn try_next_u64(&mut self) -> core::result::Result<u64, Self::Error> {
Ok(self.next_u64())
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), Self::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl rand_core_0_10::TryCryptoRng for DynCryptoRng<'_> {}
pub fn bridge_rng(rng: &mut dyn CryptoRng) -> TeeRng {
let mut seed = [0u8; 32];
rng.fill_bytes(&mut seed);
TeeRng::seed_from_bytes(&seed)
}
pub struct OsEntropy;
impl OsEntropy {
pub fn new() -> Self {
Self
}
}
#[cfg(feature = "std")]
pub struct CtrDrbg {
inner: TeeRng,
}
#[cfg(feature = "std")]
impl CtrDrbg {
pub fn new(_entropy: Arc<OsEntropy>, _perso: Option<&[u8]>) -> crate::crypto::Result<Self> {
use rand_core::RngCore as _;
let mut seed = [0u8; 32];
rand_core::OsRng.fill_bytes(&mut seed);
Ok(Self {
inner: TeeRng::seed_from_bytes(&seed),
})
}
}
#[cfg(feature = "std")]
impl CryptoRng for CtrDrbg {
fn fill_bytes(&mut self, dest: &mut [u8]) {
CryptoRng::fill_bytes(&mut self.inner, dest);
}
}
impl RngCore for TeeRng {
fn next_u32(&mut self) -> u32 {
self.inner.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.inner.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.inner.fill_bytes(dest);
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
self.inner.try_fill_bytes(dest)
}
}