use super::BlockMode;
use crate::Result;
use cipher::common::array::{Array, ArraySize};
#[derive(Clone, Debug)]
pub(crate) struct State<Size: ArraySize> {
mode: BlockMode,
bytes: Array<u8, Size>,
}
impl<Size: ArraySize> State<Size> {
pub(crate) fn new(mode: BlockMode, iv: &Array<u8, Size>) -> Self {
debug_assert!(
mode != BlockMode::Ctr || Size::USIZE == 16,
"we only support CTR for 128-bit block sizes"
);
Self {
bytes: iv.clone(),
mode,
}
}
pub(crate) fn new_from_slice(mode: BlockMode, iv: &[u8]) -> Result<Self> {
Ok(Self::new(mode, iv.try_into()?))
}
pub(crate) fn mode(&self) -> BlockMode {
self.mode
}
pub(crate) fn increment_counter(&mut self) {
debug_assert_eq!(self.mode, BlockMode::Ctr);
debug_assert!(self.bytes.len() <= 16);
let offset = 16 - Size::USIZE;
let mut bytes = [0u8; 16];
bytes[offset..].copy_from_slice(&self.bytes);
let n = u128::from_be_bytes(bytes);
let bytes = n.wrapping_add(1).to_be_bytes();
self.bytes.copy_from_slice(&bytes[offset..]);
}
pub(crate) fn xor_into(&self, block: &mut Array<u8, Size>) {
for i in 0..Size::USIZE {
block[i] ^= self.bytes[i];
}
}
}
impl<Size: ArraySize> AsRef<Array<u8, Size>> for State<Size> {
fn as_ref(&self) -> &Array<u8, Size> {
&self.bytes
}
}
impl<Size: ArraySize> AsMut<Array<u8, Size>> for State<Size> {
fn as_mut(&mut self) -> &mut Array<u8, Size> {
&mut self.bytes
}
}