crown/modes/cbc/
encryptor.rs1use crate::{
2 block::{BlockCipher, BlockCipherMarker},
3 modes::BlockMode,
4 utils::subtle::xor::xor_bytes,
5};
6
7use super::CbcImpl;
8
9pub trait CbcEncryptor<B> {
11 fn to_cbc_enc(self, iv: &[u8]) -> impl BlockMode + 'static;
17}
18
19pub trait CbcEncryptorMarker {}
20impl<T: BlockCipherMarker> CbcEncryptorMarker for T {}
21
22struct CbcEncryptorImpl<B: BlockCipher>(CbcImpl<B>);
24
25impl CbcEncryptor<crate::block::aes::Aes> for crate::block::aes::Aes {
26 fn to_cbc_enc(self, iv: &[u8]) -> impl BlockMode + 'static {
27 crate::block::aes::cbc::CBCEncryptor::new(self, iv.try_into().unwrap())
28 }
29}
30
31impl<B: BlockCipher + CbcEncryptorMarker + 'static> CbcEncryptor<B> for B {
32 fn to_cbc_enc(self, iv: &[u8]) -> impl BlockMode + 'static {
33 if iv.len() != self.block_size() {
34 panic!(
35 "cipher.NewCBCEncrypter: IV length must equal block size: {}",
36 self.block_size()
37 );
38 }
39
40 CbcEncryptorImpl(CbcImpl::new(self, iv))
41 }
42}
43
44impl<B: BlockCipher> BlockMode for CbcEncryptorImpl<B> {
45 fn block_size(&self) -> usize {
46 self.0.block_size
47 }
48
49 fn encrypt(&mut self, inout: &mut [u8]) {
50 if inout.len() % self.0.block_size != 0 {
51 panic!("crypto/cipher: input not full blocks");
52 }
53
54 let mut iv = self.0.iv.clone();
55 let dst_chunks = inout.chunks_exact_mut(self.0.block_size);
56
57 for dst_block in dst_chunks {
58 xor_bytes(dst_block, &iv);
60 self.0.b.encrypt_block(dst_block);
61
62 iv.copy_from_slice(dst_block);
64 }
65
66 self.0.iv.copy_from_slice(&iv);
68 }
69 fn decrypt(&mut self, _inout: &mut [u8]) {
70 todo!()
71 }
72}