/rust/registry/src/index.crates.io-1949cf8c6b5b557f/chacha20-0.10.0/src/backends/soft.rs
Line | Count | Source |
1 | | //! Portable implementation which does not rely on architecture-specific intrinsics. |
2 | | |
3 | | #![allow(clippy::cast_possible_truncation)] |
4 | | |
5 | | use crate::{ChaChaCore, Rounds, STATE_WORDS, Variant, quarter_round}; |
6 | | |
7 | | #[cfg(feature = "cipher")] |
8 | | use crate::chacha::Block; |
9 | | #[cfg(feature = "cipher")] |
10 | | use cipher::{ |
11 | | BlockSizeUser, ParBlocksSizeUser, StreamCipherBackend, |
12 | | consts::{U1, U64}, |
13 | | }; |
14 | | |
15 | | #[cfg(feature = "rng")] |
16 | | use crate::rng::BLOCK_WORDS; |
17 | | |
18 | | pub(crate) struct Backend<'a, R: Rounds, V: Variant>(pub(crate) &'a mut ChaChaCore<R, V>); |
19 | | |
20 | | #[cfg(feature = "cipher")] |
21 | | impl<R: Rounds, V: Variant> BlockSizeUser for Backend<'_, R, V> { |
22 | | type BlockSize = U64; |
23 | | } |
24 | | |
25 | | #[cfg(feature = "cipher")] |
26 | | impl<R: Rounds, V: Variant> ParBlocksSizeUser for Backend<'_, R, V> { |
27 | | type ParBlocksSize = U1; |
28 | | } |
29 | | |
30 | | #[cfg(feature = "cipher")] |
31 | | impl<R: Rounds, V: Variant> StreamCipherBackend for Backend<'_, R, V> { |
32 | | #[inline(always)] |
33 | | fn gen_ks_block(&mut self, block: &mut Block) { |
34 | | let res = run_rounds::<R>(&self.0.state); |
35 | | let mut ctr = (u64::from(self.0.state[13]) << 32) | u64::from(self.0.state[12]); |
36 | | ctr = ctr.wrapping_add(1); |
37 | | self.0.state[12] = ctr as u32; |
38 | | if size_of::<V::Counter>() == 8 { |
39 | | self.0.state[13] = (ctr >> 32) as u32; |
40 | | } |
41 | | |
42 | | for (chunk, val) in block.chunks_exact_mut(4).zip(res.iter()) { |
43 | | chunk.copy_from_slice(&val.to_le_bytes()); |
44 | | } |
45 | | } |
46 | | } |
47 | | |
48 | | #[cfg(feature = "rng")] |
49 | | impl<R: Rounds, V: Variant> Backend<'_, R, V> { |
50 | | #[inline(always)] |
51 | 0 | pub(crate) fn gen_ks_blocks(&mut self, buffer: &mut [u32; 64]) { |
52 | 0 | for block in 0..4 { |
53 | 0 | let res = run_rounds::<R>(&self.0.state); |
54 | 0 | let mut ctr = (u64::from(self.0.state[13]) << 32) | u64::from(self.0.state[12]); |
55 | 0 | ctr = ctr.wrapping_add(1); |
56 | 0 | self.0.state[12] = ctr as u32; |
57 | 0 | self.0.state[13] = (ctr >> 32) as u32; |
58 | 0 |
|
59 | 0 | buffer[block * BLOCK_WORDS as usize..(block + 1) * BLOCK_WORDS as usize] |
60 | 0 | .copy_from_slice(&res); |
61 | 0 | } |
62 | 0 | } Unexecuted instantiation: <chacha20::backends::soft::Backend<chacha20::R12, chacha20::variants::Legacy>>::gen_ks_blocks Unexecuted instantiation: <chacha20::backends::soft::Backend<_, _>>::gen_ks_blocks |
63 | | } |
64 | | |
65 | | #[inline(always)] |
66 | 0 | fn run_rounds<R: Rounds>(state: &[u32; STATE_WORDS]) -> [u32; STATE_WORDS] { |
67 | 0 | let mut res = *state; |
68 | | |
69 | 0 | for _ in 0..R::COUNT { |
70 | 0 | // column rounds |
71 | 0 | quarter_round(0, 4, 8, 12, &mut res); |
72 | 0 | quarter_round(1, 5, 9, 13, &mut res); |
73 | 0 | quarter_round(2, 6, 10, 14, &mut res); |
74 | 0 | quarter_round(3, 7, 11, 15, &mut res); |
75 | 0 |
|
76 | 0 | // diagonal rounds |
77 | 0 | quarter_round(0, 5, 10, 15, &mut res); |
78 | 0 | quarter_round(1, 6, 11, 12, &mut res); |
79 | 0 | quarter_round(2, 7, 8, 13, &mut res); |
80 | 0 | quarter_round(3, 4, 9, 14, &mut res); |
81 | 0 | } |
82 | | |
83 | 0 | for (s1, s0) in res.iter_mut().zip(state.iter()) { |
84 | 0 | *s1 = s1.wrapping_add(*s0); |
85 | 0 | } |
86 | 0 | res |
87 | 0 | } Unexecuted instantiation: chacha20::backends::soft::run_rounds::<chacha20::R12> Unexecuted instantiation: chacha20::backends::soft::run_rounds::<_> |