aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2025-04-11 18:24:44 +0200
committerDaniel Schadt <kingdread@gmx.de>2025-04-11 18:24:44 +0200
commitaf2c01c00afdb819c95d68e2c7e980e673c0d5b2 (patch)
tree8e329ca44fdf30a628408a83c84f88ee4948191b /src
parentab5cb252fc6b16ce308646011d7c692aa935d223 (diff)
downloadzears-af2c01c00afdb819c95d68e2c7e980e673c0d5b2.tar.gz
zears-af2c01c00afdb819c95d68e2c7e980e673c0d5b2.tar.bz2
zears-af2c01c00afdb819c95d68e2c7e980e673c0d5b2.zip
merge {de,en}cipher_aez_{tiny,core}
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs222
1 files changed, 62 insertions, 160 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 163279a..a0ddfa9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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) {