From 17eac70307759693568ee1e13ee9deca7b753621 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 8 Jun 2020 20:03:13 -0700 Subject: [PATCH] block-cipher: add BlockCipherMut Adds a stateful equivalent to `BlockCipher` that permits `&mut self` access to the underlying type. The main use case for this trait is hardware cryptographic accelerators which need to e.g. communitate with a peripheral device via an underlying `&mut` reference. While it's possible to use some underlying logic to use the existing `BlockCipher` trait in such a scenario, the solutions are somewhat ugly. Here is a real-world example: https://github.com/iqlusioninc/usbarmory.rs/blob/develop/firmware/usbarmory/src/dcp/aes128.rs#L198-L236 The idea with `BlockCipherMut` would be to alternatively provide `AeadMut`/`AeadMutInPlace` for AEAD modes with an underlying `BlockCipherMut` (when possible). --- block-cipher/src/lib.rs | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/block-cipher/src/lib.rs b/block-cipher/src/lib.rs index e7ea86e0d..d9be47f69 100644 --- a/block-cipher/src/lib.rs +++ b/block-cipher/src/lib.rs @@ -99,3 +99,79 @@ pub trait BlockCipher { } } } + +/// Stateful block cipher which permits `&mut self` access. +/// +/// The main use case for this trait is hardware encryption engines which +/// require `&mut self` access to an underlying hardware peripheral. +pub trait BlockCipherMut { + /// 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(&mut self, block: &mut GenericArray); + + /// Decrypt block in-place + fn decrypt_block(&mut 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`. + #[inline] + fn encrypt_blocks( + &mut self, + blocks: &mut GenericArray, Self::ParBlocks>, + ) { + for block in blocks.iter_mut() { + self.encrypt_block(block); + } + } + + /// Decrypt several blocks in parallel using instruction level parallelism + /// if possible. + /// + /// If `ParBlocks` equals to 1 it's equivalent to `decrypt_block`. + #[inline] + fn decrypt_blocks( + &mut self, + blocks: &mut GenericArray, Self::ParBlocks>, + ) { + for block in blocks.iter_mut() { + self.decrypt_block(block); + } + } +} + +impl BlockCipherMut for Alg { + type BlockSize = Alg::BlockSize; + type ParBlocks = Alg::ParBlocks; + + /// Encrypt block in-place + fn encrypt_block(&mut self, block: &mut GenericArray) { + ::encrypt_block(self, block); + } + + /// Decrypt block in-place + fn decrypt_block(&mut self, block: &mut GenericArray) { + ::decrypt_block(self, block); + } + + fn encrypt_blocks( + &mut self, + blocks: &mut GenericArray, Self::ParBlocks>, + ) { + ::encrypt_blocks(self, blocks); + } + + fn decrypt_blocks( + &mut self, + blocks: &mut GenericArray, Self::ParBlocks>, + ) { + ::decrypt_blocks(self, blocks); + } +}