tasign 0.2.0

TA ELF signing utilities with CMS/PKCS#7 support
//! ChaCha20 RNG (RustCrypto backend) with mbedtls-compatible `CtrDrbg` / `OsEntropy` names.

extern crate alloc;

#[cfg(feature = "std")]
use alloc::sync::Arc;

use rand_chacha::ChaCha20Rng;
use rand_core::{RngCore, SeedableRng};

/// Trait for cryptographic random number generation.
pub trait CryptoRng {
    fn fill_bytes(&mut self, dest: &mut [u8]);
}

/// ChaCha20-based deterministic RNG for tests and signing.
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 {}

/// Forward `CryptoRng` trait object to `rand_core` for RSA/ECDSA signing.
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<'_> {}

/// Reseed a [`TeeRng`] from an external [`CryptoRng`] (mbedtls CtrDrbg-style facade).
///
/// Signing paths use [`DynCryptoRng`] directly to avoid an extra ChaCha20 reseed layer.
pub fn bridge_rng(rng: &mut dyn CryptoRng) -> TeeRng {
    let mut seed = [0u8; 32];
    rng.fill_bytes(&mut seed);
    TeeRng::seed_from_bytes(&seed)
}

/// Placeholder entropy source (API-compatible with mbedtls `OsEntropy`).
pub struct OsEntropy;

impl OsEntropy {
    pub fn new() -> Self {
        Self
    }
}

/// CTR-DRBG facade seeded from OS entropy (API-compatible with mbedtls `CtrDrbg`).
#[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)
    }
}