diff --git a/chacha20/src/backends/neon.rs b/chacha20/src/backends/neon.rs index 23c9207..79c3121 100644 --- a/chacha20/src/backends/neon.rs +++ b/chacha20/src/backends/neon.rs @@ -88,15 +88,6 @@ impl ParBlocksSizeUser for Backend { type ParBlocksSize = U4; } -macro_rules! add64 { - ($a:expr, $b:expr) => { - vreinterpretq_u32_u64(vaddq_u64( - vreinterpretq_u64_u32($a), - vreinterpretq_u64_u32($b), - )) - }; -} - /// Evaluates to `a = a + b`, where the operands are u32x4s macro_rules! add_assign_vec { ($a:expr, $b:expr) => { @@ -113,7 +104,7 @@ impl StreamCipherBackend for Backend { self.gen_par_ks_blocks(&mut par); *block = par[0]; unsafe { - self.state[3] = add64!(state3, vld1q_u32([1, 0, 0, 0].as_ptr())); + self.state[3] = vaddq_u32(state3, vld1q_u32([1, 0, 0, 0].as_ptr())); } } @@ -126,19 +117,19 @@ impl StreamCipherBackend for Backend { self.state[0], self.state[1], self.state[2], - add64!(self.state[3], self.ctrs[0]), + vaddq_u32(self.state[3], self.ctrs[0]), ], [ self.state[0], self.state[1], self.state[2], - add64!(self.state[3], self.ctrs[1]), + vaddq_u32(self.state[3], self.ctrs[1]), ], [ self.state[0], self.state[1], self.state[2], - add64!(self.state[3], self.ctrs[2]), + vaddq_u32(self.state[3], self.ctrs[2]), ], ]; @@ -152,7 +143,7 @@ impl StreamCipherBackend for Backend { add_assign_vec!(blocks[block][state_row], self.state[state_row]); } if block > 0 { - blocks[block][3] = add64!(blocks[block][3], self.ctrs[block - 1]); + blocks[block][3] = vaddq_u32(blocks[block][3], self.ctrs[block - 1]); } // write blocks to dest for state_row in 0..4 { @@ -162,7 +153,7 @@ impl StreamCipherBackend for Backend { ); } } - self.state[3] = add64!(self.state[3], self.ctrs[3]); + self.state[3] = vaddq_u32(self.state[3], self.ctrs[3]); } } } @@ -205,19 +196,19 @@ impl Backend { self.state[0], self.state[1], self.state[2], - add64!(self.state[3], self.ctrs[0]), + vaddq_u32(self.state[3], self.ctrs[0]), ], [ self.state[0], self.state[1], self.state[2], - add64!(self.state[3], self.ctrs[1]), + vaddq_u32(self.state[3], self.ctrs[1]), ], [ self.state[0], self.state[1], self.state[2], - add64!(self.state[3], self.ctrs[2]), + vaddq_u32(self.state[3], self.ctrs[2]), ], ]; @@ -232,7 +223,7 @@ impl Backend { add_assign_vec!(blocks[block][state_row], self.state[state_row]); } if block > 0 { - blocks[block][3] = add64!(blocks[block][3], self.ctrs[block - 1]); + blocks[block][3] = vaddq_u32(blocks[block][3], self.ctrs[block - 1]); } // write blocks to buffer for state_row in 0..4 { @@ -243,7 +234,7 @@ impl Backend { } dest_ptr = dest_ptr.add(64); } - self.state[3] = add64!(self.state[3], self.ctrs[3]); + self.state[3] = vaddq_u32(self.state[3], self.ctrs[3]); } } diff --git a/chacha20/src/rng.rs b/chacha20/src/rng.rs index b9a4b9e..654cfb9 100644 --- a/chacha20/src/rng.rs +++ b/chacha20/src/rng.rs @@ -1114,5 +1114,30 @@ pub(crate) mod tests { rng.set_stream([3, 3333, 333333]); let expected = 2059058063; assert_eq!(rng.next_u32(), expected); + rng.set_stream(1234567); + let expected = 1254506509; + assert_eq!(rng.next_u32(), expected); + rng.set_stream([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); + let expected = 1391671567; + assert_eq!(rng.next_u32(), expected); + } + + /// If this test fails, the backend may be + /// performing 64-bit addition. + #[test] + fn counter_wrapping() { + let mut rng = ChaChaRng::from_seed([0u8; 32]); + + // get first four blocks and word pos + let mut first_blocks = [0u8; 64 * 4]; + rng.fill_bytes(&mut first_blocks); + let word_pos = rng.get_word_pos(); + + // get first four blocks after wrapping + rng.set_block_pos(u32::MAX); + let mut result = [0u8; 64 * 5]; + rng.fill_bytes(&mut result); + assert_eq!(word_pos, rng.get_word_pos()); + assert_eq!(&first_blocks[0..64 * 4], &result[64..]); } }