use crypto_common::generic_array::{ArrayLength, GenericArray};
#[cfg(feature = "internal-software-crypto-cbc")]
pub use software::*;
use crate::{Error, Support};
pub trait Api<Key, Block>: Support<bool> + Send
where
Key: ArrayLength<u8>,
Block: ArrayLength<u8>,
{
fn encrypt(key: &Array<Key>, iv: &Array<Block>, blocks: &mut [u8]) -> Result<(), Error>;
fn decrypt(key: &Array<Key>, iv: &Array<Block>, blocks: &mut [u8]) -> Result<(), Error>;
}
pub type Array<N> = GenericArray<u8, N>;
#[cfg(feature = "internal-software-crypto-cbc")]
mod software {
use core::marker::PhantomData;
use aes::cipher::{BlockCipher, BlockDecryptMut, BlockEncryptMut};
use cbc::{Decryptor, Encryptor};
use crypto_common::{KeyInit, KeyIvInit, KeySizeUser};
use wasefire_error::Code;
use super::*;
pub struct Software<C> {
cipher: PhantomData<C>,
}
impl<C> Support<bool> for Software<C> {
const SUPPORT: bool = true;
}
impl<Key, Block, C> Api<Key, Block> for Software<C>
where
C: Send + KeyInit + KeySizeUser<KeySize = Key>,
C: BlockCipher<BlockSize = Block> + BlockDecryptMut + BlockEncryptMut,
Key: ArrayLength<u8>,
Block: ArrayLength<u8>,
{
fn encrypt(key: &Array<Key>, iv: &Array<Block>, blocks: &mut [u8]) -> Result<(), Error> {
Ok(Encryptor::<C>::new(key, iv).encrypt_blocks_mut(convert_blocks(blocks)?))
}
fn decrypt(key: &Array<Key>, iv: &Array<Block>, blocks: &mut [u8]) -> Result<(), Error> {
Ok(Decryptor::<C>::new(key, iv).decrypt_blocks_mut(convert_blocks(blocks)?))
}
}
fn convert_blocks<N: ArrayLength<u8>>(blocks: &mut [u8]) -> Result<&mut [Array<N>], Error> {
if !blocks.len().is_multiple_of(N::USIZE) {
return Err(Error::user(Code::InvalidLength));
}
let ptr = blocks.as_mut_ptr() as *mut Array<N>;
let len = blocks.len() / N::USIZE;
let blocks = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
Ok(blocks)
}
}