Skip to content

Commit

Permalink
block-cipher: add BlockCipherMut
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
tarcieri committed Jun 9, 2020
1 parent bdc337c commit 17eac70
Showing 1 changed file with 76 additions and 0 deletions.
76 changes: 76 additions & 0 deletions block-cipher/src/lib.rs
Expand Up @@ -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<u8>;

/// Number of blocks which can be processed in parallel by
/// cipher implementation
type ParBlocks: ArrayLength<GenericArray<u8, Self::BlockSize>>;

/// Encrypt block in-place
fn encrypt_block(&mut self, block: &mut GenericArray<u8, Self::BlockSize>);

/// Decrypt block in-place
fn decrypt_block(&mut self, block: &mut GenericArray<u8, Self::BlockSize>);

/// 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<GenericArray<u8, Self::BlockSize>, 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<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
) {
for block in blocks.iter_mut() {
self.decrypt_block(block);
}
}
}

impl<Alg: BlockCipher> BlockCipherMut for Alg {
type BlockSize = Alg::BlockSize;
type ParBlocks = Alg::ParBlocks;

/// Encrypt block in-place
fn encrypt_block(&mut self, block: &mut GenericArray<u8, Self::BlockSize>) {
<Self as BlockCipher>::encrypt_block(self, block);
}

/// Decrypt block in-place
fn decrypt_block(&mut self, block: &mut GenericArray<u8, Self::BlockSize>) {
<Self as BlockCipher>::decrypt_block(self, block);
}

fn encrypt_blocks(
&mut self,
blocks: &mut GenericArray<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
) {
<Self as BlockCipher>::encrypt_blocks(self, blocks);
}

fn decrypt_blocks(
&mut self,
blocks: &mut GenericArray<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
) {
<Self as BlockCipher>::decrypt_blocks(self, blocks);
}
}

0 comments on commit 17eac70

Please sign in to comment.