1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use subtle::ConstantTimeEq; use ::common::{ Tag, tags, with, pad, absorb }; use ::constant::{ U, S, BLOCK_LENGTH, KEY_LENGTH, TAG_LENGTH }; use ::{ permutation, Norx, Encrypt, Decrypt }; pub struct Process<Mode> { state: [U; S], started: bool, _mode: Mode } impl Norx { pub fn encrypt(self, aad: &[u8]) -> Process<Encrypt> { let Norx(mut state) = self; absorb::<tags::Header>(&mut state, aad); Process { state, started: false, _mode: Encrypt } } pub fn decrypt(self, aad: &[u8]) -> Process<Decrypt> { let Norx(mut state) = self; absorb::<tags::Header>(&mut state, aad); Process { state, started: false, _mode: Decrypt } } } impl Process<Encrypt> { pub fn process<'a, I>(&mut self, bufs: I) where I: Iterator<Item = (&'a [u8; BLOCK_LENGTH], &'a mut [u8; BLOCK_LENGTH])> { for (input, output) in bufs { self.started = true; self.state[15] ^= <tags::Payload as Tag>::TAG; permutation::norx(&mut self.state); with(&mut self.state, |state| { for i in 0..BLOCK_LENGTH { state[i] ^= input[i]; } output.copy_from_slice(&state[..BLOCK_LENGTH]); }); } } pub fn finalize(mut self, key: &[u8; KEY_LENGTH], aad2: &[u8], input: &[u8], output: &mut [u8]) { assert!(input.len() < BLOCK_LENGTH); assert_eq!(input.len() + TAG_LENGTH, output.len()); let (output, tag) = output.split_at_mut(input.len()); let tag = array_mut_ref!(tag, 0, TAG_LENGTH); if self.started || !input.is_empty() { let input_pad = pad(input); self.state[15] ^= <tags::Payload as Tag>::TAG; permutation::norx(&mut self.state); with(&mut self.state, |state| { for i in 0..BLOCK_LENGTH { state[i] ^= input_pad[i]; } output.copy_from_slice(&state[..input.len()]); }); } Norx(self.state).finalize(key, aad2, tag); } } impl Process<Decrypt> { pub fn process<'a, I>(&mut self, bufs: I) where I: Iterator<Item = (&'a [u8; BLOCK_LENGTH], &'a mut [u8; BLOCK_LENGTH])> { for (input, output) in bufs { self.started = true; self.state[15] ^= <tags::Payload as Tag>::TAG; permutation::norx(&mut self.state); with(&mut self.state, |state| { for i in 0..BLOCK_LENGTH { output[i] = state[i] ^ input[i]; } state[..BLOCK_LENGTH].copy_from_slice(input); }); } } pub fn finalize(mut self, key: &[u8; KEY_LENGTH], aad2: &[u8], input: &[u8], output: &mut [u8]) -> bool { assert!(output.len() < BLOCK_LENGTH); assert_eq!(input.len(), output.len() + TAG_LENGTH); let (input, tag) = input.split_at(output.len()); if self.started || !output.is_empty() { let mut lastblock = [0; BLOCK_LENGTH]; self.state[15] ^= <tags::Payload as Tag>::TAG; permutation::norx(&mut self.state); with(&mut self.state, |state| { lastblock[..input.len()].copy_from_slice(input); lastblock[input.len()..].copy_from_slice(&state[..BLOCK_LENGTH][input.len()..]); lastblock[input.len()] ^= 0x01; lastblock[BLOCK_LENGTH - 1] ^= 0x80; for i in 0..input.len() { output[i] = state[i] ^ lastblock[i]; } state[..BLOCK_LENGTH].copy_from_slice(&lastblock); }); } let mut tag2 = [0; TAG_LENGTH]; Norx(self.state).finalize(key, aad2, &mut tag2); tag.ct_eq(&tag2).unwrap_u8() == 1 } }