tail_cbc/
unaligned_bytes_mut.rs

1use crate::{Block, BlockDecryptMut, BlockEncryptMut, BlockSizeUser, InOutBuf, TailError};
2
3/// In many cases, plaintext and ciphertext input is not divisible by the block size, and padding is often used.
4/// In practical use, however, this is not always done, and user-specified processing to an unaligned part like, for example, XOR, is often applied.
5/// This trait enables to apply additional processing to an unaligned [`tail`].
6pub trait UnalignedBytesDecryptMut: BlockDecryptMut + BlockSizeUser {
7    /// In many cases, plaintext and ciphertext input is not divisible by the block size, and padding is often used.
8    /// In practical use, however, this is not always done, and the termination may be handled by, for example, XOR.
9    /// This trait and fn [`proc_tail`] divides the input into aligned blocks and an unaligned part([`tail`]),
10    /// and then applies appropriate user-specified processing to the [`tail`].
11    fn proc_tail(
12        &self,
13        blocks: &mut InOutBuf<'_, '_, Block<Self>>,
14        tail: &mut InOutBuf<'_, '_, u8>,
15    ) -> Result<(), TailError>;
16
17    /// Decrypt `inout` bytes slice.
18    #[inline]
19    #[allow(unsafe_code)]
20    fn decrypt_bytes_inout_mut<'inp, 'out>(
21        &mut self,
22        data: InOutBuf<'inp, 'out, u8>,
23    ) -> Result<&'out [u8], TailError> {
24        let n = data.len();
25
26        let (mut blocks, mut tail) = data.into_chunks();
27        self.decrypt_blocks_inout_mut(blocks.reborrow());
28        if !tail.is_empty() {
29            self.proc_tail(&mut blocks, &mut tail)?
30        }
31        let out = unsafe {
32            let ptr = blocks.into_raw().1 as *const u8;
33            core::slice::from_raw_parts(ptr, n)
34        };
35        Ok(out)
36    }
37
38    /// Unaligned bytes input and decrypt in-place. Returns resulting plaintext slice.
39    ///
40    /// Returns [`TailError`] if length of output buffer is not sufficient.
41    #[inline]
42    fn decrypt_bytes_mut<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], TailError> {
43        self.decrypt_bytes_inout_mut(buf.into())
44    }
45
46    /// Unaligned bytes input and decrypt buffer-to-buffer. Returns resulting plaintext slice.
47    ///
48    /// Returns [`TailError`] if length of output buffer is not sufficient.
49    #[inline]
50    fn decrypt_bytes_b2b_mut<'a>(
51        &mut self,
52        msg: &[u8],
53        out_buf: &'a mut [u8],
54    ) -> Result<&'a [u8], TailError> {
55        self.decrypt_bytes_inout_mut(InOutBuf::new(msg, out_buf).unwrap())
56        // FIXME:  pass NotEqualError with TailError
57        //self.decrypt_bytes_inout_mut(InOutBuf::new(msg, out_buf)?)
58    }
59}
60
61/// In many cases, plaintext and ciphertext input is not divisible by the block size, and padding is often used.
62/// In practical use, however, this is not always done, and user-specified processing to an unaligned part like, for example, XOR, is often applied.
63/// This trait enables to apply additional processing to an unaligned [`tail`].
64pub trait UnalignedBytesEncryptMut: BlockEncryptMut + BlockSizeUser {
65    /// In many cases, plaintext and ciphertext input is not divisible by the block size, and padding is often used.
66    /// In practical use, however, this is not always done, and the termination may be handled by, for example, XOR.
67    /// This trait and fn [`proc_tail`] divides the input into aligned blocks and an unaligned part([`tail`]),
68    /// and then applies appropriate user-specified processing to the [`tail`].
69    fn proc_tail(
70        &self,
71        blocks: &mut InOutBuf<'_, '_, Block<Self>>,
72        tail: &mut InOutBuf<'_, '_, u8>,
73    ) -> Result<(), TailError>;
74
75    /// Encrypt `inout` bytes slice.
76    #[inline]
77    #[allow(unsafe_code)]
78    fn encrypt_bytes_inout_mut<'inp, 'out>(
79        &mut self,
80        data: InOutBuf<'inp, 'out, u8>,
81    ) -> Result<&'out [u8], TailError> {
82        let n = data.len();
83
84        let (mut blocks, mut tail) = data.into_chunks();
85        self.encrypt_blocks_inout_mut(blocks.reborrow());
86        if !tail.is_empty() {
87            self.proc_tail(&mut blocks, &mut tail)?
88        }
89        let out = unsafe {
90            let ptr = blocks.into_raw().1 as *const u8;
91            core::slice::from_raw_parts(ptr, n)
92        };
93        Ok(out)
94    }
95
96    /// Unaligned bytes input and encrypt in-place. Returns resulting plaintext slice.
97    ///
98    /// Returns [`TailError`] if length of output buffer is not sufficient.
99    #[inline]
100    fn encrypt_bytes_mut<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], TailError> {
101        self.encrypt_bytes_inout_mut(buf.into())
102    }
103
104    /// Unaligned bytes input and encrypt buffer-to-buffer. Returns resulting plaintext slice.
105    ///
106    /// Returns [`TailError`] if length of output buffer is not sufficient.
107    #[inline]
108    fn encrypt_bytes_b2b_mut<'a>(
109        &mut self,
110        msg: &[u8],
111        out_buf: &'a mut [u8],
112    ) -> Result<&'a [u8], TailError> {
113        self.encrypt_bytes_inout_mut(InOutBuf::new(msg, out_buf).unwrap())
114        // FIXME:  pass NotEqualError with TailError
115        //self.encrypt_bytes_inout_mut(InOutBuf::new(msg, out_buf)?)
116    }
117}