cts/
ecb_cs1_enc.rs

1use crate::{ecb_enc, Encrypt, Error};
2use cipher::{
3    crypto_common::{InnerInit, InnerUser},
4    inout::InOutBuf,
5    typenum::Unsigned,
6    ArrayLength, Block, BlockBackend, BlockClosure, BlockEncrypt, BlockSizeUser, IvSizeUser,
7};
8use core::marker::PhantomData;
9
10/// The ECB-CS-1 ciphertext stealing mode encryptor.
11#[derive(Clone)]
12pub struct EcbCs1Enc<C: BlockEncrypt> {
13    cipher: C,
14}
15
16impl<C: BlockEncrypt> InnerUser for EcbCs1Enc<C> {
17    type Inner = C;
18}
19
20impl<C: BlockEncrypt> IvSizeUser for EcbCs1Enc<C> {
21    type IvSize = C::BlockSize;
22}
23
24impl<C: BlockEncrypt> InnerInit for EcbCs1Enc<C> {
25    fn inner_init(cipher: Self::Inner) -> Self {
26        Self { cipher }
27    }
28}
29
30impl<C: BlockEncrypt> Encrypt for EcbCs1Enc<C> {
31    fn encrypt_inout(self, buf: InOutBuf<'_, '_, u8>) -> Result<(), Error> {
32        if buf.len() < C::BlockSize::USIZE {
33            return Err(Error);
34        }
35        self.cipher.encrypt_with_backend(Closure {
36            buf,
37            _pd: PhantomData,
38        });
39        Ok(())
40    }
41}
42
43struct Closure<'a, BS: ArrayLength<u8>> {
44    buf: InOutBuf<'a, 'a, u8>,
45    _pd: PhantomData<BS>,
46}
47
48impl<BS: ArrayLength<u8>> BlockSizeUser for Closure<'_, BS> {
49    type BlockSize = BS;
50}
51
52impl<BS: ArrayLength<u8>> BlockClosure for Closure<'_, BS> {
53    fn call<B: BlockBackend<BlockSize = BS>>(self, cipher: &mut B) {
54        let Self { mut buf, _pd } = self;
55        let (mut blocks, tail) = buf.reborrow().into_chunks();
56
57        ecb_enc(cipher, blocks.reborrow());
58
59        if tail.is_empty() {
60            return;
61        }
62
63        let last_block = blocks.get_out().last_mut().unwrap();
64        let mut block = Block::<B>::default();
65
66        let n = tail.len();
67
68        block[..n].copy_from_slice(tail.get_in());
69        block[n..].copy_from_slice(&last_block[n..]);
70        cipher.proc_block_inplace(&mut block);
71
72        let pos = buf.len() - block.len();
73        buf.get_out()[pos..].copy_from_slice(&block);
74    }
75}