drbg 2.0.0

Crypographic random number generator CTR_DRBG defined by NIST SP 800-90A R1.
Documentation
// SPDX-License-Identifier: MIT

//! Traits and types for defining entropy sources.
use alloc::string::{String, ToString};
use core::{
    fmt,
    fmt::{Debug, Display, Formatter},
};

/// Error type for entropy source failures.
#[derive(Debug)]
pub struct Error {
    inner: String,
}

/// Represents a source of cryptograplicly secure random data. It's
/// primary use-case is to seed random number generators.
pub trait Entropy {
    /// Fill `bytes` with random data from the entropy source.
    ///
    /// # Error
    ///
    /// Returns an error if there is a problem with the underlying
    /// entropy source.
    fn fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error>;
}

impl Error {
    /// Create a new error by wrapping an underlying entropy source
    /// error.
    ///
    /// # Example
    /// ```
    /// use drbg::entropy::Error;
    ///
    /// fn fill_bytes(bytes: &mut [u8]) -> Result<(), Error> {
    ///    getrandom::fill(bytes).map_err(Error::new)
    /// }
    /// ```
    pub fn new<E>(error: E) -> Self
    where
        E: Display + Debug,
    {
        Self {
            inner: error.to_string(),
        }
    }
}

impl core::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "entropy error: {}", self.inner)
    }
}

/// An entropy source that draws random data from the host operating
/// system.
///
/// ```
/// use drbg::entropy::{OsEntropy, Entropy};
///
/// # use drbg::entropy::Error;
/// #
/// # fn main() -> Result<(),Error> {
/// #
/// let mut entropy = OsEntropy::default();
/// let mut random_data = [0u8; 32];
/// entropy.fill_bytes(&mut random_data)?;
/// #
/// # Ok(())
/// # }
/// ```
#[derive(Default)]
pub struct OsEntropy {}

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

impl Entropy for OsEntropy {
    /// Fill `bytes` with random data from the operating system using
    /// [`getrandom`](getrandom::fill).
    ///
    /// # Error
    ///
    /// Returns any error from `getrandom`.
    fn fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error> {
        getrandom::fill(bytes).map_err(Error::new)
    }
}