#[cfg(feature = "dev")]
mod dev;
mod errors;
pub use errors::{InvalidKeyNonceLength, LoopError, OverflowError};
pub use generic_array::{self, typenum::consts};
#[cfg(feature = "dev")]
pub use blobby;
use crate::block::{BlockCipher, BlockCipherMut, NewBlockCipher};
use core::convert::{TryFrom, TryInto};
use generic_array::typenum::Unsigned;
use generic_array::{ArrayLength, GenericArray};
pub type Key<C> = GenericArray<u8, <C as NewStreamCipher>::KeySize>;
pub type Nonce<C> = GenericArray<u8, <C as NewStreamCipher>::NonceSize>;
pub trait NewStreamCipher: Sized {
type KeySize: ArrayLength<u8>;
type NonceSize: ArrayLength<u8>;
fn new(key: &Key<Self>, nonce: &Nonce<Self>) -> Self;
#[inline]
fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidKeyNonceLength> {
let kl = Self::KeySize::to_usize();
let nl = Self::NonceSize::to_usize();
if key.len() != kl || nonce.len() != nl {
Err(InvalidKeyNonceLength)
} else {
let key = GenericArray::from_slice(key);
let nonce = GenericArray::from_slice(nonce);
Ok(Self::new(key, nonce))
}
}
}
pub trait SyncStreamCipher {
#[inline]
fn apply_keystream(&mut self, data: &mut [u8]) {
let res = self.try_apply_keystream(data);
if res.is_err() {
panic!("stream cipher loop detected");
}
}
fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError>;
}
pub trait SyncStreamCipherSeek {
fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError>;
fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError>;
fn current_pos<T: SeekNum>(&self) -> T {
self.try_current_pos().unwrap()
}
fn seek<T: SeekNum>(&mut self, pos: T) {
self.try_seek(pos).unwrap()
}
}
pub trait StreamCipher {
fn encrypt(&mut self, data: &mut [u8]);
fn decrypt(&mut self, data: &mut [u8]);
}
impl<C: SyncStreamCipher> StreamCipher for C {
#[inline(always)]
fn encrypt(&mut self, data: &mut [u8]) {
SyncStreamCipher::apply_keystream(self, data);
}
#[inline(always)]
fn decrypt(&mut self, data: &mut [u8]) {
SyncStreamCipher::apply_keystream(self, data);
}
}
impl<C: SyncStreamCipher> SyncStreamCipher for &mut C {
#[inline]
fn apply_keystream(&mut self, data: &mut [u8]) {
C::apply_keystream(self, data);
}
#[inline]
fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> {
C::try_apply_keystream(self, data)
}
}
pub trait FromBlockCipher {
type BlockCipher: BlockCipher;
type NonceSize: ArrayLength<u8>;
fn from_block_cipher(
cipher: Self::BlockCipher,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> Self;
}
pub trait FromBlockCipherMut {
type BlockCipher: BlockCipherMut;
type NonceSize: ArrayLength<u8>;
fn from_block_cipher_mut(
cipher: Self::BlockCipher,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> Self;
}
impl<C> FromBlockCipherMut for C
where
C: FromBlockCipher,
{
type BlockCipher = <Self as FromBlockCipher>::BlockCipher;
type NonceSize = <Self as FromBlockCipher>::NonceSize;
fn from_block_cipher_mut(
cipher: Self::BlockCipher,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> C {
C::from_block_cipher(cipher, nonce)
}
}
impl<C> NewStreamCipher for C
where
C: FromBlockCipherMut,
C::BlockCipher: NewBlockCipher,
{
type KeySize = <<Self as FromBlockCipherMut>::BlockCipher as NewBlockCipher>::KeySize;
type NonceSize = <Self as FromBlockCipherMut>::NonceSize;
fn new(key: &Key<Self>, nonce: &Nonce<Self>) -> C {
C::from_block_cipher_mut(
<<Self as FromBlockCipherMut>::BlockCipher as NewBlockCipher>::new(key),
nonce,
)
}
fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidKeyNonceLength> {
if nonce.len() != Self::NonceSize::USIZE {
Err(InvalidKeyNonceLength)
} else {
C::BlockCipher::new_varkey(key)
.map_err(|_| InvalidKeyNonceLength)
.map(|cipher| {
let nonce = GenericArray::from_slice(nonce);
Self::from_block_cipher_mut(cipher, nonce)
})
}
}
}
#[rustfmt::skip]
pub trait SeekNum:
Sized
+ TryInto<u8> + TryFrom<u8> + TryInto<i8> + TryFrom<i8>
+ TryInto<u16> + TryFrom<u16> + TryInto<i16> + TryFrom<i16>
+ TryInto<u32> + TryFrom<u32> + TryInto<i32> + TryFrom<i32>
+ TryInto<u64> + TryFrom<u64> + TryInto<i64> + TryFrom<i64>
+ TryInto<u128> + TryFrom<u128> + TryInto<i128> + TryFrom<i128>
+ TryInto<usize> + TryFrom<usize> + TryInto<isize> + TryFrom<isize>
{
fn from_block_byte<T: SeekNum>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError>;
fn to_block_byte<T: SeekNum>(self, bs: u8) -> Result<(T, u8), OverflowError>;
}
macro_rules! impl_seek_num {
{$($t:ty )*} => {
$(
impl SeekNum for $t {
fn from_block_byte<T: TryInto<Self>>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError> {
debug_assert!(byte < bs);
let block = block.try_into().map_err(|_| OverflowError)?;
let pos = block.checked_mul(bs as Self).ok_or(OverflowError)? + (byte as Self);
Ok(pos)
}
fn to_block_byte<T: TryFrom<Self>>(self, bs: u8) -> Result<(T, u8), OverflowError> {
let bs = bs as Self;
let byte = self % bs;
let block = T::try_from(self/bs).map_err(|_| OverflowError)?;
Ok((block, byte as u8))
}
}
)*
};
}
impl_seek_num! { u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 isize usize }