diff options
author | Daniel Schadt <kingdread@gmx.de> | 2025-04-11 18:24:44 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2025-04-11 18:24:44 +0200 |
commit | af2c01c00afdb819c95d68e2c7e980e673c0d5b2 (patch) | |
tree | 8e329ca44fdf30a628408a83c84f88ee4948191b /src/lib.rs | |
parent | ab5cb252fc6b16ce308646011d7c692aa935d223 (diff) | |
download | zears-af2c01c00afdb819c95d68e2c7e980e673c0d5b2.tar.gz zears-af2c01c00afdb819c95d68e2c7e980e673c0d5b2.tar.bz2 zears-af2c01c00afdb819c95d68e2c7e980e673c0d5b2.zip |
merge {de,en}cipher_aez_{tiny,core}
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 222 |
1 files changed, 62 insertions, 160 deletions
@@ -101,6 +101,12 @@ type Tweak<'a> = &'a [&'a [u8]]; static ZEROES: [u8; 1024] = [0; 1024]; +#[derive(Clone, Copy, PartialEq, Eq)] +enum Mode { + Encipher, + Decipher, +} + /// AEZ encryption scheme. pub struct Aez { key_i: Block, @@ -367,13 +373,21 @@ fn is_zeroes(data: &[u8]) -> bool { fn encipher(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { if message.len() < 256 / 8 { - encipher_aez_tiny(aez, tweaks, message) + cipher_aez_tiny(Mode::Encipher, aez, tweaks, message) + } else { + cipher_aez_core(Mode::Encipher, aez, tweaks, message) + } +} + +fn decipher(aez: &Aez, tweaks: Tweak, buffer: &mut [u8]) { + if buffer.len() < 256 / 8 { + cipher_aez_tiny(Mode::Decipher, aez, tweaks, buffer); } else { - encipher_aez_core(aez, tweaks, message) + cipher_aez_core(Mode::Decipher, aez, tweaks, buffer); } } -fn encipher_aez_tiny(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { +fn cipher_aez_tiny(mode: Mode, aez: &Aez, tweaks: Tweak, message: &mut [u8]) { let mu = message.len() * 8; assert!(mu < 256); let n = mu / 2; @@ -385,6 +399,12 @@ fn encipher_aez_tiny(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { _ => 8, }; + if mode == Mode::Decipher && mu < 128 { + let mut c = Block::from_slice(message); + c = c ^ (e(0, 3, aez, delta ^ (c | Block::one())) & Block::one()); + message.copy_from_slice(&c.bytes()[..mu / 8]); + } + let (mut left, mut right); // We might end up having to split at a nibble, so manually adjust for that if n % 8 == 0 { @@ -395,11 +415,21 @@ fn encipher_aez_tiny(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { left = Block::from_slice(&message[..n / 8 + 1]).clip(n); right = Block::from_slice(&message[n / 8..]) << 4; }; + let i = if mu >= 128 { 6 } else { 7 }; - for j in 0..round_count { - let right_ = (left ^ e(0, i, aez, delta ^ right.pad(n) ^ Block::from_int(j))).clip(n); - (left, right) = (right, right_); + + if mode == Mode::Encipher { + for j in 0..round_count { + let right_ = (left ^ e(0, i, aez, delta ^ right.pad(n) ^ Block::from_int(j))).clip(n); + (left, right) = (right, right_); + } + } else { + for j in (0..round_count).rev() { + let right_ = (left ^ e(0, i, aez, delta ^ right.pad(n) ^ Block::from_int(j))).clip(n); + (left, right) = (right, right_); + } } + if n % 8 == 0 { message[..n / 8].copy_from_slice(&right.bytes()[..n / 8]); message[n / 8..].copy_from_slice(&left.bytes()[..n / 8]); @@ -414,14 +444,15 @@ fn encipher_aez_tiny(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { index += 1; } } - if mu < 128 { + + if mode == Mode::Encipher && mu < 128 { let mut c = Block::from_slice(&message); c = c ^ (e(0, 3, aez, delta ^ (c | Block::one())) & Block::one()); message.copy_from_slice(&c.bytes()[..mu / 8]); } } -fn encipher_aez_core(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { +fn cipher_aez_core(mode: Mode, aez: &Aez, tweaks: Tweak, message: &mut [u8]) { assert!(message.len() >= 32); let delta = aez_hash(aez, tweaks); let mut blocks = BlockAccessor::new(message); @@ -462,8 +493,17 @@ fn encipher_aez_core(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { } } - let s_x = m_x ^ delta ^ x ^ e(0, 1, aez, m_y); - let s_y = m_y ^ e(-1, 1, aez, s_x); + let (s_x, s_y); + match mode { + Mode::Encipher => { + s_x = m_x ^ delta ^ x ^ e(0, 1, aez, m_y); + s_y = m_y ^ e(-1, 1, aez, s_x); + }, + Mode::Decipher => { + s_x = m_x ^ delta ^ x ^ e(0, 2, aez, m_y); + s_y = m_y ^ e(-1, 2, aez, s_x); + }, + } let s = s_x ^ s_y; let mut y = Block::null(); @@ -482,6 +522,7 @@ fn encipher_aez_core(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { ci.write_to(raw_wi); ci_.write_to(raw_xi); + y = y ^ yi; } @@ -502,8 +543,17 @@ fn encipher_aez_core(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { } } - let c_y = s_x ^ e(-1, 2, aez, s_y); - let c_x = s_y ^ delta ^ y ^ e(0, 2, aez, c_y); + let (c_x, c_y); + match mode { + Mode::Encipher => { + c_y = s_x ^ e(-1, 2, aez, s_y); + c_x = s_y ^ delta ^ y ^ e(0, 2, aez, c_y); + }, + Mode::Decipher => { + c_y = s_x ^ e(-1, 1, aez, s_y); + c_x = s_y ^ delta ^ y ^ e(0, 1, aez, c_y); + }, + } blocks.set_m_u(c_u); blocks.set_m_v(c_v); @@ -511,154 +561,6 @@ fn encipher_aez_core(aez: &Aez, tweaks: Tweak, message: &mut [u8]) { blocks.set_m_y(c_y); } -fn decipher(aez: &Aez, tweaks: Tweak, buffer: &mut [u8]) { - if buffer.len() < 256 / 8 { - decipher_aez_tiny(aez, tweaks, buffer); - } else { - decipher_aez_core(aez, tweaks, buffer); - } -} - -fn decipher_aez_tiny(aez: &Aez, tweaks: Tweak, buffer: &mut [u8]) { - let mu = buffer.len() * 8; - assert!(mu < 256); - let n = mu / 2; - let delta = aez_hash(aez, tweaks); - let round_count = match mu { - 8 => 24u32, - 16 => 16, - _ if mu < 128 => 10, - _ => 8, - }; - - if mu < 128 { - let mut c = Block::from_slice(buffer); - c = c ^ (e(0, 3, aez, delta ^ (c | Block::one())) & Block::one()); - buffer.copy_from_slice(&c.bytes()[..mu / 8]); - } - - let (mut left, mut right); - // We might end up having to split at a nibble, so manually adjust for that - if n % 8 == 0 { - left = Block::from_slice(&buffer[..n / 8]); - right = Block::from_slice(&buffer[n / 8..]); - } else { - left = Block::from_slice(&buffer[..n / 8 + 1]).clip(n); - right = Block::from_slice(&buffer[n / 8..]) << 4; - }; - let i = if mu >= 128 { 6 } else { 7 }; - for j in (0..round_count).rev() { - let right_ = (left ^ e(0, i, aez, delta ^ right.pad(n) ^ Block::from_int(j))).clip(n); - (left, right) = (right, right_); - } - - if n % 8 == 0 { - buffer[..n / 8].copy_from_slice(&right.bytes()[..n / 8]); - buffer[n / 8..].copy_from_slice(&left.bytes()[..n / 8]); - } else { - let mut index = n / 8; - buffer[..index + 1].copy_from_slice(&right.bytes()[..index + 1]); - for byte in &left.bytes()[..n / 8 + 1] { - buffer[index] |= byte >> 4; - if index < buffer.len() - 1 { - buffer[index + 1] = (byte & 0x0f) << 4; - } - index += 1; - } - } -} - -fn decipher_aez_core(aez: &Aez, tweaks: Tweak, buffer: &mut [u8]) { - assert!(buffer.len() >= 32); - let delta = aez_hash(aez, tweaks); - let mut blocks = BlockAccessor::new(buffer); - let (c_u, c_v, c_x, c_y, d) = ( - blocks.m_u(), - blocks.m_v(), - blocks.m_x(), - blocks.m_y(), - blocks.m_uv_len(), - ); - let len_v = d.saturating_sub(128); - - let mut y = Block::null(); - let mut e1_eval = E::new(1, 0, aez); - let e0_eval = E::new(0, 0, aez); - for (raw_ci, raw_ci_) in blocks.pairs_mut() { - e1_eval.advance(); - let ci = Block::from(*raw_ci); - let ci_ = Block::from(*raw_ci_); - let wi = ci ^ e1_eval.eval(ci_); - let yi = ci_ ^ e0_eval.eval(wi); - - *raw_ci = wi.bytes(); - *raw_ci_ = yi.bytes(); - - y = y ^ yi; - } - - match d { - 0 => (), - _ if d <= 127 => { - y = y ^ e(0, 4, aez, c_u.pad(d.into())); - } - _ => { - y = y ^ e(0, 4, aez, c_u); - y = y ^ e(0, 5, aez, c_v.pad(len_v.into())); - } - } - - let s_x = c_x ^ delta ^ y ^ e(0, 2, aez, c_y); - let s_y = c_y ^ e(-1, 2, aez, s_x); - let s = s_x ^ s_y; - - let mut x = Block::null(); - let mut e2_eval = E::new(2, 0, aez); - let mut e1_eval = E::new(1, 0, aez); - let e0_eval = E::new(0, 0, aez); - for (raw_wi, raw_yi) in blocks.pairs_mut() { - e2_eval.advance(); - e1_eval.advance(); - let wi = Block::from(*raw_wi); - let yi = Block::from(*raw_yi); - let s_ = e2_eval.eval(s); - let xi = wi ^ s_; - let zi = yi ^ s_; - let mi_ = xi ^ e0_eval.eval(zi); - let mi = zi ^ e1_eval.eval(mi_); - - *raw_wi = mi.bytes(); - *raw_yi = mi_.bytes(); - - x = x ^ xi; - } - - let mut m_u = Block::default(); - let mut m_v = Block::default(); - - match d { - 0 => (), - _ if d <= 127 => { - m_u = (c_u ^ e(-1, 4, aez, s)).clip(d.into()); - x = x ^ e(0, 4, aez, m_u.pad(d.into())); - } - _ => { - m_u = c_u ^ e(-1, 4, aez, s); - m_v = (c_v ^ e(-1, 5, aez, s)).clip(len_v.into()); - x = x ^ e(0, 4, aez, m_u); - x = x ^ e(0, 5, aez, m_v.pad(len_v.into())); - } - } - - let m_y = s_x ^ e(-1, 1, aez, s_y); - let m_x = s_y ^ delta ^ x ^ e(0, 1, aez, m_y); - - blocks.set_m_u(m_u); - blocks.set_m_v(m_v); - blocks.set_m_x(m_x); - blocks.set_m_y(m_y); -} - fn pad_to_blocks(value: &[u8]) -> Vec<Block> { let mut blocks = Vec::new(); for chunk in value.chunks(16) { |