Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions cipher/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,137 @@ impl<Alg: BlockCipher> 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<u8>;

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

/// Encrypt a slice of blocks, leveraging parallelism when available.
#[inline]
fn encrypt_blocks(&self, blocks: &mut [GenericArray<u8, Self::BlockSize>]) {
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<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(&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`.
fn encrypt_par_blocks(
&self,
blocks: &mut GenericArray<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
);
}

impl<Alg: EncryptPar> Encrypt for Alg {
type BlockSize = Alg::BlockSize;

#[inline]
fn encrypt_block(&self, block: &mut GenericArray<u8, Self::BlockSize>) {
<Self as EncryptPar>::encrypt_block(self, block);
}

#[inline]
fn encrypt_blocks(&self, mut blocks: &mut [GenericArray<u8, Self::BlockSize>]) {
let pb = <Self as EncryptPar>::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<u8>;

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

/// Decrypt a slice of blocks, leveraging parallelism when available.
#[inline]
fn decrypt_blocks(&self, blocks: &mut [GenericArray<u8, Self::BlockSize>]) {
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<u8>;

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

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

/// 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<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
);
}

impl<Alg: DecryptPar> Decrypt for Alg {
type BlockSize = Alg::BlockSize;

#[inline]
fn decrypt_block(&self, block: &mut GenericArray<u8, Self::BlockSize>) {
<Self as DecryptPar>::decrypt_block(self, block);
}

#[inline]
fn decrypt_blocks(&self, mut blocks: &mut [GenericArray<u8, Self::BlockSize>]) {
let pb = <Self as DecryptPar>::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);
}
}
}