use std::cell::Cell;
use crate::{Cipher, CryptoError, CryptoErrorKind};
use crate::cipher_mode::{Padding, InitialVec, EncryptStream, Pond, DecryptStream};
use std::marker::PhantomData;
pub struct CFB<C, P, IV> {
s: usize,
buf: Cell<Vec<u8>>,
cur_iv: Vec<u8>,
cipher: C,
padding: P,
iv: IV,
phd: PhantomData<*const u8>,
}
impl<C, P, IV> CFB<C, P, IV>
where C: Cipher, P: 'static + Padding, IV: InitialVec<C> {
pub fn new(c: C, p: P, iv: IV, s: usize) -> Result<Self, CryptoError> {
if (s & 7) > 0 {
return Err(CryptoError::new(CryptoErrorKind::InvalidParameter,
format!("Wrong s: {}, s % 8 must be equal to 0", s)));
}
let s = s >> 3;
if s < 1 || s > c.block_size().unwrap_or(s) {
return Err(CryptoError::new(CryptoErrorKind::InvalidParameter,
format!("Wrong s(in bytes): {}, the s need to satisfy 1 <= s <= {}", s, c.block_size().unwrap_or(s))));
}
let mut curiv = Vec::new();
curiv.resize(s, 0);
p.padding(&mut curiv);
if (curiv.len() % s) != 0 {
return Err(CryptoError::new(CryptoErrorKind::InvalidParameter,
format!("Wrong padding len: {}, the padding len should be equal to a multiple of s: {}", curiv.len(), s)));
}
let mut iv = iv;
if let Err(e) = iv.initial_vec(&mut curiv) {
return Err(e);
} else if c.block_size().is_some() && curiv.len() != c.block_size().unwrap() {
return Err(CryptoError::new(CryptoErrorKind::InnerErr,
format!("Wrong IV len: {}, the IV len must be the {} in bytes", curiv.len(), c.block_size().unwrap())));
}
let block_len = c.block_size().unwrap_or(1);
Ok(Self {
buf: Cell::new(Vec::with_capacity(block_len)),
cur_iv: curiv,
cipher: c,
padding: p,
iv,
s,
phd: PhantomData,
})
}
pub fn update_iv(&mut self) -> Result<&Vec<u8>, CryptoError> {
let block_len = self.cipher.block_size().unwrap_or(1);
match self.iv.initial_vec(&mut self.cur_iv) {
Ok(_) => {
if self.cipher.block_size().is_some() && block_len != self.cur_iv.len() {
Err(CryptoError::new(CryptoErrorKind::InnerErr,
format!("Wrong IV len: {}, the IV len must be the {} in bytes", self.cur_iv.len(), block_len)))
} else {
Ok(&self.cur_iv)
}
},
Err(e) => Err(e),
}
}
pub fn cur_iv(&self) -> Vec<u8> {
self.cur_iv.clone()
}
pub fn set_iv(&mut self, iv: Vec<u8>) -> Result<(), CryptoError> {
let block_len = self.cipher.block_size().unwrap_or(1);
if self.cipher.block_size().is_some() && iv.len() != block_len {
Err(CryptoError::new(CryptoErrorKind::InvalidParameter,
format!("Wrong IV len: {}, the IV len must be the {} in bytes", self.cur_iv.len(), block_len)))
} else {
let mut iv = iv;
self.cur_iv.clear();
self.cur_iv.append(&mut iv);
Ok(())
}
}
#[inline]
fn get_buf(&self) -> &mut Vec<u8> {
unsafe {
&mut (*self.buf.as_ptr())
}
}
pub fn encrypt_stream(self) -> CFBEncrypt<C, P, IV> {
CFBEncrypt {
pond: Vec::with_capacity(self.cipher.block_size().unwrap_or(1)),
data: Vec::with_capacity(self.cipher.block_size().unwrap_or(1)),
ij: self.cur_iv.clone(),
cfb: self,
}
}
pub fn decrypt_stream(self) -> CFBDecrypt<C, P, IV> {
CFBDecrypt {
pond: Vec::with_capacity(self.cipher.block_size().unwrap_or(1)),
data: Vec::with_capacity(self.cipher.block_size().unwrap_or(1)),
ij: self.cur_iv.clone(),
cfb: self,
}
}
fn encrypt_inner(&self, ij: &mut Vec<u8>, dst: &mut Vec<u8>, mut data: &[u8]) -> Result<usize, CryptoError> {
let oj = self.get_buf();
while data.len() >= self.s {
match self.cipher.encrypt(oj, ij.as_slice()) {
Ok(_) => {
let block = &data[..self.s];
oj.iter_mut().take(self.s).zip(block.iter()).for_each(|(a, &b)| {
*a = (*a) ^ b;
});
dst.extend(oj.iter().take(self.s));
let oj_len = oj.len();
oj.extend(ij.iter().skip(self.s));
ij.clear();
ij.extend(oj.iter().skip(oj_len));
ij.extend(oj.iter().take(self.s));
data = &data[self.s..];
},
Err(e) => {
return Err(e);
}
}
}
Ok(dst.len())
}
fn decrypt_inner(&self, ij: &mut Vec<u8>, dst: &mut Vec<u8>, mut data: &[u8]) -> Result<usize, CryptoError> {
let oj = self.get_buf();
while !data.is_empty() {
match self.cipher.encrypt(oj, ij.as_slice()) {
Ok(_) => {
let cj = &data[..self.s];
cj.iter().zip(oj.iter().take(self.s)).for_each(|(&a, &b)| {
dst.push(a ^ b);
});
oj.clear();
oj.extend(ij.iter().skip(self.s));
ij.clear();
ij.append(oj);
ij.extend_from_slice(cj);
data = &data[self.s..];
},
Err(e) => {
return Err(e);
}
}
}
Ok(dst.len())
}
}
impl<C, P, IV> Cipher for CFB<C, P, IV>
where C: Cipher, P: 'static + Padding, IV: InitialVec<C> {
type Output = usize;
fn block_size(&self) -> Option<usize> {
self.cipher.block_size()
}
fn encrypt(&self, dst: &mut Vec<u8>, plaintext_block: &[u8]) -> Result<usize, CryptoError> {
let mut ij = self.cur_iv.clone();
dst.clear();
self.encrypt_inner(&mut ij, dst, plaintext_block)?;
let remain = plaintext_block.len() % self.s;
let mut data = plaintext_block[(plaintext_block.len() - remain)..plaintext_block.len()].to_vec();
self.padding.padding(&mut data);
self.encrypt_inner(&mut ij, dst, data.as_slice())
}
fn decrypt(&self, dst: &mut Vec<u8>, cipher_block: &[u8]) -> Result<usize, CryptoError> {
if cipher_block.len() % self.s != 0 {
return Err(CryptoError::new(CryptoErrorKind::InvalidParameter,
format!("Wrong ciphertext len: {}, the ciphertext block length(in bytes) should be equal to {}", cipher_block.len(), self.s)));
}
dst.clear();
let mut ij = self.cur_iv.clone();
self.decrypt_inner(&mut ij, dst, cipher_block)?;
self.padding.unpadding(dst)
}
}
impl<C, P, IV> Clone for CFB<C, P, IV>
where C: Cipher + Clone, P: 'static + Padding + Clone, IV: InitialVec<C> + Clone {
fn clone(&self) -> Self {
Self {
s: self.s,
buf: Cell::new(Vec::with_capacity(self.cipher.block_size().unwrap_or(1))),
cur_iv: self.cur_iv.clone(),
cipher: self.cipher.clone(),
padding: self.padding.clone(),
iv: self.iv.clone(),
phd: PhantomData,
}
}
}
pub struct CFBEncrypt<C, P, IV> {
cfb: CFB<C, P, IV>,
data: Vec<u8>,
pond: Vec<u8>,
ij: Vec<u8>,
}
pub struct CFBDecrypt<C, P, IV> {
cfb: CFB<C, P, IV>,
data: Vec<u8>,
pond: Vec<u8>,
ij: Vec<u8>,
}
impl_cipher_iv!(CFBEncrypt, cfb);
impl_fn_reset_iv!(CFBEncrypt, cfb);
impl_cipher_iv!(CFBDecrypt, cfb);
impl_fn_reset_iv!(CFBDecrypt, cfb);
impl<C, P, IV> EncryptStream for CFBEncrypt<C, P, IV>
where C: Cipher, P: 'static + Padding, IV: InitialVec<C> {
fn write(&mut self, data: &[u8]) -> Result<Pond, CryptoError> {
let mut data = data;
if data.is_empty() {
return Ok(Pond::new(&mut self.pond, false));
} else {
let len = std::cmp::min(self.cfb.s - self.data.len(), data.len());
self.data.extend(data.iter().take(len));
data = &data[len..];
}
if self.data.len() == self.cfb.s {
if let Err(e) = self.cfb.encrypt_inner(&mut self.ij, &mut self.pond, self.data.as_slice()) {
return Err(e);
} else {
self.data.clear();
}
}
if let Err(e) = self.cfb.encrypt_inner(&mut self.ij, &mut self.pond, data) {
Err(e)
} else {
let len = data.len() % self.cfb.s;
data = &data[(data.len() - len)..];
self.data.extend_from_slice(data);
Ok(Pond::new(&mut self.pond, false))
}
}
fn finish(&mut self) -> Result<Pond, CryptoError> {
self.cfb.padding.padding(&mut self.data);
if let Err(e) = self.cfb.encrypt_inner(&mut self.ij, &mut self.pond, self.data.as_slice()) {
Err(e)
} else {
self.data.clear();
self.ij.clear();
self.ij.extend(self.cfb.cur_iv.iter());
Ok(Pond::new(&mut self.pond, true))
}
}
}
impl<C, P, IV> DecryptStream for CFBDecrypt<C, P, IV>
where C: Cipher, P: 'static + Padding, IV: InitialVec<C> {
fn write(&mut self, data: &[u8]) -> Result<Pond, CryptoError> {
if data.is_empty() {
return Ok(Pond::new(&mut self.pond, false));
} else {
self.data.extend_from_slice(data);
}
let bound = self.data.len() - (self.data.len() % self.cfb.s);
let data = &self.data.as_slice()[..bound];
if let Err(e) = self.cfb.decrypt_inner(&mut self.ij, &mut self.pond, data) {
Err(e)
} else {
let tmp = self.cfb.get_buf();
tmp.clear();
tmp.extend_from_slice(&self.data.as_slice()[bound..]);
self.data.clear();
self.data.append(tmp);
Ok(Pond::new(&mut self.pond, false))
}
}
fn finish(&mut self) -> Result<Pond, CryptoError> {
if let Err(e) = self.cfb.decrypt_inner(&mut self.ij, &mut self.pond, self.data.as_slice()) {
Err(e)
} else {
if let Err(e) = self.cfb.padding.unpadding(&mut self.pond) {
return Err(e);
} else {
self.data.clear();
self.ij.clear();
self.ij.extend(self.cfb.cur_iv.iter());
}
Ok(Pond::new(&mut self.pond, true))
}
}
}