botan 0.4.0

Rust wrapper for Botan cryptography library
Documentation
use botan_sys::*;
use utils::*;

#[derive(Debug)]
/// A cryptographic random number generator
pub struct RandomNumberGenerator {
    obj: botan_rng_t
}

impl Drop for RandomNumberGenerator {
    fn drop(&mut self) {
        unsafe { botan_rng_destroy(self.obj); }
    }
}

impl RandomNumberGenerator {

    fn new_of_type(typ: &str) -> Result<RandomNumberGenerator> {
        let mut obj = ptr::null_mut();
        let typ = make_cstr(typ)?;
        call_botan! { botan_rng_init(&mut obj, typ.as_ptr()) }
        Ok(RandomNumberGenerator { obj })
    }

    pub(crate) fn handle(&self) -> botan_rng_t { self.obj }

    /// Create a new userspace RNG object
    ///
    /// # Examples
    /// ```
    /// let userspace_rng = botan::RandomNumberGenerator::new_userspace().unwrap();
    /// ```
    pub fn new_userspace() -> Result<RandomNumberGenerator> {
        RandomNumberGenerator::new_of_type("user")
    }

    /// Create a new reference to the system PRNG
    ///
    /// # Examples
    /// ```
    /// let system_rng = botan::RandomNumberGenerator::new_system().unwrap();
    /// ```
    pub fn new_system() -> Result<RandomNumberGenerator> {
        RandomNumberGenerator::new_of_type("system")
    }

    /// Create a new reference to an RNG of some arbitrary type
    ///
    /// # Examples
    /// ```
    /// let a_rng = botan::RandomNumberGenerator::new().unwrap();
    /// ```
    pub fn new() -> Result<RandomNumberGenerator> {
        RandomNumberGenerator::new_userspace()
    }

    /// Read bytes from an RNG
    ///
    /// # Examples
    /// ```
    /// let rng = botan::RandomNumberGenerator::new().unwrap();
    /// let output = rng.read(32).unwrap();
    /// assert_eq!(output.len(), 32);
    /// ```
    pub fn read(&self, len: usize) -> Result<Vec<u8>> {
        let mut result = vec![0; len];
        self.fill(&mut result)?;
        Ok(result)
    }

    /// Store bytes from the RNG into the passed slice
    ///
    /// # Examples
    /// ```
    /// let rng = botan::RandomNumberGenerator::new().unwrap();
    /// let mut output = vec![0; 32];
    /// rng.fill(&mut output).unwrap();
    /// ```
    pub fn fill(&self, out: &mut [u8]) -> Result<()> {
        call_botan! { botan_rng_get(self.obj, out.as_mut_ptr(), out.len()) }
        Ok(())
    }

    /// Attempt to reseed the RNG by unspecified means
    ///
    /// # Examples
    /// ```
    /// let rng = botan::RandomNumberGenerator::new().unwrap();
    /// rng.reseed(256).unwrap();
    /// ```
    pub fn reseed(&self, bits: usize) -> Result<()> {
        call_botan! { botan_rng_reseed(self.obj, bits) }
        Ok(())
    }

    /// Attempt to reseed the RNG by getting data from source RNG
    ///
    /// # Examples
    /// ```
    /// let system_rng = botan::RandomNumberGenerator::new_system().unwrap();
    /// let rng = botan::RandomNumberGenerator::new_userspace().unwrap();
    /// rng.reseed_from_rng(&system_rng, 256).unwrap();
    /// ```
    pub fn reseed_from_rng(&self, source: &RandomNumberGenerator, bits: usize) -> Result<()> {
        call_botan! { botan_rng_reseed_from_rng(self.obj, source.handle(), bits) }
        Ok(())
    }

    /// Add some seed material to the RNG
    ///
    /// # Examples
    /// ```
    /// let rng = botan::RandomNumberGenerator::new_userspace().unwrap();
    /// let my_seed = vec![0x42, 0x6F, 0x62];
    /// rng.add_entropy(&my_seed);
    /// ```
    pub fn add_entropy(&self, seed: &[u8]) -> Result<()> {
        call_botan! { botan_rng_add_entropy(self.obj, seed.as_ptr(), seed.len()) }
        Ok(())
    }

}