diff options
-rw-r--r-- | src/accessor.rs | 58 | ||||
-rw-r--r-- | src/lib.rs | 88 |
2 files changed, 132 insertions, 14 deletions
diff --git a/src/accessor.rs b/src/accessor.rs index 35d2890..e7e6de6 100644 --- a/src/accessor.rs +++ b/src/accessor.rs @@ -8,6 +8,8 @@ pub struct BlockAccessor<'a> { num_block_pairs: usize, } +const BIG_CHUNK_SIZE: usize = 8 * 32; + impl<'a> BlockAccessor<'a> { pub fn new(message: &'a mut [u8]) -> Self { let num_block_pairs = (message.len() - 16 - 16) / 32; @@ -78,4 +80,60 @@ impl<'a> BlockAccessor<'a> { .map(move |x| x.split_at_mut(16)) .map(move |(x, y)| (x.try_into().unwrap(), y.try_into().unwrap())) } + + pub fn suffix_8_mut(&mut self) -> impl Iterator<Item = (&mut [u8; 16], &mut [u8; 16])> { + let start = self.suffix_start() / BIG_CHUNK_SIZE * BIG_CHUNK_SIZE; + let stop = self.suffix_start(); + self.data[start..stop] + .chunks_exact_mut(32) + .map(move |x| x.split_at_mut(16)) + .map(move |(x, y)| (x.try_into().unwrap(), y.try_into().unwrap())) + } + + pub fn pairs_8_mut( + &mut self, + ) -> impl Iterator<Item = ([&mut [u8; 16]; 8], [&mut [u8; 16]; 8])> { + let stop = self.suffix_start() / BIG_CHUNK_SIZE * BIG_CHUNK_SIZE; + self.data[..stop] + .chunks_exact_mut(BIG_CHUNK_SIZE) + .map(move |x| { + let (b0, b1) = x.split_at_mut(BIG_CHUNK_SIZE / 2); + let (b00, b01) = b0.split_at_mut(BIG_CHUNK_SIZE / 4); + let (b10, b11) = b1.split_at_mut(BIG_CHUNK_SIZE / 4); + let (b000, b001) = b00.split_at_mut(BIG_CHUNK_SIZE / 8); + let (b010, b011) = b01.split_at_mut(BIG_CHUNK_SIZE / 8); + let (b100, b101) = b10.split_at_mut(BIG_CHUNK_SIZE / 8); + let (b110, b111) = b11.split_at_mut(BIG_CHUNK_SIZE / 8); + let (b0000, b0001) = b000.split_at_mut(16); + let (b0010, b0011) = b001.split_at_mut(16); + let (b0100, b0101) = b010.split_at_mut(16); + let (b0110, b0111) = b011.split_at_mut(16); + let (b1000, b1001) = b100.split_at_mut(16); + let (b1010, b1011) = b101.split_at_mut(16); + let (b1100, b1101) = b110.split_at_mut(16); + let (b1110, b1111) = b111.split_at_mut(16); + ( + [ + b0000.try_into().unwrap(), + b0010.try_into().unwrap(), + b0100.try_into().unwrap(), + b0110.try_into().unwrap(), + b1000.try_into().unwrap(), + b1010.try_into().unwrap(), + b1100.try_into().unwrap(), + b1110.try_into().unwrap(), + ], + [ + b0001.try_into().unwrap(), + b0011.try_into().unwrap(), + b0101.try_into().unwrap(), + b0111.try_into().unwrap(), + b1001.try_into().unwrap(), + b1011.try_into().unwrap(), + b1101.try_into().unwrap(), + b1111.try_into().unwrap(), + ], + ) + }) + } } @@ -481,6 +481,54 @@ fn cipher_aez_tiny(mode: Mode, aez: &Aez, tweaks: Tweak, message: &mut [u8]) { } } +macro_rules! unroll_pairs { + ( + $accessor:expr; + setup_unrolled => $setup_unrolled:block; + setup_single => $setup_single:block; + roll ($left:ident, $right:ident) => $roll:block; + ) => { + for (left, right) in $accessor.pairs_8_mut() { + $setup_unrolled; + + let [l0, l1, l2, l3, l4, l5, l6, l7] = left; + let [r0, r1, r2, r3, r4, r5, r6, r7] = right; + + let $left = l0; + let $right = r0; + $roll; + let $left = l1; + let $right = r1; + $roll; + let $left = l2; + let $right = r2; + $roll; + let $left = l3; + let $right = r3; + $roll; + let $left = l4; + let $right = r4; + $roll; + let $left = l5; + let $right = r5; + $roll; + let $left = l6; + let $right = r6; + $roll; + let $left = l7; + let $right = r7; + $roll; + } + + for (left, right) in $accessor.suffix_8_mut() { + let $left = left; + let $right = right; + $setup_single; + $roll; + } + }; +} + fn pass_one(aez: &Aez, blocks: &mut BlockAccessor) -> Block { let mut x = Block::null(); let mut e1_eval = E::new(1, 0, aez); @@ -507,20 +555,32 @@ fn pass_two(aez: &Aez, blocks: &mut BlockAccessor, s: Block) -> Block { let e2_eval = E::new(2, 0, aez); let mut e1_eval = E::new(1, 0, aez); let e0_eval = E::new(0, 0, aez); + let mut evals_for_s = e2_eval.evals_for(s); - for ((raw_wi, raw_xi), s_) in blocks.pairs_mut().zip(e2_eval.evals_for(s)) { - e1_eval.advance(); - let wi = Block::from(*raw_wi); - let xi = Block::from(*raw_xi); - let yi = wi ^ s_; - let zi = xi ^ s_; - let ci_ = yi ^ e0_eval.eval(zi); - let ci = zi ^ e1_eval.eval(ci_); - - ci.write_to(raw_wi); - ci_.write_to(raw_xi); - - y = y ^ yi; + unroll_pairs! { blocks; + setup_unrolled => { + evals_for_s.refill(); + }; + setup_single => { + if evals_for_s.len == 0 { + evals_for_s.refill(); + } + }; + roll (raw_wi, raw_xi) => { + e1_eval.advance(); + let wi = Block::from(*raw_wi); + let xi = Block::from(*raw_xi); + let yi = wi ^ evals_for_s.blocks[8 - evals_for_s.len]; + let zi = xi ^ evals_for_s.blocks[8 - evals_for_s.len]; + let ci_ = yi ^ e0_eval.eval(zi); + let ci = zi ^ e1_eval.eval(ci_); + + ci.write_to(raw_wi); + ci_.write_to(raw_xi); + + y = y ^ yi; + evals_for_s.len -= 1; + }; } y @@ -692,7 +752,7 @@ impl<'a> E<'a> { self.aez.aes.aes4(block ^ delta) } - fn evals_for(self, block: Block) -> impl Iterator<Item = Block> { + fn evals_for(self, block: Block) -> Eiter<'a> { Eiter::new(self, block) } |