From b6f16776083f7f108cc84309a5de62d7a1481ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 4 Dec 2024 16:32:24 +0300 Subject: [PATCH 1/2] cipher: add traits for tweakable block ciphers --- cipher/src/lib.rs | 2 + cipher/src/tweak.rs | 145 +++++++++++++++++++++++++++++++++++++++ cipher/src/tweak/ctx.rs | 35 ++++++++++ cipher/src/tweak/zero.rs | 122 ++++++++++++++++++++++++++++++++ 4 files changed, 304 insertions(+) create mode 100644 cipher/src/tweak.rs create mode 100644 cipher/src/tweak/ctx.rs create mode 100644 cipher/src/tweak/zero.rs diff --git a/cipher/src/lib.rs b/cipher/src/lib.rs index 7e34bba0c..9fff63c52 100644 --- a/cipher/src/lib.rs +++ b/cipher/src/lib.rs @@ -36,9 +36,11 @@ pub mod block; #[cfg(feature = "dev")] mod dev; pub mod stream; +pub mod tweak; pub use block::*; pub use stream::*; +pub use tweak::*; pub use crypto_common::{ array::{self, Array}, diff --git a/cipher/src/tweak.rs b/cipher/src/tweak.rs new file mode 100644 index 000000000..bd97f6f29 --- /dev/null +++ b/cipher/src/tweak.rs @@ -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 = Array, ::ParBlocksSize>; +/// Tweak used by a [`TweakSizeUser`] implementor. +pub type Tweak = Array::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, + ); + + /// Encrypt single `inout` block. + #[inline] + fn encrypt_block_inout(&self, tweak: &Tweak, block: InOut<'_, '_, Block>) { + self.encrypt_with_backend(ctx::BlockCtx { tweak, block }); + } + + /// Encrypt single block in-place. + #[inline] + fn encrypt_block(&self, tweak: &Tweak, block: &mut Block) { + self.encrypt_block_inout(tweak, block.into()); + } + + /// Encrypt `in_block` and write result to `out_block`. + #[inline] + fn encrypt_block_b2b( + &self, + tweak: &Tweak, + in_block: &Block, + out_block: &mut Block, + ) { + 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, + ); + + /// Decrypt single `inout` block. + #[inline] + fn decrypt_block_inout(&self, tweak: &Tweak, block: InOut<'_, '_, Block>) { + self.decrypt_with_backend(ctx::BlockCtx { tweak, block }); + } + + /// Decrypt single block in-place. + #[inline] + fn decrypt_block(&self, tweak: &Tweak, block: &mut Block) { + self.decrypt_block_inout(tweak, block.into()); + } + + /// Decrypt `in_block` and write result to `out_block`. + #[inline] + fn decrypt_block_b2b( + &self, + tweak: &Tweak, + in_block: &Block, + out_block: &mut Block, + ) { + 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(self, backend: &B) + where + B: TweakBlockCipherEncBackend; +} + +/// 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(self, backend: &B) + where + B: TweakBlockCipherDecBackend; +} + +/// Trait implemented by block cipher mode encryption backends. +pub trait TweakBlockCipherEncBackend: ParBlocksSizeUser + TweakSizeUser { + /// Encrypt single inout block. + fn encrypt_block(&self, tweak: &Tweak, block: InOut<'_, '_, Block>); + + /// Encrypt inout blocks in parallel. + #[inline(always)] + fn encrypt_par_blocks( + &self, + tweak: &ParTweaks, + mut blocks: InOut<'_, '_, ParBlocks>, + ) { + 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, block: InOut<'_, '_, Block>); + + /// Decrypt inout blocks in parallel. + #[inline(always)] + fn decrypt_par_blocks( + &self, + tweak: &ParTweaks, + mut blocks: InOut<'_, '_, ParBlocks>, + ) { + for i in 0..Self::ParBlocksSize::USIZE { + self.decrypt_block(&tweak[i], blocks.get(i)); + } + } +} diff --git a/cipher/src/tweak/ctx.rs b/cipher/src/tweak/ctx.rs new file mode 100644 index 000000000..9b96498ed --- /dev/null +++ b/cipher/src/tweak/ctx.rs @@ -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, + pub block: InOut<'a, 'a, Block>, +} + +impl BlockSizeUser for BlockCtx<'_, TS, BS> { + type BlockSize = BS; +} + +impl TweakSizeUser for BlockCtx<'_, TS, BS> { + type TweakSize = TS; +} + +impl TweakBlockCipherEncClosure for BlockCtx<'_, TS, BS> { + #[inline(always)] + fn call>(self, backend: &B) { + backend.encrypt_block(self.tweak, self.block); + } +} + +impl TweakBlockCipherDecClosure for BlockCtx<'_, TS, BS> { + #[inline(always)] + fn call>(self, backend: &B) { + backend.decrypt_block(self.tweak, self.block); + } +} diff --git a/cipher/src/tweak/zero.rs b/cipher/src/tweak/zero.rs new file mode 100644 index 000000000..cd0e5171f --- /dev/null +++ b/cipher/src/tweak/zero.rs @@ -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(pub C); + +impl BlockSizeUser for ZeroTweak { + type BlockSize = C::BlockSize; +} + +impl BlockCipherEncrypt for ZeroTweak { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + self.0.encrypt_with_backend(ClosureWrapper { + f, + _pd: PhantomData, + }); + } +} + +impl BlockCipherDecrypt for ZeroTweak { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + 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 { + f: F, + _pd: PhantomData<(TS, BS)>, +} + +impl BlockSizeUser for ClosureWrapper { + type BlockSize = BS; +} + +impl TweakSizeUser for ClosureWrapper { + type TweakSize = TS; +} + +impl TweakBlockCipherEncClosure for ClosureWrapper +where + F: BlockCipherEncClosure, +{ + fn call>(self, backend: &B) { + self.f.call(&BackendWrapper { + backend, + _pd: PhantomData, + }) + } +} + +impl TweakBlockCipherDecClosure for ClosureWrapper +where + F: BlockCipherDecClosure, +{ + fn call>(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, +} + +impl BlockSizeUser for BackendWrapper<'_, BS, B> { + type BlockSize = BS; +} + +impl ParBlocksSizeUser for BackendWrapper<'_, BS, B> { + type ParBlocksSize = B::ParBlocksSize; +} + +impl> BlockCipherEncBackend + for BackendWrapper<'_, BS, B> +{ + #[inline] + fn encrypt_block(&self, block: inout::InOut<'_, '_, Block>) { + self.backend.encrypt_block(&Default::default(), block); + } + + #[inline] + fn encrypt_par_blocks(&self, blocks: inout::InOut<'_, '_, ParBlocks>) { + self.backend.encrypt_par_blocks(&Default::default(), blocks); + } +} + +impl> BlockCipherDecBackend + for BackendWrapper<'_, BS, B> +{ + #[inline] + fn decrypt_block(&self, block: inout::InOut<'_, '_, Block>) { + self.backend.decrypt_block(&Default::default(), block); + } + + #[inline] + fn decrypt_par_blocks(&self, blocks: inout::InOut<'_, '_, ParBlocks>) { + self.backend.decrypt_par_blocks(&Default::default(), blocks); + } +} From 4c4bf6abbede5e1cc28a619306369d42fdee1919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 9 Dec 2024 17:02:04 +0300 Subject: [PATCH 2/2] remove parallel block processing --- cipher/src/tweak.rs | 55 ++++++++++++++++++++++------------------ cipher/src/tweak/ctx.rs | 18 ++++++++----- cipher/src/tweak/zero.rs | 36 ++++++++++++-------------- 3 files changed, 59 insertions(+), 50 deletions(-) diff --git a/cipher/src/tweak.rs b/cipher/src/tweak.rs index bd97f6f29..ec3cb432e 100644 --- a/cipher/src/tweak.rs +++ b/cipher/src/tweak.rs @@ -3,8 +3,7 @@ //! [1]: https://people.eecs.berkeley.edu/~daw/papers/tweak-crypto02.pdf use crypto_common::{ array::{Array, ArraySize}, - typenum::Unsigned, - Block, BlockSizeUser, ParBlocks, ParBlocksSizeUser, + Block, BlockSizeUser, }; use inout::InOut; @@ -13,8 +12,6 @@ mod zero; pub use zero::ZeroTweak; -/// Array of tweaks used by a implementor of [`TweakSizeUser`] and [`ParBlocksSizeUser`]. -pub type ParTweaks = Array, ::ParBlocksSize>; /// Tweak used by a [`TweakSizeUser`] implementor. pub type Tweak = Array::TweakSize>; @@ -109,37 +106,47 @@ pub trait TweakBlockCipherDecClosure: BlockSizeUser + TweakSizeUser { } /// Trait implemented by block cipher mode encryption backends. -pub trait TweakBlockCipherEncBackend: ParBlocksSizeUser + TweakSizeUser { +pub trait TweakBlockCipherEncBackend: BlockSizeUser + TweakSizeUser { /// Encrypt single inout block. - fn encrypt_block(&self, tweak: &Tweak, block: InOut<'_, '_, Block>); + fn encrypt_block_inout(&self, tweak: &Tweak, block: InOut<'_, '_, Block>); - /// Encrypt inout blocks in parallel. - #[inline(always)] - fn encrypt_par_blocks( + /// Encrypt single block in-place. + #[inline] + fn encrypt_block(&self, tweak: &Tweak, block: &mut Block) { + self.encrypt_block_inout(tweak, block.into()); + } + + /// Encrypt `in_block` and write result to `out_block`. + #[inline] + fn encrypt_block_b2b( &self, - tweak: &ParTweaks, - mut blocks: InOut<'_, '_, ParBlocks>, + tweak: &Tweak, + in_block: &Block, + out_block: &mut Block, ) { - for i in 0..Self::ParBlocksSize::USIZE { - self.encrypt_block(&tweak[i], blocks.get(i)); - } + self.encrypt_block_inout(tweak, (in_block, out_block).into()); } } /// Trait implemented by block cipher mode decryption backends. -pub trait TweakBlockCipherDecBackend: ParBlocksSizeUser + TweakSizeUser { +pub trait TweakBlockCipherDecBackend: BlockSizeUser + TweakSizeUser { /// Decrypt single inout block. - fn decrypt_block(&self, tweak: &Tweak, block: InOut<'_, '_, Block>); + fn decrypt_block_inout(&self, tweak: &Tweak, block: InOut<'_, '_, Block>); - /// Decrypt inout blocks in parallel. - #[inline(always)] - fn decrypt_par_blocks( + /// Decrypt single block in-place. + #[inline] + fn decrypt_block(&self, tweak: &Tweak, block: &mut Block) { + self.decrypt_block_inout(tweak, block.into()); + } + + /// Decrypt `in_block` and write result to `out_block`. + #[inline] + fn decrypt_block_b2b( &self, - tweak: &ParTweaks, - mut blocks: InOut<'_, '_, ParBlocks>, + tweak: &Tweak, + in_block: &Block, + out_block: &mut Block, ) { - for i in 0..Self::ParBlocksSize::USIZE { - self.decrypt_block(&tweak[i], blocks.get(i)); - } + self.decrypt_block_inout(tweak, (in_block, out_block).into()); } } diff --git a/cipher/src/tweak/ctx.rs b/cipher/src/tweak/ctx.rs index 9b96498ed..65ca6a557 100644 --- a/cipher/src/tweak/ctx.rs +++ b/cipher/src/tweak/ctx.rs @@ -21,15 +21,21 @@ impl TweakSizeUser for BlockCtx<'_, TS, BS> { } impl TweakBlockCipherEncClosure for BlockCtx<'_, TS, BS> { - #[inline(always)] - fn call>(self, backend: &B) { - backend.encrypt_block(self.tweak, self.block); + #[inline] + fn call(self, backend: &B) + where + B: TweakBlockCipherEncBackend, + { + backend.encrypt_block_inout(self.tweak, self.block); } } impl TweakBlockCipherDecClosure for BlockCtx<'_, TS, BS> { - #[inline(always)] - fn call>(self, backend: &B) { - backend.decrypt_block(self.tweak, self.block); + #[inline] + fn call(self, backend: &B) + where + B: TweakBlockCipherDecBackend, + { + backend.decrypt_block_inout(self.tweak, self.block); } } diff --git a/cipher/src/tweak/zero.rs b/cipher/src/tweak/zero.rs index cd0e5171f..9bebf1a90 100644 --- a/cipher/src/tweak/zero.rs +++ b/cipher/src/tweak/zero.rs @@ -1,13 +1,13 @@ use core::marker::PhantomData; -use crypto_common::{array::ArraySize, Block, BlockSizes, ParBlocks, ParBlocksSizeUser}; +use crypto_common::{array::ArraySize, Block, BlockSizes, ParBlocksSizeUser}; use super::{ TweakBlockCipherDecBackend, TweakBlockCipherDecClosure, TweakBlockCipherDecrypt, TweakBlockCipherEncBackend, TweakBlockCipherEncrypt, TweakSizeUser, }; use crate::{ - tweak::TweakBlockCipherEncClosure, BlockCipherDecBackend, BlockCipherDecClosure, + consts::U1, tweak::TweakBlockCipherEncClosure, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, }; @@ -22,6 +22,7 @@ impl BlockSizeUser for ZeroTweak { } impl BlockCipherEncrypt for ZeroTweak { + #[inline] fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { self.0.encrypt_with_backend(ClosureWrapper { f, @@ -31,6 +32,7 @@ impl BlockCipherEncrypt for ZeroTweak { } impl BlockCipherDecrypt for ZeroTweak { + #[inline] fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { self.0.decrypt_with_backend(ClosureWrapper { f, @@ -58,6 +60,7 @@ impl TweakBlockCipherEncClosure for ClosureWra where F: BlockCipherEncClosure, { + #[inline] fn call>(self, backend: &B) { self.f.call(&BackendWrapper { backend, @@ -70,6 +73,7 @@ impl TweakBlockCipherDecClosure for ClosureWra where F: BlockCipherDecClosure, { + #[inline] fn call>(self, backend: &B) { self.f.call(&BackendWrapper { backend, @@ -89,34 +93,26 @@ impl BlockSizeUser for BackendWrapper<'_, BS, B> { type BlockSize = BS; } -impl ParBlocksSizeUser for BackendWrapper<'_, BS, B> { - type ParBlocksSize = B::ParBlocksSize; +impl ParBlocksSizeUser for BackendWrapper<'_, BS, B> { + type ParBlocksSize = U1; } -impl> BlockCipherEncBackend - for BackendWrapper<'_, BS, B> +impl BlockCipherEncBackend for BackendWrapper<'_, BS, B> +where + B: TweakBlockCipherEncBackend, { #[inline] fn encrypt_block(&self, block: inout::InOut<'_, '_, Block>) { - self.backend.encrypt_block(&Default::default(), block); - } - - #[inline] - fn encrypt_par_blocks(&self, blocks: inout::InOut<'_, '_, ParBlocks>) { - self.backend.encrypt_par_blocks(&Default::default(), blocks); + self.backend.encrypt_block_inout(&Default::default(), block); } } -impl> BlockCipherDecBackend - for BackendWrapper<'_, BS, B> +impl BlockCipherDecBackend for BackendWrapper<'_, BS, B> +where + B: TweakBlockCipherDecBackend, { #[inline] fn decrypt_block(&self, block: inout::InOut<'_, '_, Block>) { - self.backend.decrypt_block(&Default::default(), block); - } - - #[inline] - fn decrypt_par_blocks(&self, blocks: inout::InOut<'_, '_, ParBlocks>) { - self.backend.decrypt_par_blocks(&Default::default(), blocks); + self.backend.decrypt_block_inout(&Default::default(), block); } }