diff --git a/xts/benches/aes.rs b/xts/benches/aes.rs index e44e6f4..e131f22 100644 --- a/xts/benches/aes.rs +++ b/xts/benches/aes.rs @@ -1,7 +1,7 @@ #![feature(test)] extern crate test; -use aes::{ Aes128, Aes256 }; +use aes::{Aes128, Aes256}; cipher::block_encryptor_bench!( KeyIv: xts::Encryptor, diff --git a/xts/src/decrypt.rs b/xts/src/decrypt.rs index fefd342..ffdfa6d 100644 --- a/xts/src/decrypt.rs +++ b/xts/src/decrypt.rs @@ -1,6 +1,7 @@ use core::{fmt, ops::Add}; -use crate::xts_core::{precompute_iv, Xts}; +use crate::xts_core::{precompute_iv, Stealer, Xts}; +use crate::{Error, Result}; use cipher::{ array::ArraySize, crypto_common::{BlockSizes, IvSizeUser}, @@ -8,7 +9,7 @@ use cipher::{ typenum::Sum, AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncrypt, BlockModeDecBackend, BlockModeDecClosure, BlockModeDecrypt, BlockSizeUser, - Iv, IvState, Key, KeyInit, KeyIvInit, KeySizeUser, ParBlocks, ParBlocksSizeUser, + InOutBuf, Iv, IvState, Key, KeyInit, KeyIvInit, KeySizeUser, ParBlocks, ParBlocksSizeUser, }; #[cfg(feature = "zeroize")] @@ -87,6 +88,34 @@ where pub fn reset_iv(&mut self, iv: &Block) { self.iv = precompute_iv(&self.tweaker, iv) } + + /// Decrypt `inout` buffer. + pub fn decrypt_inout(&mut self, mut buf: InOutBuf<'_, '_, u8>) -> Result<()> { + if buf.len() < C::BlockSize::USIZE { + return Err(Error); + }; + + { + let (blocks, _) = buf.reborrow().into_chunks(); + self.decrypt_blocks_inout(blocks); + } + + self.ciphertext_stealing(buf.get_out()); + + Ok(()) + } + + /// Decrypt data in-place. + fn decrypt(&mut self, buf: &mut [u8]) -> Result<()> { + self.decrypt_inout(buf.into()) + } + + /// Decrypt data buffer-to-buffer. + fn decrypt_b2b(&mut self, in_buf: &[u8], out_buf: &mut [u8]) -> Result<()> { + InOutBuf::new(in_buf, out_buf) + .map_err(|_| Error) + .and_then(|buf| self.decrypt_inout(buf)) + } } impl BlockSizeUser for SplitDecryptor @@ -95,7 +124,7 @@ where C: BlockCipherDecrypt, T: BlockCipherEncrypt, { - type BlockSize = C::BlockSize; + type BlockSize = BS; } impl BlockModeDecrypt for SplitDecryptor @@ -147,13 +176,33 @@ where } } +impl Stealer for SplitDecryptor +where + BS: BlockSizes, + C: BlockCipherDecrypt, + T: BlockCipherEncrypt, +{ + fn process_block(&self, block: &mut Block) { + self.cipher.decrypt_block(block); + } + + fn get_iv_mut(&mut self) -> &mut Block { + &mut self.iv + } + + #[inline(always)] + fn is_decrypt() -> bool { + false + } +} + impl IvSizeUser for SplitDecryptor where BS: BlockSizes, C: BlockCipherDecrypt, T: BlockCipherEncrypt, { - type IvSize = C::BlockSize; + type IvSize = BS; } impl IvState for SplitDecryptor @@ -290,9 +339,4 @@ where fn get_iv_mut(&mut self) -> &mut Block { self.iv } - - #[inline(always)] - fn is_decrypt() -> bool { - true - } } diff --git a/xts/src/encrypt.rs b/xts/src/encrypt.rs index c35abdf..31dd474 100644 --- a/xts/src/encrypt.rs +++ b/xts/src/encrypt.rs @@ -1,8 +1,10 @@ -use crate::xts_core::{precompute_iv, Xts}; +use crate::xts_core::{precompute_iv, Stealer, Xts}; +use crate::{Error, Result}; +use cipher::InOutBuf; use cipher::{ - array::ArraySize, crypto_common::BlockSizes, typenum::Sum, AlgorithmName, - Block, BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockModeEncBackend, + array::ArraySize, crypto_common::BlockSizes, typenum::Sum, AlgorithmName, Block, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockModeEncBackend, BlockModeEncClosure, BlockModeEncrypt, BlockSizeUser, InOut, Iv, IvSizeUser, IvState, Key, KeyInit, KeyIvInit, KeySizeUser, ParBlocks, ParBlocksSizeUser, }; @@ -85,6 +87,34 @@ where pub fn reset_iv(&mut self, iv: &Block) { self.iv = precompute_iv(&self.tweaker, iv) } + + /// Encrypt `inout` buffer. + pub fn encrypt_inout(&mut self, mut buf: InOutBuf<'_, '_, u8>) -> Result<()> { + if buf.len() < C::BlockSize::USIZE { + return Err(Error); + }; + + { + let (blocks, _) = buf.reborrow().into_chunks(); + self.encrypt_blocks_inout(blocks); + } + + self.ciphertext_stealing(buf.get_out()); + + Ok(()) + } + + /// Encrypt data in-place. + fn encrypt(&mut self, buf: &mut [u8]) -> Result<()> { + self.encrypt_inout(buf.into()) + } + + /// Encrypt data buffer-to-buffer. + fn encrypt_b2b(&mut self, in_buf: &[u8], out_buf: &mut [u8]) -> Result<()> { + InOutBuf::new(in_buf, out_buf) + .map_err(|_| Error) + .and_then(|buf| self.encrypt_inout(buf)) + } } impl BlockSizeUser for SplitEncryptor @@ -93,7 +123,7 @@ where C: BlockCipherEncrypt, T: BlockCipherEncrypt, { - type BlockSize = C::BlockSize; + type BlockSize = BS; } impl IvSizeUser for SplitEncryptor @@ -165,6 +195,26 @@ where } } +impl Stealer for SplitEncryptor +where + BS: BlockSizes, + C: BlockCipherEncrypt, + T: BlockCipherEncrypt, +{ + fn process_block(&self, block: &mut Block) { + self.cipher.encrypt_block(block); + } + + fn get_iv_mut(&mut self) -> &mut Block { + &mut self.iv + } + + #[inline(always)] + fn is_decrypt() -> bool { + false + } +} + impl AlgorithmName for SplitEncryptor where BS: BlockSizes, @@ -192,7 +242,7 @@ where } impl Drop for SplitEncryptor -where +where C: BlockCipherEncrypt, T: BlockCipherEncrypt, { @@ -280,11 +330,6 @@ where } fn get_iv_mut(&mut self) -> &mut Block { - self.iv - } - - #[inline(always)] - fn is_decrypt() -> bool { - false + &mut self.iv } } diff --git a/xts/src/xts_core.rs b/xts/src/xts_core.rs index 8af76ea..4677c2f 100644 --- a/xts/src/xts_core.rs +++ b/xts/src/xts_core.rs @@ -1,4 +1,5 @@ use cipher::typenum::Unsigned; +use cipher::BlockCipherDecrypt; use cipher::{ crypto_common::BlockSizes, Array, Block, BlockCipherEncrypt, BlockSizeUser, InOut, InOutBuf, ParBlocks, ParBlocksSizeUser, @@ -31,9 +32,6 @@ pub trait Xts: ParBlocksSizeUser + BlockSizeUser { /// Gets the IV reference. fn get_iv_mut(&mut self) -> &mut Array; - /// There is a slight difference regarding the tweak during decryption - fn is_decrypt() -> bool; - //Unused but keeping for now just in case fn _process(&self, mut block: InOut<'_, '_, Block>) { let mut b = block.clone_in(); @@ -122,51 +120,17 @@ pub trait Xts: ParBlocksSizeUser + BlockSizeUser { } } -pub trait XtsMode: Xts { - fn process_all_in_place(&mut self, buffer: &mut [u8]) -> Result<()> { - let block_size = Self::block_size(); - let par_blocks_size = Self::ParBlocksSize::USIZE; - - if buffer.len() < block_size { - return Err(Error); - } - - let need_stealing = buffer.len() % Self::block_size() == 0; - - let (buffer, remaining_buffer) = if need_stealing { - buffer.split_at_mut((buffer.len() / block_size - 1) * block_size) - } else { - (buffer, [0u8; 0].as_mut_slice()) - }; - - // Split buffer into blocks - let mut blocks = buffer - .chunks_exact_mut(block_size) - .map(|b| <&mut Block>::try_from(b).unwrap()); - - // Can't figure out how to get parblocks in place here, commenting for now - // if par_blocks_size > 1 { - // let mut blocks: alloc::vec::Vec<&mut Block> = blocks.collect(); +pub(crate) trait Stealer: BlockSizeUser { + /// Encrypt/Decrypt the block + fn process_block(&self, block: &mut Block); - // let mut par_blocks = blocks.chunks_exact_mut(par_blocks_size); - // for b in par_blocks { - // let mut b = <&mut ParBlocks>::try_from(*b).unwrap(); - // } - - // self.process_tail_blocks_inplace(tail); - // } else { - for b in blocks { - self.process_block_inplace(b); - } - //} - - if need_stealing { - self.ciphertext_stealing(remaining_buffer); - }; + /// Gets the IV reference. + fn get_iv_mut(&mut self) -> &mut Array; - Ok(()) - } + /// There is a slight difference regarding the tweak during decryption + fn is_decrypt() -> bool; + /// Perform the ciphertext stealing phase fn ciphertext_stealing(&mut self, buffer: &mut [u8]) { let remaining_bytes = buffer.len() - Self::block_size(); @@ -185,7 +149,7 @@ pub trait XtsMode: Xts { carry }; - self.process_inplace(second_to_last_block); + self.process_block(second_to_last_block); { let iv = self.get_iv_mut(); @@ -195,7 +159,7 @@ pub trait XtsMode: Xts { } } else { // Process normally - self.process_block_inplace(second_to_last_block); + self.process_block(second_to_last_block); } // We first swap the remaining bytes with the previous block's @@ -209,6 +173,6 @@ pub trait XtsMode: Xts { let second_to_last_block: &mut Block = (&mut buffer[0..Self::block_size()]) .try_into() .expect("Not a full block on second to last block!"); - self.process_block_inplace(second_to_last_block); + self.process_block(second_to_last_block); } } diff --git a/xts/tests/aes.rs b/xts/tests/aes.rs index c18532b..63653be 100644 --- a/xts/tests/aes.rs +++ b/xts/tests/aes.rs @@ -1,6 +1,6 @@ use aes::*; -use xts::{Decryptor, Encryptor}; use cipher::{block_mode_dec_test, block_mode_enc_test}; +use xts::{Decryptor, Encryptor}; #[test] fn manual_test() {