Skip to content
Closed
Show file tree
Hide file tree
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
168 changes: 97 additions & 71 deletions cipher/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
/// Key for an algorithm that implements [`NewBlockCipher`].
pub type Key<B> = GenericArray<u8, <B as NewBlockCipher>::KeySize>;

/// Block on which a [`BlockCipher`] operates.
pub type Block<B> = GenericArray<u8, <B as BlockCipher>::BlockSize>;

/// Blocks being acted over in parallel.
pub type ParBlocks<B> = GenericArray<Block<B>, <B as BlockCipher>::ParBlocks>;
// /// Block on which a [`BlockCipher`] operates.
// pub type Block<B> = GenericArray<u8, <B as BlockCipher>::BlockSize>;
//
// /// Blocks being acted over in parallel.
// pub type ParBlocks<B> = GenericArray<Block<B>, <B as BlockCipher>::ParBlocks>;

/// Instantiate a [`BlockCipher`] algorithm.
pub trait NewBlockCipher: Sized {
Expand All @@ -55,41 +55,105 @@ pub trait NewBlockCipher: Sized {

/// The trait which defines in-place encryption and decryption
/// over single block or several blocks in parallel.
pub trait BlockCipher {
pub trait BlockCipher<BlockSize, ParBlocks>
where
BlockSize: ArrayLength<u8>,
ParBlocks: ArrayLength<GenericArray<u8, BlockSize>>,
Self: Encrypt<BlockSize = BlockSize, ParBlocks = ParBlocks>
+ Decrypt<BlockSize = BlockSize, ParBlocks = ParBlocks>,
{
}

/// 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>;

/// 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>);
}

// impl<Alg: BlockCipher> BlockCipherMut for Alg {
// type BlockSize = Alg::BlockSize;
//
// #[inline]
// fn encrypt_block(&mut self, block: &mut GenericArray<u8, Self::BlockSize>) {
// <Self as BlockCipher>::encrypt_block(self, block);
// }
//
// #[inline]
// fn decrypt_block(&mut self, block: &mut GenericArray<u8, Self::BlockSize>) {
// <Self as BlockCipher>::decrypt_block(self, block);
// }
// }

// impl<Alg: BlockCipher> BlockCipher for &Alg {
// type BlockSize = Alg::BlockSize;
// type ParBlocks = Alg::ParBlocks;
//
// #[inline]
// fn encrypt_block(&self, block: &mut Block<Self>) {
// Alg::encrypt_block(self, block);
// }
//
// #[inline]
// fn decrypt_block(&self, block: &mut Block<Self>) {
// Alg::decrypt_block(self, block);
// }
//
// #[inline]
// fn encrypt_blocks(&self, blocks: &mut ParBlocks<Self>) {
// Alg::encrypt_blocks(self, blocks);
// }
//
// #[inline]
// fn decrypt_blocks(&self, blocks: &mut ParBlocks<Self>) {
// Alg::decrypt_blocks(self, blocks);
// }
// }

/// Encrypt-only functionality for block ciphers
pub trait Encrypt {
/// 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<Block<Self>>;
type ParBlocks: ArrayLength<GenericArray<u8, Self::BlockSize>>;

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

/// Decrypt block in-place
fn decrypt_block(&self, block: &mut Block<Self>);
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`.
#[inline]
fn encrypt_blocks(&self, blocks: &mut ParBlocks<Self>) {
fn encrypt_par_blocks(
&self,
blocks: &mut GenericArray<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
) {
for block in blocks.iter_mut() {
self.encrypt_block(block);
}
}

/// Encrypt a slice of blocks, leveraging parallelism when available.
#[inline]
fn encrypt_slice(&self, mut blocks: &mut [Block<Self>]) {
fn encrypt_blocks(&self, mut blocks: &mut [GenericArray<u8, Self::BlockSize>]) {
let pb = Self::ParBlocks::to_usize();

if pb > 1 {
let mut iter = blocks.chunks_exact_mut(pb);

for chunk in &mut iter {
self.encrypt_blocks(chunk.try_into().unwrap())
self.encrypt_par_blocks(chunk.try_into().unwrap())
}

blocks = iter.into_remainder();
Expand All @@ -99,28 +163,44 @@ pub trait BlockCipher {
self.encrypt_block(block);
}
}
}

/// Decrypt-only functionality for block ciphers
pub trait Decrypt {
/// 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`.
#[inline]
fn decrypt_blocks(&self, blocks: &mut ParBlocks<Self>) {
fn decrypt_par_blocks(
&self,
blocks: &mut GenericArray<GenericArray<u8, Self::BlockSize>, Self::ParBlocks>,
) {
for block in blocks.iter_mut() {
self.decrypt_block(block);
}
}

/// Decrypt a slice of blocks, leveraging parallelism when available.
#[inline]
fn decrypt_slice(&self, mut blocks: &mut [Block<Self>]) {
fn decrypt_blocks(&self, mut blocks: &mut [GenericArray<u8, Self::BlockSize>]) {
let pb = Self::ParBlocks::to_usize();

if pb > 1 {
let mut iter = blocks.chunks_exact_mut(pb);

for chunk in &mut iter {
self.decrypt_blocks(chunk.try_into().unwrap())
self.decrypt_par_blocks(chunk.try_into().unwrap())
}

blocks = iter.into_remainder();
Expand All @@ -131,57 +211,3 @@ 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>;

/// 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>);
}

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

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

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

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

#[inline]
fn encrypt_block(&self, block: &mut Block<Self>) {
Alg::encrypt_block(self, block);
}

#[inline]
fn decrypt_block(&self, block: &mut Block<Self>) {
Alg::decrypt_block(self, block);
}

#[inline]
fn encrypt_blocks(&self, blocks: &mut ParBlocks<Self>) {
Alg::encrypt_blocks(self, blocks);
}

#[inline]
fn decrypt_blocks(&self, blocks: &mut ParBlocks<Self>) {
Alg::decrypt_blocks(self, blocks);
}
}
118 changes: 61 additions & 57 deletions cipher/src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,11 @@ impl<C: SyncStreamCipher> SyncStreamCipher for &mut C {
/// Trait for initializing a stream cipher from a block cipher
pub trait FromBlockCipher {
/// Block cipher
type BlockCipher: BlockCipher;
type BlockCipher: BlockCipher<Self::BlockSize, Self::ParBlocks>;
/// Block size
type BlockSize: ArrayLength<u8>;
/// Parallel blocks
type ParBlocks: ArrayLength<GenericArray<u8, Self::BlockSize>>;
/// Nonce size in bytes
type NonceSize: ArrayLength<u8>;

Expand All @@ -167,62 +171,62 @@ pub trait FromBlockCipher {
}

/// Trait for initializing a stream cipher from a mutable block cipher
pub trait FromBlockCipherMut {
/// Block cipher
type BlockCipher: BlockCipherMut;
/// Nonce size in bytes
type NonceSize: ArrayLength<u8>;

/// Instantiate a stream cipher from a block cipher
fn from_block_cipher_mut(
cipher: Self::BlockCipher,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> Self;
}

impl<C> FromBlockCipherMut for C
where
C: FromBlockCipher,
{
type BlockCipher = <Self as FromBlockCipher>::BlockCipher;
type NonceSize = <Self as FromBlockCipher>::NonceSize;

fn from_block_cipher_mut(
cipher: Self::BlockCipher,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> C {
C::from_block_cipher(cipher, nonce)
}
}

impl<C> NewStreamCipher for C
where
C: FromBlockCipherMut,
C::BlockCipher: NewBlockCipher,
{
type KeySize = <<Self as FromBlockCipherMut>::BlockCipher as NewBlockCipher>::KeySize;
type NonceSize = <Self as FromBlockCipherMut>::NonceSize;

fn new(key: &Key<Self>, nonce: &Nonce<Self>) -> C {
C::from_block_cipher_mut(
<<Self as FromBlockCipherMut>::BlockCipher as NewBlockCipher>::new(key),
nonce,
)
}

fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidKeyNonceLength> {
if nonce.len() != Self::NonceSize::USIZE {
Err(InvalidKeyNonceLength)
} else {
C::BlockCipher::new_varkey(key)
.map_err(|_| InvalidKeyNonceLength)
.map(|cipher| {
let nonce = GenericArray::from_slice(nonce);
Self::from_block_cipher_mut(cipher, nonce)
})
}
}
}
// pub trait FromBlockCipherMut {
// /// Block cipher
// type BlockCipher: BlockCipherMut;
// /// Nonce size in bytes
// type NonceSize: ArrayLength<u8>;
//
// /// Instantiate a stream cipher from a block cipher
// fn from_block_cipher_mut(
// cipher: Self::BlockCipher,
// nonce: &GenericArray<u8, Self::NonceSize>,
// ) -> Self;
// }

// impl<C> FromBlockCipherMut for C
// where
// C: FromBlockCipher,
// {
// type BlockCipher = <Self as FromBlockCipher>::BlockCipher;
// type NonceSize = <Self as FromBlockCipher>::NonceSize;
//
// fn from_block_cipher_mut(
// cipher: Self::BlockCipher,
// nonce: &GenericArray<u8, Self::NonceSize>,
// ) -> C {
// C::from_block_cipher(cipher, nonce)
// }
// }

// impl<C> NewStreamCipher for C
// where
// C: FromBlockCipherMut,
// C::BlockCipher: NewBlockCipher,
// {
// type KeySize = <<Self as FromBlockCipherMut>::BlockCipher as NewBlockCipher>::KeySize;
// type NonceSize = <Self as FromBlockCipherMut>::NonceSize;
//
// fn new(key: &Key<Self>, nonce: &Nonce<Self>) -> C {
// C::from_block_cipher_mut(
// <<Self as FromBlockCipherMut>::BlockCipher as NewBlockCipher>::new(key),
// nonce,
// )
// }
//
// fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidKeyNonceLength> {
// if nonce.len() != Self::NonceSize::USIZE {
// Err(InvalidKeyNonceLength)
// } else {
// C::BlockCipher::new_varkey(key)
// .map_err(|_| InvalidKeyNonceLength)
// .map(|cipher| {
// let nonce = GenericArray::from_slice(nonce);
// Self::from_block_cipher_mut(cipher, nonce)
// })
// }
// }
// }

/// Trait implemented for numeric types which can be used with the
/// [`SyncStreamCipherSeek`] trait.
Expand Down