1use core::marker::PhantomData;
2
3use crate::{Decrypt, Encrypt, Error, ecb_dec, ecb_enc};
4use cipher::{
5 Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncBackend,
6 BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, IvSizeUser,
7 array::ArraySize,
8 common::{InnerInit, InnerUser},
9 inout::InOutBuf,
10 typenum::Unsigned,
11};
12
13#[derive(Debug)]
15pub struct EcbCs1<C: BlockSizeUser> {
16 cipher: C,
17}
18
19impl<C: BlockSizeUser> InnerUser for EcbCs1<C> {
20 type Inner = C;
21}
22
23impl<C: BlockSizeUser> IvSizeUser for EcbCs1<C> {
24 type IvSize = C::BlockSize;
25}
26
27impl<C: BlockSizeUser> InnerInit for EcbCs1<C> {
28 fn inner_init(cipher: Self::Inner) -> Self {
29 Self { cipher }
30 }
31}
32
33impl<C: BlockCipherEncrypt> Encrypt for EcbCs1<C> {
34 fn encrypt_inout(self, buf: InOutBuf<'_, '_, u8>) -> Result<(), Error> {
35 if buf.len() < C::BlockSize::USIZE {
36 return Err(Error);
37 }
38 self.cipher.encrypt_with_backend(Closure {
39 buf,
40 _pd: PhantomData,
41 });
42 Ok(())
43 }
44}
45
46impl<C: BlockCipherDecrypt> Decrypt for EcbCs1<C> {
47 fn decrypt_inout(self, buf: InOutBuf<'_, '_, u8>) -> Result<(), Error> {
48 if buf.len() < C::BlockSize::USIZE {
49 return Err(Error);
50 }
51 self.cipher.decrypt_with_backend(Closure {
52 buf,
53 _pd: PhantomData,
54 });
55 Ok(())
56 }
57}
58
59struct Closure<'a, BS: ArraySize> {
60 buf: InOutBuf<'a, 'a, u8>,
61 _pd: PhantomData<BS>,
62}
63
64impl<BS: ArraySize> BlockSizeUser for Closure<'_, BS> {
65 type BlockSize = BS;
66}
67
68impl<BS: ArraySize> BlockCipherEncClosure for Closure<'_, BS> {
69 fn call<B: BlockCipherEncBackend<BlockSize = BS>>(self, cipher: &B) {
70 let mut buf = self.buf;
71 let (mut blocks, tail) = buf.reborrow().into_chunks();
72
73 ecb_enc(cipher, blocks.reborrow());
74
75 if tail.is_empty() {
76 return;
77 }
78
79 let last_block = blocks.get_out().last_mut().unwrap();
80 let mut block = Block::<B>::default();
81
82 let n = tail.len();
83
84 block[..n].copy_from_slice(tail.get_in());
85 block[n..].copy_from_slice(&last_block[n..]);
86 cipher.encrypt_block_inplace(&mut block);
87
88 let pos = buf.len() - block.len();
89 buf.get_out()[pos..].copy_from_slice(&block);
90 }
91}
92
93impl<BS: ArraySize> BlockCipherDecClosure for Closure<'_, BS> {
94 fn call<B: BlockCipherDecBackend<BlockSize = BS>>(self, cipher: &B) {
95 let mut buf = self.buf;
96 let (mut blocks, tail) = buf.reborrow().into_chunks();
97
98 if !tail.is_empty() {
99 let mid = blocks.len() - 1;
100 blocks = blocks.split_at(mid).0;
101 };
102
103 ecb_dec(cipher, blocks);
104
105 if tail.is_empty() {
106 return;
107 }
108
109 let tail_len = tail.len();
110 let bs = B::BlockSize::USIZE;
111 let mid = buf.len() - (bs + tail_len);
112 let mut rem = buf.split_at(mid).1;
113
114 let n = rem.len() - bs;
115 let mut block1: Block<B> = rem.get_in()[..bs].try_into().unwrap();
116 let mut block2: Block<B> = rem.get_in()[n..].try_into().unwrap();
117
118 cipher.decrypt_block_inplace(&mut block2);
119 block1[n..].copy_from_slice(&block2[n..]);
120
121 cipher.decrypt_block_inplace(&mut block1);
122
123 rem.get_out()[..bs].copy_from_slice(&block1);
124 rem.get_out()[bs..].copy_from_slice(&block2[..n]);
125 }
126}