diff --git a/aes/src/block/block128.rs b/aes/src/block/block128.rs index 3a43fd2..c7a17bb 100644 --- a/aes/src/block/block128.rs +++ b/aes/src/block/block128.rs @@ -2,7 +2,7 @@ use crate::{ block::{Block32, secret_block}, sbox::SboxLookup, }; -use cipher_core::{parse_block_int, BlockError, InputBlock}; +use cipher_core::{BlockError, InputBlock, parse_block_int}; use std::{ ops::BitXor, slice::{from_raw_parts, from_raw_parts_mut}, diff --git a/aes/src/block/mod.rs b/aes/src/block/mod.rs index ad47237..6e6f358 100644 --- a/aes/src/block/mod.rs +++ b/aes/src/block/mod.rs @@ -1,6 +1,5 @@ mod block128; mod block32; -mod secret_block; -use crate::secret_block; +use cipher_core::secret_block; pub use {block32::Block32, block128::Block128}; diff --git a/aes/src/block/secret_block.rs b/aes/src/block/secret_block.rs deleted file mode 100644 index eb3432f..0000000 --- a/aes/src/block/secret_block.rs +++ /dev/null @@ -1,190 +0,0 @@ -/// Macro to generate a masked, zeroizable integer wrapper type. -/// -/// Usage: -/// ``` -/// use des::secret_block; -/// secret_block! { -/// /// docs... -/// pub struct Block48(u64, 48, 0x0000_FFFF_FFFF_FFFFu64); -/// } -/// ``` -#[macro_export] -macro_rules! secret_block { - ( - $(#[$meta:meta])* - $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); -) => { - $(#[$meta])* - #[derive(Debug, Clone, Copy, PartialEq, Eq)] - $vis struct $name($int); - - impl $name { - /// Mask to restrict the underlying integer to valid bits. - pub const MASK: $int = $mask; - - /// Calculate the number of hex digits needed for the bit width - const fn hex_width() -> usize { - ($bits as usize).div_ceil(4) - } - - /// Calculate the number of octal digits needed for the bit width - const fn octal_width() -> usize { - ($bits as usize).div_ceil(3) - } - - #[inline] - #[must_use] - pub const fn new(value: $int) -> Self { - Self(value & Self::MASK) - } - - secret_block!(@conversions_as $int); - secret_block!(@conversions_from $int $int); - } - - impl From<$int> for $name { - fn from(v: $int) -> Self { - Self(v & Self::MASK) - } - } - - impl From<$name> for $int { - fn from(value: $name) -> $int { - value.0 - } - } - - impl std::fmt::UpperHex for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$X}", self.0, width = Self::hex_width()) - } - } - - impl std::fmt::LowerHex for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$x}", self.0, width = Self::hex_width()) - } - } - - impl std::fmt::Octal for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$o}", self.0, width = Self::octal_width()) - } - } - - impl std::fmt::Binary for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$b}", self.0, width = $bits) - } - } - - }; - // Helper: generate conversions_as based on type - (@conversions_as u8) => { - /// Return value as u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u8(&self) -> u8 { - self.0 as u8 - } - - secret_block!(@conversions_as u16); - }; - (@conversions_as u16) => { - /// Return value as u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u16(&self) -> u16 { - self.0 as u16 - } - - secret_block!(@conversions_as u32); - }; - (@conversions_as u32) => { - /// Return value as u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u32(&self) -> u32 { - self.0 as u32 - } - - secret_block!(@conversions_as u64); - }; - (@conversions_as u64) => { - /// Return value as u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u64(&self) -> u64 { - self.0 as u64 - } - - secret_block!(@conversions_as u128); - }; - (@conversions_as u128) => { - /// Return value as u129 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u128(&self) -> u128 { - self.0 as u128 - } - }; - // Helper: generate conversions_from based on type - (@conversions_from u8 $int:tt) => { - /// Create value from u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u8(key: u8) -> Self { - Self(key as $int & Self::MASK) - } - }; - (@conversions_from u16 $int:tt) => { - /// Create value from u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u16(key: u16) -> Self { - Self(key as $int & Self::MASK) - } - - secret_block!(@conversions_from u8 $int); - }; - (@conversions_from u32 $int:tt) => { - /// Create value from u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u32(key: u32) -> Self { - Self(key as $int & Self::MASK) - } - - secret_block!(@conversions_from u16 $int); - }; - (@conversions_from u64 $int:tt) => { - /// Create value from u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u64(key: u64) -> Self { - Self(key as $int & Self::MASK) - } - - secret_block!(@conversions_from u32 $int); - }; - (@conversions_from u128 $int:tt) => { - /// Create value from u128 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u128(key: u128) -> Self { - Self(key & Self::MASK) - } - - secret_block!(@conversions_from u64 $int); - } -} diff --git a/aes/src/key/expanded.rs b/aes/src/key/expanded.rs deleted file mode 100644 index bc047b7..0000000 --- a/aes/src/key/expanded.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::secret_key; - -secret_key! { - pub struct ExpandedKey(u32, 32, 0xFFFF_FFFF); -} diff --git a/aes/src/key/mod.rs b/aes/src/key/mod.rs index 9bbdd55..a4ac36c 100644 --- a/aes/src/key/mod.rs +++ b/aes/src/key/mod.rs @@ -1,7 +1,6 @@ mod aes_key; -mod secret_key; mod subkey; mod subkeys; -use crate::secret_key; +use cipher_core::secret_key; pub use {aes_key::Key, subkey::Subkey, subkeys::Subkeys}; diff --git a/aes/src/key/secret_key.rs b/aes/src/key/secret_key.rs deleted file mode 100644 index 1b6346f..0000000 --- a/aes/src/key/secret_key.rs +++ /dev/null @@ -1,149 +0,0 @@ -/// Macro to generate a masked, zeroizable integer wrapper type. -/// -/// Usage: -/// ``` -/// use des::secret_key; -/// secret_key! { -/// /// docs... -/// pub struct Subkey(u64, 48, 0x0000_FFFF_FFFF_FFFFu64); -/// } -/// ``` -#[macro_export] -macro_rules! secret_key { - ( - $(#[$meta:meta])* - $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); -) => { - $(#[$meta])* - #[derive(Default, Clone, Copy)] - $vis struct $name($int); - - impl $name { - /// Mask to restrict the underlying integer to valid bits. - pub const MASK: $int = $mask; - - secret_key!(@conversions_as $int); - secret_key!(@conversions_from $int $int); - } - - impl ::std::fmt::Debug for $name { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - f.write_str(concat!(stringify!($name), "[REDACTED]")) - } - } - - impl From<$int> for $name { - fn from(v: $int) -> Self { - Self(v & Self::MASK) - } - } - }; - // Helper: generate conversions_as based on type - (@conversions_as u8) => { - /// Return value as u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u8(&self) -> u8 { - self.0 as u8 - } - - secret_key!(@conversions_as u16); - }; - (@conversions_as u16) => { - /// Return value as u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u16(&self) -> u16 { - self.0 as u16 - } - - secret_key!(@conversions_as u32); - }; - (@conversions_as u32) => { - /// Return value as u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u32(&self) -> u32 { - self.0 as u32 - } - - secret_key!(@conversions_as u64); - }; - (@conversions_as u64) => { - /// Return value as u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u64(&self) -> u64 { - self.0 as u64 - } - - secret_key!(@conversions_as u128); - }; - (@conversions_as u128) => { - /// Return value as u128 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u128(&self) -> u128 { - self.0 as u128 - } - }; - // Helper: generate conversions_from based on type - (@conversions_from u8 $int:tt) => { - /// Create value from u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u8(key: u8) -> Self { - Self(key as $int & Self::MASK) - } - }; - (@conversions_from u16 $int:tt) => { - /// Create value from u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u16(key: u16) -> Self { - Self(key as $int & Self::MASK) - } - - secret_key!(@conversions_from u8 $int); - }; - (@conversions_from u32 $int:tt) => { - /// Create value from u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u32(key: u32) -> Self { - Self(key as $int & Self::MASK) - } - - secret_key!(@conversions_from u16 $int); - }; - (@conversions_from u64 $int:tt) => { - /// Create value from u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u64(key: u64) -> Self { - Self(key as $int & Self::MASK) - } - - secret_key!(@conversions_from u32 $int); - }; - (@conversions_from u128 $int:tt) => { - /// Create value from u128 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u128(key: u128) -> Self { - Self(key & Self::MASK) - } - - secret_key!(@conversions_from u64 $int); - } -} diff --git a/cipher-core/Cargo.toml b/cipher-core/Cargo.toml index 09ffddb..485f605 100644 --- a/cipher-core/Cargo.toml +++ b/cipher-core/Cargo.toml @@ -6,6 +6,7 @@ edition.workspace = true [dependencies] thiserror.workspace = true +zeroize.workspace = true [lints] workspace = true diff --git a/cipher-core/src/lib.rs b/cipher-core/src/lib.rs index d04f1dc..960d9e8 100644 --- a/cipher-core/src/lib.rs +++ b/cipher-core/src/lib.rs @@ -1,11 +1,12 @@ mod error; +mod macros; mod parsing; mod traits; mod types; pub use { error::{BlockError, CipherError, CipherResult}, - parsing::{parse_block_int, BlockInt}, + parsing::{BlockInt, parse_block_int}, traits::{BlockCipher, BlockParser, InputBlock}, types::{CipherAction, Output}, }; diff --git a/cipher-core/src/macros.rs b/cipher-core/src/macros.rs new file mode 100644 index 0000000..5cc91b4 --- /dev/null +++ b/cipher-core/src/macros.rs @@ -0,0 +1,265 @@ +/// Macro to generate a masked integer wrapper type for cipher blocks. +/// +/// Generates a type with formatting traits, conversions, and security features. +/// +/// # Example +/// ```ignore +/// secret_block! { +/// pub struct Block64(u64, 64, 0xFFFF_FFFF_FFFF_FFFF); +/// } +/// ``` +#[macro_export] +macro_rules! secret_block { + ( + $(#[$meta:meta])* + $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); + ) => { + $(#[$meta])* + #[derive(Debug, Clone, Copy, PartialEq, Eq, ::zeroize::Zeroize)] + $vis struct $name($int); + + impl $name { + /// Mask to restrict the underlying integer to valid bits. + pub const MASK: $int = $mask; + + const fn hex_width() -> usize { + ($bits as usize).div_ceil(4) + } + + const fn octal_width() -> usize { + ($bits as usize).div_ceil(3) + } + + #[inline] + #[must_use] + pub const fn new(value: $int) -> Self { + Self(value & Self::MASK) + } + + $crate::secret_block!(@conversions_as $int); + $crate::secret_block!(@conversions_from $int $int); + } + + impl From<$int> for $name { + fn from(v: $int) -> Self { + Self(v & Self::MASK) + } + } + + impl From<$name> for $int { + fn from(value: $name) -> $int { + value.0 + } + } + + impl ::std::fmt::UpperHex for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "{:0width$X}", self.0, width = Self::hex_width()) + } + } + + impl ::std::fmt::LowerHex for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "{:0width$x}", self.0, width = Self::hex_width()) + } + } + + impl ::std::fmt::Octal for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "{:0width$o}", self.0, width = Self::octal_width()) + } + } + + impl ::std::fmt::Binary for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "{:0width$b}", self.0, width = $bits) + } + } + }; + + // Conversion chain: as_u8 -> as_u16 -> as_u32 -> as_u64 -> as_u128 + (@conversions_as u8) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u8(&self) -> u8 { self.0 as u8 } + $crate::secret_block!(@conversions_as u16); + }; + (@conversions_as u16) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u16(&self) -> u16 { self.0 as u16 } + $crate::secret_block!(@conversions_as u32); + }; + (@conversions_as u32) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u32(&self) -> u32 { self.0 as u32 } + $crate::secret_block!(@conversions_as u64); + }; + (@conversions_as u64) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u64(&self) -> u64 { self.0 as u64 } + $crate::secret_block!(@conversions_as u128); + }; + (@conversions_as u128) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u128(&self) -> u128 { self.0 as u128 } + }; + + // Conversion chain: from_u128 -> from_u64 -> from_u32 -> from_u16 -> from_u8 + (@conversions_from u8 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u8(v: u8) -> Self { Self(v as $int & Self::MASK) } + }; + (@conversions_from u16 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u16(v: u16) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_block!(@conversions_from u8 $int); + }; + (@conversions_from u32 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u32(v: u32) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_block!(@conversions_from u16 $int); + }; + (@conversions_from u64 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u64(v: u64) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_block!(@conversions_from u32 $int); + }; + (@conversions_from u128 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u128(v: u128) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_block!(@conversions_from u64 $int); + }; +} + +/// Macro to generate a masked integer wrapper type for cipher keys. +/// +/// Keys have redacted Debug output and are zeroized on drop for security. +/// +/// # Example +/// ```ignore +/// secret_key! { +/// pub struct Key(u64, 64, 0xFFFF_FFFF_FFFF_FFFF); +/// } +/// ``` +#[macro_export] +macro_rules! secret_key { + ( + $(#[$meta:meta])* + $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); + ) => { + $(#[$meta])* + #[derive(Default, Clone, Copy, ::zeroize::Zeroize)] + $vis struct $name($int); + + impl $name { + /// Mask to restrict the underlying integer to valid bits. + pub const MASK: $int = $mask; + + $crate::secret_key!(@conversions_as $int); + $crate::secret_key!(@conversions_from $int $int); + } + + impl ::std::fmt::Debug for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + f.write_str(concat!(stringify!($name), "[REDACTED]")) + } + } + + impl From<$int> for $name { + fn from(v: $int) -> Self { + Self(v & Self::MASK) + } + } + }; + + // Conversion chain: as_u8 -> as_u16 -> as_u32 -> as_u64 -> as_u128 + (@conversions_as u8) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u8(&self) -> u8 { self.0 as u8 } + $crate::secret_key!(@conversions_as u16); + }; + (@conversions_as u16) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u16(&self) -> u16 { self.0 as u16 } + $crate::secret_key!(@conversions_as u32); + }; + (@conversions_as u32) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u32(&self) -> u32 { self.0 as u32 } + $crate::secret_key!(@conversions_as u64); + }; + (@conversions_as u64) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u64(&self) -> u64 { self.0 as u64 } + $crate::secret_key!(@conversions_as u128); + }; + (@conversions_as u128) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u128(&self) -> u128 { self.0 as u128 } + }; + + // Conversion chain: from_u128 -> from_u64 -> from_u32 -> from_u16 -> from_u8 + (@conversions_from u8 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u8(v: u8) -> Self { Self(v as $int & Self::MASK) } + }; + (@conversions_from u16 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u16(v: u16) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_key!(@conversions_from u8 $int); + }; + (@conversions_from u32 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u32(v: u32) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_key!(@conversions_from u16 $int); + }; + (@conversions_from u64 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u64(v: u64) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_key!(@conversions_from u32 $int); + }; + (@conversions_from u128 $int:tt) => { + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u128(v: u128) -> Self { Self(v as $int & Self::MASK) } + $crate::secret_key!(@conversions_from u64 $int); + }; +} diff --git a/des/src/block/block32.rs b/des/src/block/block32.rs index 8e3501f..5a2e26d 100644 --- a/des/src/block/block32.rs +++ b/des/src/block/block32.rs @@ -1,6 +1,6 @@ use std::ops::BitXor; -use crate::secret_block; +use super::secret_block; secret_block! { pub struct Block32(u32, 32, 0xFFFF_FFFF); diff --git a/des/src/block/block48.rs b/des/src/block/block48.rs index 576232b..dbac787 100644 --- a/des/src/block/block48.rs +++ b/des/src/block/block48.rs @@ -1,4 +1,5 @@ -use crate::{block::Block6, key::Subkey, secret_block}; +use super::{Block6, secret_block}; +use crate::key::Subkey; use std::{array, ops::BitXor}; secret_block! { diff --git a/des/src/block/block6.rs b/des/src/block/block6.rs index 2c5fb0c..2d040bf 100644 --- a/des/src/block/block6.rs +++ b/des/src/block/block6.rs @@ -1,4 +1,4 @@ -use crate::secret_block; +use super::secret_block; secret_block! { pub struct Block6(u8, 6, 0x3F); diff --git a/des/src/block/block64.rs b/des/src/block/block64.rs index 5bfedf8..06fe572 100644 --- a/des/src/block/block64.rs +++ b/des/src/block/block64.rs @@ -1,5 +1,5 @@ use crate::block::{lr::LR, secret_block}; -use cipher_core::{parse_block_int, BlockError, InputBlock}; +use cipher_core::{BlockError, InputBlock, parse_block_int}; use std::{ slice::{from_raw_parts, from_raw_parts_mut}, str::FromStr, diff --git a/des/src/block/mod.rs b/des/src/block/mod.rs index d4672b0..f674661 100644 --- a/des/src/block/mod.rs +++ b/des/src/block/mod.rs @@ -3,7 +3,6 @@ mod block48; mod block6; mod block64; mod lr; -mod secret_block; -use crate::secret_block; +use cipher_core::secret_block; pub use {block6::Block6, block32::Block32, block48::Block48, block64::Block64, lr::LR}; diff --git a/des/src/block/secret_block.rs b/des/src/block/secret_block.rs deleted file mode 100644 index 5032c8b..0000000 --- a/des/src/block/secret_block.rs +++ /dev/null @@ -1,168 +0,0 @@ -/// Macro to generate a masked, zeroizable integer wrapper type. -/// -/// Usage: -/// ``` -/// use des::secret_block; -/// secret_block! { -/// /// docs... -/// pub struct Block48(u64, 48, 0x0000_FFFF_FFFF_FFFFu64); -/// } -/// ``` -#[macro_export] -macro_rules! secret_block { - ( - $(#[$meta:meta])* - $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); -) => { - $(#[$meta])* - #[derive(Debug, Clone, Copy, PartialEq, Eq, ::zeroize::Zeroize)] - $vis struct $name($int); - - impl $name { - /// Mask to restrict the underlying integer to valid bits. - pub const MASK: $int = $mask; - - /// Calculate the number of hex digits needed for the bit width - const fn hex_width() -> usize { - ($bits as usize).div_ceil(4) - } - - /// Calculate the number of octal digits needed for the bit width - const fn octal_width() -> usize { - ($bits as usize).div_ceil(3) - } - - #[inline] - #[must_use] - pub const fn new(value: $int) -> Self { - Self(value & Self::MASK) - } - - secret_block!(@conversions_as $int); - secret_block!(@conversions_from $int $int); - } - - impl From<$int> for $name { - fn from(v: $int) -> Self { - Self(v & Self::MASK) - } - } - - impl From<$name> for $int { - fn from(value: $name) -> $int { - value.0 - } - } - - impl std::fmt::UpperHex for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$X}", self.0, width = Self::hex_width()) - } - } - - impl std::fmt::LowerHex for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$x}", self.0, width = Self::hex_width()) - } - } - - impl std::fmt::Octal for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$o}", self.0, width = Self::octal_width()) - } - } - - impl std::fmt::Binary for $name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:0width$b}", self.0, width = $bits) - } - } - - }; - // Helper: generate conversions_as based on type - (@conversions_as u8) => { - /// Return value as u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u8(&self) -> u8 { - self.0 as u8 - } - - secret_block!(@conversions_as u16); - }; - (@conversions_as u16) => { - /// Return value as u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u16(&self) -> u16 { - self.0 as u16 - } - - secret_block!(@conversions_as u32); - }; - (@conversions_as u32) => { - /// Return value as u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u32(&self) -> u32 { - self.0 as u32 - } - - secret_block!(@conversions_as u64); - }; - (@conversions_as u64) => { - /// Return value as u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u64(&self) -> u64 { - self.0 as u64 - } - }; - // Helper: generate conversions_from based on type - (@conversions_from u8 $int:tt) => { - /// Create value from u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u8(key: u8) -> Self { - Self(key as $int & Self::MASK) - } - }; - (@conversions_from u16 $int:tt) => { - /// Create value from u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u16(key: u16) -> Self { - Self(key as $int & Self::MASK) - } - - secret_block!(@conversions_from u8 $int); - }; - (@conversions_from u32 $int:tt) => { - /// Create value from u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u32(key: u32) -> Self { - Self(key as $int & Self::MASK) - } - - secret_block!(@conversions_from u16 $int); - }; - (@conversions_from u64 $int:tt) => { - /// Create value from u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u64(key: u64) -> Self { - Self(key & Self::MASK) - } - - secret_block!(@conversions_from u32 $int); - } -} diff --git a/des/src/des.rs b/des/src/des.rs index 777040d..93834bb 100644 --- a/des/src/des.rs +++ b/des/src/des.rs @@ -81,21 +81,21 @@ where { let mut lr = LR::from(block); - for subkey in subkeys { + for &subkey in subkeys { feistel(&mut lr, subkey); } lr.swap(); lr.into() } -fn feistel(lr: &mut LR, subkey: &Subkey) { +fn feistel(lr: &mut LR, subkey: Subkey) { let tmp = lr.right; lr.right = lr.left ^ f_function(lr.right, subkey); lr.left = tmp; } #[must_use] -fn f_function(right: Block32, subkey: &Subkey) -> Block32 { +fn f_function(right: Block32, subkey: Subkey) -> Block32 { let expanded = expansion_permutation(right); let xored = expanded ^ subkey; let sboxed = s_box_substitution(xored); diff --git a/des/src/key/cd56.rs b/des/src/key/cd56.rs index 2f59851..9c90830 100644 --- a/des/src/key/cd56.rs +++ b/des/src/key/cd56.rs @@ -1,7 +1,7 @@ use crate::key::{half28::Half28, key56::Key56}; use zeroize::ZeroizeOnDrop; -#[derive(ZeroizeOnDrop)] +#[derive(Clone, ZeroizeOnDrop)] pub struct CD56 { pub c: Half28, pub d: Half28, @@ -14,7 +14,7 @@ impl CD56 { Self { c, d } } - pub fn rotate_left(&mut self, amount: u8) { + pub const fn rotate_left(&mut self, amount: u8) { self.c = self.c.rotate_left(amount); self.d = self.d.rotate_left(amount); } @@ -22,12 +22,12 @@ impl CD56 { impl From for Key56 { fn from(value: CD56) -> Self { - Self::from_half28(&value.c, &value.d) + Self::from_half28(value.c, value.d) } } impl From<&CD56> for Key56 { fn from(value: &CD56) -> Self { - Self::from_half28(&value.c, &value.d) + Self::from_half28(value.c, value.d) } } diff --git a/des/src/key/half28.rs b/des/src/key/half28.rs index fa3ee76..9181a1b 100644 --- a/des/src/key/half28.rs +++ b/des/src/key/half28.rs @@ -7,7 +7,7 @@ secret_key! { impl Half28 { #[must_use] - pub const fn rotate_left(&self, amount: u8) -> Self { + pub const fn rotate_left(self, amount: u8) -> Self { let value = self.0; let main_shifted = (value << amount) & Self::MASK; let wrapped_bits = (value >> (28 - amount)) & ((1 << amount) - 1); diff --git a/des/src/key/key56.rs b/des/src/key/key56.rs index 356440a..81202ba 100644 --- a/des/src/key/key56.rs +++ b/des/src/key/key56.rs @@ -1,7 +1,4 @@ -use crate::{ - key::{cd56::CD56, half28::Half28}, - secret_key, -}; +use super::{cd56::CD56, half28::Half28, secret_key}; secret_key! { /// 56-bit key after PC-1 (lower 56 bits used). @@ -10,14 +7,14 @@ secret_key! { impl Key56 { #[must_use] - pub const fn split(&self) -> CD56 { + pub const fn split(self) -> CD56 { let c = ((self.0 >> 28) & 0x0FFF_FFFF) as u32; let d = (self.0 & 0x0FFF_FFFF) as u32; CD56::new(Half28::from_u32(c), Half28::from_u32(d)) } #[must_use] - pub const fn from_half28(left: &Half28, right: &Half28) -> Self { + pub const fn from_half28(left: Half28, right: Half28) -> Self { let left = left.as_u64(); let right = right.as_u64(); Self::from_u64((left << 28) | right) diff --git a/des/src/key/mod.rs b/des/src/key/mod.rs index 6db9f79..3947c3f 100644 --- a/des/src/key/mod.rs +++ b/des/src/key/mod.rs @@ -2,9 +2,8 @@ mod cd56; mod des_key; mod half28; mod key56; -mod secret_key; mod subkey; mod subkeys; -use crate::secret_key; +use cipher_core::secret_key; pub use {des_key::Key, subkey::Subkey, subkeys::Subkeys}; diff --git a/des/src/key/secret_key.rs b/des/src/key/secret_key.rs deleted file mode 100644 index a935415..0000000 --- a/des/src/key/secret_key.rs +++ /dev/null @@ -1,127 +0,0 @@ -/// Macro to generate a masked, zeroizable integer wrapper type. -/// -/// Usage: -/// ``` -/// use des::secret_key; -/// secret_key! { -/// /// docs... -/// pub struct Subkey(u64, 48, 0x0000_FFFF_FFFF_FFFFu64); -/// } -/// ``` -#[macro_export] -macro_rules! secret_key { - ( - $(#[$meta:meta])* - $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); -) => { - $(#[$meta])* - #[derive(::zeroize::ZeroizeOnDrop, Default)] - $vis struct $name($int); - - impl $name { - /// Mask to restrict the underlying integer to valid bits. - pub const MASK: $int = $mask; - - secret_key!(@conversions_as $int); - secret_key!(@conversions_from $int $int); - } - - impl ::std::fmt::Debug for $name { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - f.write_str(concat!(stringify!($name), "[REDACTED]")) - } - } - - impl From<$int> for $name { - fn from(v: $int) -> Self { - Self(v & Self::MASK) - } - } - }; - // Helper: generate conversions_as based on type - (@conversions_as u8) => { - /// Return value as u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u8(&self) -> u8 { - self.0 as u8 - } - - secret_key!(@conversions_as u16); - }; - (@conversions_as u16) => { - /// Return value as u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u16(&self) -> u16 { - self.0 as u16 - } - - secret_key!(@conversions_as u32); - }; - (@conversions_as u32) => { - /// Return value as u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u32(&self) -> u32 { - self.0 as u32 - } - - secret_key!(@conversions_as u64); - }; - (@conversions_as u64) => { - /// Return value as u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn as_u64(&self) -> u64 { - self.0 as u64 - } - }; - // Helper: generate conversions_from based on type - (@conversions_from u8 $int:tt) => { - /// Create value from u8 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u8(key: u8) -> Self { - Self(key as $int & Self::MASK) - } - }; - (@conversions_from u16 $int:tt) => { - /// Create value from u16 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u16(key: u16) -> Self { - Self(key as $int & Self::MASK) - } - - secret_key!(@conversions_from u8 $int); - }; - (@conversions_from u32 $int:tt) => { - /// Create value from u32 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u32(key: u32) -> Self { - Self(key as $int & Self::MASK) - } - - secret_key!(@conversions_from u16 $int); - }; - (@conversions_from u64 $int:tt) => { - /// Create value from u64 - #[allow(dead_code)] - #[inline] - #[must_use] - pub const fn from_u64(key: u64) -> Self { - Self(key & Self::MASK) - } - - secret_key!(@conversions_from u32 $int); - } -}