-
Notifications
You must be signed in to change notification settings - Fork 198
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cipher: add traits for tweakable block ciphers
- Loading branch information
Showing
4 changed files
with
304 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
//! Traits used to define functionality of [tweakable block ciphers][1]. | ||
//! | ||
//! [1]: https://people.eecs.berkeley.edu/~daw/papers/tweak-crypto02.pdf | ||
use crypto_common::{ | ||
array::{Array, ArraySize}, | ||
typenum::Unsigned, | ||
Block, BlockSizeUser, ParBlocks, ParBlocksSizeUser, | ||
}; | ||
use inout::InOut; | ||
|
||
mod ctx; | ||
mod zero; | ||
|
||
pub use zero::ZeroTweak; | ||
|
||
/// Array of tweaks used by a implementor of [`TweakSizeUser`] and [`ParBlocksSizeUser`]. | ||
pub type ParTweaks<C> = Array<Tweak<C>, <C as ParBlocksSizeUser>::ParBlocksSize>; | ||
/// Tweak used by a [`TweakSizeUser`] implementor. | ||
pub type Tweak<C> = Array<u8, <C as TweakSizeUser>::TweakSize>; | ||
|
||
/// Trait which contains tweak size used by the tweak cipher traits. | ||
pub trait TweakSizeUser { | ||
/// Size of the tweak in bytes. | ||
type TweakSize: ArraySize; | ||
} | ||
|
||
/// Encrypt-only functionality for tweakable block ciphers. | ||
pub trait TweakBlockCipherEncrypt: BlockSizeUser + TweakSizeUser + Sized { | ||
/// Encrypt data using backend provided to the rank-2 closure. | ||
fn encrypt_with_backend( | ||
&self, | ||
f: impl TweakBlockCipherEncClosure<BlockSize = Self::BlockSize, TweakSize = Self::TweakSize>, | ||
); | ||
|
||
/// Encrypt single `inout` block. | ||
#[inline] | ||
fn encrypt_block_inout(&self, tweak: &Tweak<Self>, block: InOut<'_, '_, Block<Self>>) { | ||
self.encrypt_with_backend(ctx::BlockCtx { tweak, block }); | ||
} | ||
|
||
/// Encrypt single block in-place. | ||
#[inline] | ||
fn encrypt_block(&self, tweak: &Tweak<Self>, block: &mut Block<Self>) { | ||
self.encrypt_block_inout(tweak, block.into()); | ||
} | ||
|
||
/// Encrypt `in_block` and write result to `out_block`. | ||
#[inline] | ||
fn encrypt_block_b2b( | ||
&self, | ||
tweak: &Tweak<Self>, | ||
in_block: &Block<Self>, | ||
out_block: &mut Block<Self>, | ||
) { | ||
self.encrypt_block_inout(tweak, (in_block, out_block).into()); | ||
} | ||
} | ||
|
||
/// Decrypt-only functionality for tweakable block ciphers. | ||
pub trait TweakBlockCipherDecrypt: BlockSizeUser + TweakSizeUser + Sized { | ||
/// Decrypt data using backend provided to the rank-2 closure. | ||
fn decrypt_with_backend( | ||
&self, | ||
f: impl TweakBlockCipherDecClosure<BlockSize = Self::BlockSize, TweakSize = Self::TweakSize>, | ||
); | ||
|
||
/// Decrypt single `inout` block. | ||
#[inline] | ||
fn decrypt_block_inout(&self, tweak: &Tweak<Self>, block: InOut<'_, '_, Block<Self>>) { | ||
self.decrypt_with_backend(ctx::BlockCtx { tweak, block }); | ||
} | ||
|
||
/// Decrypt single block in-place. | ||
#[inline] | ||
fn decrypt_block(&self, tweak: &Tweak<Self>, block: &mut Block<Self>) { | ||
self.decrypt_block_inout(tweak, block.into()); | ||
} | ||
|
||
/// Decrypt `in_block` and write result to `out_block`. | ||
#[inline] | ||
fn decrypt_block_b2b( | ||
&self, | ||
tweak: &Tweak<Self>, | ||
in_block: &Block<Self>, | ||
out_block: &mut Block<Self>, | ||
) { | ||
self.decrypt_block_inout(tweak, (in_block, out_block).into()); | ||
} | ||
} | ||
|
||
/// Trait for [`TweakBlockCipherEncBackend`] users. | ||
/// | ||
/// This trait is used to define rank-2 closures. | ||
pub trait TweakBlockCipherEncClosure: BlockSizeUser + TweakSizeUser { | ||
/// Execute closure with the provided block cipher backend. | ||
fn call<B>(self, backend: &B) | ||
where | ||
B: TweakBlockCipherEncBackend<BlockSize = Self::BlockSize, TweakSize = Self::TweakSize>; | ||
} | ||
|
||
/// Trait for [`TweakBlockCipherDecBackend`] users. | ||
/// | ||
/// This trait is used to define rank-2 closures. | ||
pub trait TweakBlockCipherDecClosure: BlockSizeUser + TweakSizeUser { | ||
/// Execute closure with the provided block cipher backend. | ||
fn call<B>(self, backend: &B) | ||
where | ||
B: TweakBlockCipherDecBackend<BlockSize = Self::BlockSize, TweakSize = Self::TweakSize>; | ||
} | ||
|
||
/// Trait implemented by block cipher mode encryption backends. | ||
pub trait TweakBlockCipherEncBackend: ParBlocksSizeUser + TweakSizeUser { | ||
/// Encrypt single inout block. | ||
fn encrypt_block(&self, tweak: &Tweak<Self>, block: InOut<'_, '_, Block<Self>>); | ||
|
||
/// Encrypt inout blocks in parallel. | ||
#[inline(always)] | ||
fn encrypt_par_blocks( | ||
&self, | ||
tweak: &ParTweaks<Self>, | ||
mut blocks: InOut<'_, '_, ParBlocks<Self>>, | ||
) { | ||
for i in 0..Self::ParBlocksSize::USIZE { | ||
self.encrypt_block(&tweak[i], blocks.get(i)); | ||
} | ||
} | ||
} | ||
|
||
/// Trait implemented by block cipher mode decryption backends. | ||
pub trait TweakBlockCipherDecBackend: ParBlocksSizeUser + TweakSizeUser { | ||
/// Decrypt single inout block. | ||
fn decrypt_block(&self, tweak: &Tweak<Self>, block: InOut<'_, '_, Block<Self>>); | ||
|
||
/// Decrypt inout blocks in parallel. | ||
#[inline(always)] | ||
fn decrypt_par_blocks( | ||
&self, | ||
tweak: &ParTweaks<Self>, | ||
mut blocks: InOut<'_, '_, ParBlocks<Self>>, | ||
) { | ||
for i in 0..Self::ParBlocksSize::USIZE { | ||
self.decrypt_block(&tweak[i], blocks.get(i)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use crypto_common::{array::ArraySize, Block, BlockSizeUser, BlockSizes}; | ||
use inout::InOut; | ||
|
||
use super::{ | ||
Tweak, TweakBlockCipherDecBackend, TweakBlockCipherDecClosure, TweakBlockCipherEncBackend, | ||
TweakBlockCipherEncClosure, TweakSizeUser, | ||
}; | ||
|
||
/// Closure used in methods which operate over separate blocks. | ||
pub(super) struct BlockCtx<'a, TS: ArraySize, BS: BlockSizes> { | ||
pub tweak: &'a Tweak<Self>, | ||
pub block: InOut<'a, 'a, Block<Self>>, | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes> BlockSizeUser for BlockCtx<'_, TS, BS> { | ||
type BlockSize = BS; | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes> TweakSizeUser for BlockCtx<'_, TS, BS> { | ||
type TweakSize = TS; | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes> TweakBlockCipherEncClosure for BlockCtx<'_, TS, BS> { | ||
#[inline(always)] | ||
fn call<B: TweakBlockCipherEncBackend<BlockSize = BS, TweakSize = TS>>(self, backend: &B) { | ||
backend.encrypt_block(self.tweak, self.block); | ||
} | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes> TweakBlockCipherDecClosure for BlockCtx<'_, TS, BS> { | ||
#[inline(always)] | ||
fn call<B: TweakBlockCipherDecBackend<BlockSize = BS, TweakSize = TS>>(self, backend: &B) { | ||
backend.decrypt_block(self.tweak, self.block); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
use core::marker::PhantomData; | ||
|
||
use crypto_common::{array::ArraySize, Block, BlockSizes, ParBlocks, ParBlocksSizeUser}; | ||
|
||
use super::{ | ||
TweakBlockCipherDecBackend, TweakBlockCipherDecClosure, TweakBlockCipherDecrypt, | ||
TweakBlockCipherEncBackend, TweakBlockCipherEncrypt, TweakSizeUser, | ||
}; | ||
use crate::{ | ||
tweak::TweakBlockCipherEncClosure, BlockCipherDecBackend, BlockCipherDecClosure, | ||
BlockCipherDecrypt, BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, | ||
BlockSizeUser, | ||
}; | ||
|
||
/// Wrapper around tweakable block cipher which implements | ||
/// the [common block cipher traits][crate::block] using zero tweak. | ||
#[derive(Debug, Clone)] | ||
pub struct ZeroTweak<C: TweakSizeUser + BlockSizeUser>(pub C); | ||
|
||
impl<C: TweakSizeUser + BlockSizeUser> BlockSizeUser for ZeroTweak<C> { | ||
type BlockSize = C::BlockSize; | ||
} | ||
|
||
impl<C: TweakBlockCipherEncrypt> BlockCipherEncrypt for ZeroTweak<C> { | ||
fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = Self::BlockSize>) { | ||
self.0.encrypt_with_backend(ClosureWrapper { | ||
f, | ||
_pd: PhantomData, | ||
}); | ||
} | ||
} | ||
|
||
impl<C: TweakBlockCipherDecrypt> BlockCipherDecrypt for ZeroTweak<C> { | ||
fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = Self::BlockSize>) { | ||
self.0.decrypt_with_backend(ClosureWrapper { | ||
f, | ||
_pd: PhantomData, | ||
}); | ||
} | ||
} | ||
|
||
/// Wrapper around non-tweakble block cipher closures which implements the tweakable | ||
/// block cipher closure traits using zero tweak. | ||
struct ClosureWrapper<TS: ArraySize, BS: BlockSizes, F> { | ||
f: F, | ||
_pd: PhantomData<(TS, BS)>, | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes, F> BlockSizeUser for ClosureWrapper<TS, BS, F> { | ||
type BlockSize = BS; | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes, F> TweakSizeUser for ClosureWrapper<TS, BS, F> { | ||
type TweakSize = TS; | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes, F> TweakBlockCipherEncClosure for ClosureWrapper<TS, BS, F> | ||
where | ||
F: BlockCipherEncClosure<BlockSize = BS>, | ||
{ | ||
fn call<B: TweakBlockCipherEncBackend<BlockSize = BS, TweakSize = TS>>(self, backend: &B) { | ||
self.f.call(&BackendWrapper { | ||
backend, | ||
_pd: PhantomData, | ||
}) | ||
} | ||
} | ||
|
||
impl<TS: ArraySize, BS: BlockSizes, F> TweakBlockCipherDecClosure for ClosureWrapper<TS, BS, F> | ||
where | ||
F: BlockCipherDecClosure<BlockSize = BS>, | ||
{ | ||
fn call<B: TweakBlockCipherDecBackend<BlockSize = BS, TweakSize = TS>>(self, backend: &B) { | ||
self.f.call(&BackendWrapper { | ||
backend, | ||
_pd: PhantomData, | ||
}) | ||
} | ||
} | ||
|
||
/// Wrapper around tweakable block cipher backend which implements non-tweakable | ||
/// block cipher backend traits using zero tweak. | ||
struct BackendWrapper<'a, BS: BlockSizes, B> { | ||
backend: &'a B, | ||
_pd: PhantomData<BS>, | ||
} | ||
|
||
impl<BS: BlockSizes, B> BlockSizeUser for BackendWrapper<'_, BS, B> { | ||
type BlockSize = BS; | ||
} | ||
|
||
impl<BS: BlockSizes, B: ParBlocksSizeUser> ParBlocksSizeUser for BackendWrapper<'_, BS, B> { | ||
type ParBlocksSize = B::ParBlocksSize; | ||
} | ||
|
||
impl<BS: BlockSizes, B: TweakBlockCipherEncBackend<BlockSize = BS>> BlockCipherEncBackend | ||
for BackendWrapper<'_, BS, B> | ||
{ | ||
#[inline] | ||
fn encrypt_block(&self, block: inout::InOut<'_, '_, Block<Self>>) { | ||
self.backend.encrypt_block(&Default::default(), block); | ||
} | ||
|
||
#[inline] | ||
fn encrypt_par_blocks(&self, blocks: inout::InOut<'_, '_, ParBlocks<Self>>) { | ||
self.backend.encrypt_par_blocks(&Default::default(), blocks); | ||
} | ||
} | ||
|
||
impl<BS: BlockSizes, B: TweakBlockCipherDecBackend<BlockSize = BS>> BlockCipherDecBackend | ||
for BackendWrapper<'_, BS, B> | ||
{ | ||
#[inline] | ||
fn decrypt_block(&self, block: inout::InOut<'_, '_, Block<Self>>) { | ||
self.backend.decrypt_block(&Default::default(), block); | ||
} | ||
|
||
#[inline] | ||
fn decrypt_par_blocks(&self, blocks: inout::InOut<'_, '_, ParBlocks<Self>>) { | ||
self.backend.decrypt_par_blocks(&Default::default(), blocks); | ||
} | ||
} |