libsignal-protocol 0.1.0

An idiomatic high-level interface to the libsignal-protocol-c crate.
Documentation
#![allow(dead_code)]

use libsignal_protocol::{
    crypto::{Crypto, Sha256Hmac, Sha512Digest, SignalCipherType},
    InternalError,
};
use std::{panic::RefUnwindSafe, sync::Mutex};

pub(crate) struct MockCrypto<C> {
    inner: C,
    random_func: Option<
        Box<
            dyn Fn(&mut [u8]) -> Result<(), InternalError>
                + RefUnwindSafe
                + 'static,
        >,
    >,
}

impl<C: Crypto> MockCrypto<C> {
    pub fn new(inner: C) -> MockCrypto<C> {
        MockCrypto {
            inner,
            random_func: None,
        }
    }

    pub fn random_func<F>(mut self, func: F) -> Self
    where
        F: Fn(&mut [u8]) -> Result<(), InternalError> + RefUnwindSafe + 'static,
    {
        self.random_func = Some(Box::new(func));
        self
    }
}

impl<C: Crypto> Crypto for MockCrypto<C> {
    fn fill_random(&self, buffer: &mut [u8]) -> Result<(), InternalError> {
        if let Some(ref random_func) = self.random_func {
            random_func(buffer)
        } else {
            self.inner.fill_random(buffer)
        }
    }

    fn hmac_sha256(
        &self,
        key: &[u8],
    ) -> Result<Box<dyn Sha256Hmac>, InternalError> {
        self.inner.hmac_sha256(key)
    }

    fn sha512_digest(&self) -> Result<Box<dyn Sha512Digest>, InternalError> {
        self.inner.sha512_digest()
    }

    fn encrypt(
        &self,
        cipher: SignalCipherType,
        key: &[u8],
        iv: &[u8],
        data: &[u8],
    ) -> Result<Vec<u8>, InternalError> {
        self.inner.encrypt(cipher, key, iv, data)
    }

    fn decrypt(
        &self,
        cipher: SignalCipherType,
        key: &[u8],
        iv: &[u8],
        data: &[u8],
    ) -> Result<Vec<u8>, InternalError> {
        self.inner.decrypt(cipher, key, iv, data)
    }
}

pub fn fake_random_generator() -> impl Fn(&mut [u8]) -> Result<(), InternalError>
{
    let test_next_random = Mutex::new(0);

    move |data| {
        let mut test_next_random = test_next_random.lock().unwrap();

        for i in 0..data.len() {
            data[i] = *test_next_random;
            *test_next_random = test_next_random.wrapping_add(1);
        }

        Ok(())
    }
}