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}