From b9f57a9f13f4d90fe31502297c4636dc214c1418 Mon Sep 17 00:00:00 2001 From: Noah Stiltner Date: Thu, 6 Feb 2025 12:01:07 -0600 Subject: [PATCH 1/4] added test --- chacha20/src/rng.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/chacha20/src/rng.rs b/chacha20/src/rng.rs index b9a4b9e..406f8ee 100644 --- a/chacha20/src/rng.rs +++ b/chacha20/src/rng.rs @@ -1115,4 +1115,23 @@ pub(crate) mod tests { let expected = 2059058063; 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..]); + } } From 6c6436018722b6fe4d9e7e3790d6bc250a7dfee9 Mon Sep 17 00:00:00 2001 From: Noah Stiltner Date: Thu, 6 Feb 2025 12:23:53 -0600 Subject: [PATCH 2/4] fixed 64-bit addition --- chacha20/src/backends/neon.rs | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) 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]); } } From 4c5398f9098bb73519df7b538379b8756067ef43 Mon Sep 17 00:00:00 2001 From: Noah Stiltner Date: Thu, 6 Feb 2025 13:15:29 -0600 Subject: [PATCH 3/4] added 2 more endian tests just to be sure; they passed --- chacha20/src/rng.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chacha20/src/rng.rs b/chacha20/src/rng.rs index 406f8ee..b4d2932 100644 --- a/chacha20/src/rng.rs +++ b/chacha20/src/rng.rs @@ -1114,6 +1114,12 @@ 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 From 037240087fc40524001243a8b9841943ee7605b2 Mon Sep 17 00:00:00 2001 From: Noah Stiltner Date: Thu, 6 Feb 2025 13:17:46 -0600 Subject: [PATCH 4/4] fmt --- chacha20/src/rng.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chacha20/src/rng.rs b/chacha20/src/rng.rs index b4d2932..654cfb9 100644 --- a/chacha20/src/rng.rs +++ b/chacha20/src/rng.rs @@ -1117,7 +1117,7 @@ pub(crate) mod tests { 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]); + rng.set_stream([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); let expected = 1391671567; assert_eq!(rng.next_u32(), expected); }