diff --git a/cipher/src/block.rs b/cipher/src/block.rs index 551e9d14a..06f9f58fc 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -185,3 +185,137 @@ impl BlockCipher for &Alg { Alg::decrypt_blocks(self, blocks); } } + +/// Encrypt-only functionality for block ciphers +pub trait Encrypt { + /// Size of the block in bytes + type BlockSize: ArrayLength; + + /// Encrypt block in-place + fn encrypt_block(&self, block: &mut GenericArray); + + /// Encrypt a slice of blocks, leveraging parallelism when available. + #[inline] + fn encrypt_blocks(&self, blocks: &mut [GenericArray]) { + for block in blocks { + self.encrypt_block(block); + } + } +} + +/// Block cipher which can encrypt several blocks in parallel +pub trait EncryptPar { + /// Size of the block in bytes + type BlockSize: ArrayLength; + + /// Number of blocks which can be processed in parallel by + /// cipher implementation + type ParBlocks: ArrayLength>; + + /// Encrypt block in-place + fn encrypt_block(&self, block: &mut GenericArray); + + /// Encrypt several blocks in parallel using instruction level parallelism + /// if possible. + /// + /// If `ParBlocks` equals to 1 it's equivalent to `encrypt_block`. + fn encrypt_par_blocks( + &self, + blocks: &mut GenericArray, Self::ParBlocks>, + ); +} + +impl Encrypt for Alg { + type BlockSize = Alg::BlockSize; + + #[inline] + fn encrypt_block(&self, block: &mut GenericArray) { + ::encrypt_block(self, block); + } + + #[inline] + fn encrypt_blocks(&self, mut blocks: &mut [GenericArray]) { + let pb = ::ParBlocks::to_usize(); + + if pb > 1 { + let mut iter = blocks.chunks_exact_mut(pb); + + for chunk in &mut iter { + self.encrypt_par_blocks(chunk.try_into().unwrap()) + } + + blocks = iter.into_remainder(); + } + + for block in blocks { + self.encrypt_block(block); + } + } +} + +/// Decrypt-only functionality for block ciphers +pub trait Decrypt { + /// Size of the block in bytes + type BlockSize: ArrayLength; + + /// Decrypt block in-place + fn decrypt_block(&self, block: &mut GenericArray); + + /// Decrypt a slice of blocks, leveraging parallelism when available. + #[inline] + fn decrypt_blocks(&self, blocks: &mut [GenericArray]) { + for block in blocks.iter_mut() { + self.decrypt_block(block); + } + } +} + +/// Block cipher which can decrypt several blocks in parallel +pub trait DecryptPar { + /// Size of the block in bytes + type BlockSize: ArrayLength; + + /// Number of blocks which can be processed in parallel by + /// cipher implementation + type ParBlocks: ArrayLength>; + + /// Decrypt block in-place + fn decrypt_block(&self, block: &mut GenericArray); + + /// Decrypt several blocks in parallel using instruction level parallelism + /// if possible. + /// + /// If `ParBlocks` equals to 1 it's equivalent to `decrypt_block`. + fn decrypt_par_blocks( + &self, + blocks: &mut GenericArray, Self::ParBlocks>, + ); +} + +impl Decrypt for Alg { + type BlockSize = Alg::BlockSize; + + #[inline] + fn decrypt_block(&self, block: &mut GenericArray) { + ::decrypt_block(self, block); + } + + #[inline] + fn decrypt_blocks(&self, mut blocks: &mut [GenericArray]) { + let pb = ::ParBlocks::to_usize(); + + if pb > 1 { + let mut iter = blocks.chunks_exact_mut(pb); + + for chunk in &mut iter { + self.decrypt_par_blocks(chunk.try_into().unwrap()) + } + + blocks = iter.into_remainder(); + } + + for block in blocks { + self.decrypt_block(block); + } + } +}