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
123
124
125
126
127
128
129
130
131
use salsa20_core::{CONSTANTS, IV_WORDS, KEY_WORDS, STATE_WORDS};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub(crate) mod sse2;
pub(crate) struct Block {
state: [u32; STATE_WORDS],
}
impl Block {
pub(crate) fn generate(
key: &[u32; KEY_WORDS],
iv: [u32; IV_WORDS],
counter: u64,
) -> [u32; STATE_WORDS] {
let mut block = Self {
state: [
CONSTANTS[0],
CONSTANTS[1],
CONSTANTS[2],
CONSTANTS[3],
key[0],
key[1],
key[2],
key[3],
key[4],
key[5],
key[6],
key[7],
(counter & 0xffff_ffff) as u32,
((counter >> 32) & 0xffff_ffff) as u32,
iv[0],
iv[1],
],
};
block.rounds();
block.finish(key, iv, counter)
}
#[inline]
fn rounds(&mut self) {
self.double_round();
self.double_round();
self.double_round();
self.double_round();
self.double_round();
self.double_round();
self.double_round();
self.double_round();
self.double_round();
self.double_round();
}
#[inline]
fn double_round(&mut self) {
let state = &mut self.state;
quarter_round(0, 4, 8, 12, state);
quarter_round(1, 5, 9, 13, state);
quarter_round(2, 6, 10, 14, state);
quarter_round(3, 7, 11, 15, state);
quarter_round(0, 5, 10, 15, state);
quarter_round(1, 6, 11, 12, state);
quarter_round(2, 7, 8, 13, state);
quarter_round(3, 4, 9, 14, state);
}
#[inline]
fn finish(
self,
key: &[u32; KEY_WORDS],
iv: [u32; IV_WORDS],
counter: u64,
) -> [u32; STATE_WORDS] {
let mut state = self.state;
state[0] = state[0].wrapping_add(CONSTANTS[0]);
state[1] = state[1].wrapping_add(CONSTANTS[1]);
state[2] = state[2].wrapping_add(CONSTANTS[2]);
state[3] = state[3].wrapping_add(CONSTANTS[3]);
state[4] = state[4].wrapping_add(key[0]);
state[5] = state[5].wrapping_add(key[1]);
state[6] = state[6].wrapping_add(key[2]);
state[7] = state[7].wrapping_add(key[3]);
state[8] = state[8].wrapping_add(key[4]);
state[9] = state[9].wrapping_add(key[5]);
state[10] = state[10].wrapping_add(key[6]);
state[11] = state[11].wrapping_add(key[7]);
state[12] = state[12].wrapping_add((counter & 0xffff_ffff) as u32);
state[13] = state[13].wrapping_add(((counter >> 32) & 0xffff_ffff) as u32);
state[14] = state[14].wrapping_add(iv[0]);
state[15] = state[15].wrapping_add(iv[1]);
state
}
}
#[inline]
pub(crate) fn quarter_round(a: usize, b: usize, c: usize, d: usize, state: &mut [u32; 16]) {
state[a] = state[a].wrapping_add(state[b]);
state[d] ^= state[a];
state[d] = state[d].rotate_left(16);
state[c] = state[c].wrapping_add(state[d]);
state[b] ^= state[c];
state[b] = state[b].rotate_left(12);
state[a] = state[a].wrapping_add(state[b]);
state[d] ^= state[a];
state[d] = state[d].rotate_left(8);
state[c] = state[c].wrapping_add(state[d]);
state[b] ^= state[c];
state[b] = state[b].rotate_left(7);
}