diff --git a/aes/src/aes.rs b/aes/src/aes.rs index b732e36..8fd2ff3 100644 --- a/aes/src/aes.rs +++ b/aes/src/aes.rs @@ -1,3 +1,5 @@ +use cipher_core::BlockCipher; + use crate::key::Key; pub struct Aes {} @@ -8,10 +10,17 @@ impl Aes { } } -impl Aes { +impl BlockCipher for Aes { const BLOCK_SIZE: usize = 16; - fn from_key(key: &[u8]) -> Self { Self::new(key) } + + fn transform_impl( + &self, + block: &[u8], + action: cipher_core::CipherAction, + ) -> cipher_core::CipherResult { + todo!() + } } diff --git a/aes/src/block/secret_block.rs b/aes/src/block/secret_block.rs index f70f0bb..eb3432f 100644 --- a/aes/src/block/secret_block.rs +++ b/aes/src/block/secret_block.rs @@ -121,9 +121,11 @@ macro_rules! secret_block { pub const fn as_u64(&self) -> u64 { self.0 as u64 } + + secret_block!(@conversions_as u128); }; (@conversions_as u128) => { - /// Return value as u64 + /// Return value as u129 #[allow(dead_code)] #[inline] #[must_use] @@ -175,7 +177,7 @@ macro_rules! secret_block { secret_block!(@conversions_from u32 $int); }; (@conversions_from u128 $int:tt) => { - /// Create value from u64 + /// Create value from u128 #[allow(dead_code)] #[inline] #[must_use] diff --git a/aes/src/key/mod.rs b/aes/src/key/mod.rs index 148a4ca..b5aaac9 100644 --- a/aes/src/key/mod.rs +++ b/aes/src/key/mod.rs @@ -1,3 +1,7 @@ mod aes_key; +mod secret_key; +mod subkey; +mod subkeys; +use crate::secret_key; pub use aes_key::Key; diff --git a/aes/src/key/secret_key.rs b/aes/src/key/secret_key.rs new file mode 100644 index 0000000..51b5f7f --- /dev/null +++ b/aes/src/key/secret_key.rs @@ -0,0 +1,149 @@ +/// 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 + } + + 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/aes/src/key/subkey.rs b/aes/src/key/subkey.rs new file mode 100644 index 0000000..74c9a7a --- /dev/null +++ b/aes/src/key/subkey.rs @@ -0,0 +1,13 @@ +use crate::key::secret_key; + +secret_key! { + /// A single AES round subkey + pub struct Subkey(u32, 32, 0xFFFF_FFFF); +} + +impl Subkey { + /// Zero value. + pub const fn zero() -> Self { + Self(0) + } +} diff --git a/aes/src/key/subkeys.rs b/aes/src/key/subkeys.rs new file mode 100644 index 0000000..7b29ca8 --- /dev/null +++ b/aes/src/key/subkeys.rs @@ -0,0 +1,132 @@ +use crate::key::{Key, subkey::Subkey}; +use std::{ + fmt::Debug, + iter::Rev, + ops::Index, + slice::{Iter, IterMut}, +}; + +// #[derive(Default)] +pub struct Subkeys([Subkey; 44]); + +impl Subkeys { + /// Generates 44 round subkeys from the given key. + #[must_use] + pub fn from_key(key: &Key) -> Self { + todo!() + } + + /// Returns an iterator over the subkeys. + pub fn iter(&self) -> Iter<'_, Subkey> { + self.0.iter() + } + + /// Returns a reverse iterator over the subkeys. + pub fn iter_rev(&self) -> Rev> { + self.0.iter().rev() + } + + /// Returns a mutable iterator over the subkeys. + pub fn iter_mut(&mut self) -> IterMut<'_, Subkey> { + self.0.iter_mut() + } +} + +impl<'a> IntoIterator for &'a Subkeys { + type Item = &'a Subkey; + type IntoIter = Iter<'a, Subkey>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a> IntoIterator for &'a mut Subkeys { + type Item = &'a mut Subkey; + type IntoIter = IterMut<'a, Subkey>; + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +impl Index for Subkeys { + type Output = Subkey; + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +impl Debug for Subkeys { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("Subkeys[REDACTED]") + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_KEY: u128 = 0x0F1571C947D9E8591CB7ADD6AF7F6798; + + impl PartialEq<[[u8; 4]; 44]> for Subkeys { + fn eq(&self, other: &[[u8; 4]; 44]) -> bool { + self.iter() + .zip(other) + .all(|(a, &b)| a.as_u32() == u32::from_be_bytes(b)) + } + } + + #[test] + fn from_key() { + let key = Key::from(TEST_KEY); + let subkeys = Subkeys::from_key(&key); + assert_eq!( + subkeys, + [ + [0x0F, 0x15, 0x71, 0xC9], + [0x47, 0xD9, 0xE8, 0x59], + [0x1C, 0xB7, 0xAD, 0xD6], + [0xAF, 0x7F, 0x67, 0x98], + [0xDC, 0x90, 0x37, 0xB0], + [0x9B, 0x49, 0xDF, 0xE9], + [0x87, 0xFE, 0x72, 0x3F], + [0x28, 0x81, 0x15, 0xA7], + [0xD2, 0xC9, 0x6B, 0x84], + [0x49, 0x80, 0xB4, 0x6D], + [0xCE, 0x7E, 0xC6, 0x52], + [0xE6, 0xFF, 0xD3, 0xF5], + [0xC0, 0xAF, 0x8D, 0x0A], + [0x89, 0x2F, 0x39, 0x67], + [0x47, 0x51, 0xFF, 0x35], + [0xA1, 0xAE, 0x2C, 0xC0], + [0x2C, 0xDE, 0x37, 0x38], + [0xA5, 0xF1, 0x0E, 0x5F], + [0xE2, 0xA0, 0xF1, 0x6A], + [0x43, 0x0E, 0xDD, 0xAA], + [0x97, 0x1F, 0x9B, 0x22], + [0x32, 0xEE, 0x95, 0x7D], + [0xD0, 0x4E, 0x64, 0x17], + [0x93, 0x40, 0xB9, 0xBD], + [0xBE, 0x49, 0xE1, 0xFE], + [0x8C, 0xA7, 0x74, 0x83], + [0x5C, 0xE9, 0x10, 0x94], + [0xCF, 0xA9, 0xA9, 0x29], + [0x2D, 0x9A, 0x44, 0x74], + [0xA1, 0x3D, 0x30, 0xF7], + [0xFD, 0xD4, 0x20, 0x63], + [0x32, 0x7D, 0x89, 0x4A], + [0x52, 0x3D, 0x92, 0x57], + [0xF3, 0x00, 0xA2, 0xA0], + [0x0E, 0xD4, 0x82, 0xC3], + [0x3C, 0xA9, 0x0B, 0x89], + [0x9A, 0x16, 0x35, 0xBC], + [0x69, 0x16, 0x97, 0x1C], + [0x67, 0xC2, 0x15, 0xDF], + [0x5B, 0x6B, 0x1E, 0x56], + [0xD3, 0x64, 0x84, 0x85], + [0xBA, 0x72, 0x13, 0x99], + [0xDD, 0xB0, 0x06, 0x46], + [0x86, 0xDB, 0x18, 0x10], + ] + ) + } +}