qrc_opensource_rs/cipher/
chacha.rs1use crate::tools::intutils::{qrc_intutils_clear32, qrc_intutils_copy8, qrc_intutils_le32to8, qrc_intutils_le8to32, qrc_intutils_rotl32, qrc_intutils_xor};
29
30use core::default::Default;
31
32#[cfg(feature = "no_std")]
33use alloc::vec::Vec;
34
35pub const QRC_CHACHA_BLOCK_SIZE: usize = 64;
40
41pub const QRC_CHACHA_KEY128_SIZE: usize = 16;
46
47pub const QRC_CHACHA_KEY256_SIZE: usize = 32;
52
53pub const QRC_CHACHA_NONCE_SIZE: usize = 8;
58
59pub const QRC_CHACHA_ROUND_COUNT: usize = 20;
64
65#[derive(Clone)]
70pub struct QrcChachaState {
71 pub state: [u32; 16], }
73impl Default for QrcChachaState{
74 fn default() -> Self {
75 Self {
76 state: [Default::default(); 16],
77 }
78 }
79}
80
81#[derive(Clone)]
90pub struct QrcChachaKeyparams {
91 pub key: Vec<u8>, pub keylen: usize, pub nonce: Vec<u8>, }
95impl Default for QrcChachaKeyparams{
96 fn default() -> Self {
97 Self {
98 key: Default::default(),
99 keylen: Default::default(),
100 nonce: Default::default(),
101 }
102 }
103}
104
105pub fn qrc_chacha_dispose(ctx: &mut QrcChachaState) {
114 qrc_intutils_clear32(&mut ctx.state, 16);
115}
116
117pub fn qrc_chacha_initialize(ctx: &mut QrcChachaState, keyparams: QrcChachaKeyparams) {
127 if keyparams.keylen == 32 {
128 ctx.state[0] = 0x61707865;
129 ctx.state[1] = 0x3320646E;
130 ctx.state[2] = 0x79622D32;
131 ctx.state[3] = 0x6B206574;
132 ctx.state[4] = qrc_intutils_le8to32(&keyparams.key);
133 ctx.state[5] = qrc_intutils_le8to32(&keyparams.key[4..]);
134 ctx.state[6] = qrc_intutils_le8to32(&keyparams.key[8..]);
135 ctx.state[7] = qrc_intutils_le8to32(&keyparams.key[12..]);
136 ctx.state[8] = qrc_intutils_le8to32(&keyparams.key[16..]);
137 ctx.state[9] = qrc_intutils_le8to32(&keyparams.key[20..]);
138 ctx.state[10] = qrc_intutils_le8to32(&keyparams.key[24..]);
139 ctx.state[11] = qrc_intutils_le8to32(&keyparams.key[28..]);
140 ctx.state[12] = 0;
141 ctx.state[13] = 0;
142 ctx.state[14] = qrc_intutils_le8to32(&keyparams.nonce);
143 ctx.state[15] = qrc_intutils_le8to32(&keyparams.nonce[4..]);
144 } else {
145 ctx.state[0] = 0x61707865;
146 ctx.state[1] = 0x3120646E;
147 ctx.state[2] = 0x79622D36;
148 ctx.state[3] = 0x6B206574;
149 ctx.state[4] = qrc_intutils_le8to32(&keyparams.key[0..]);
150 ctx.state[5] = qrc_intutils_le8to32(&keyparams.key[4..]);
151 ctx.state[6] = qrc_intutils_le8to32(&keyparams.key[8..]);
152 ctx.state[7] = qrc_intutils_le8to32(&keyparams.key[12..]);
153 ctx.state[8] = qrc_intutils_le8to32(&keyparams.key[0..]);
154 ctx.state[9] = qrc_intutils_le8to32(&keyparams.key[4..]);
155 ctx.state[10] = qrc_intutils_le8to32(&keyparams.key[8..]);
156 ctx.state[11] = qrc_intutils_le8to32(&keyparams.key[12..]);
157 ctx.state[12] = 0;
158 ctx.state[13] = 0;
159 ctx.state[14] = qrc_intutils_le8to32(&keyparams.nonce);
160 ctx.state[15] = qrc_intutils_le8to32(&keyparams.nonce[4..]);
161 }
162}
163
164pub fn qrc_chacha_transform(ctx: &mut QrcChachaState, output: &mut [u8], input: &[u8], mut length: usize) {
173 let mut oft = 0;
174
175 if length != 0 {
176 while length >= QRC_CHACHA_BLOCK_SIZE {
177 chacha_permute_p512c(ctx.clone(), &mut output[oft..]);
178 chacha_increment(ctx);
179 qrc_intutils_xor(&mut output[oft..], &input[oft..], QRC_CHACHA_BLOCK_SIZE);
180 oft += QRC_CHACHA_BLOCK_SIZE;
181 length -= QRC_CHACHA_BLOCK_SIZE;
182 }
183
184 if length != 0 {
185 let tmp = &mut [0u8; QRC_CHACHA_BLOCK_SIZE];
186 chacha_permute_p512c(ctx.clone(), tmp);
187 chacha_increment(ctx);
188 qrc_intutils_copy8(&mut output[oft..], tmp, length);
189
190 for i in oft..oft + length {
191 output[i] ^= input[i];
192 }
193 }
194 }
195}
196
197fn chacha_increment(ctx: &mut QrcChachaState) {
200 ctx.state[12] = ctx.state[12].wrapping_add(1);
201
202 if ctx.state[12] == 0 {
203 ctx.state[13] = ctx.state[13].wrapping_add(1);
204 }
205}
206
207fn chacha_permute_p512c(ctx: QrcChachaState, output: &mut [u8]) {
208 let mut x0 = ctx.state[0];
209 let mut x1 = ctx.state[1];
210 let mut x2 = ctx.state[2];
211 let mut x3 = ctx.state[3];
212 let mut x4 = ctx.state[4];
213 let mut x5 = ctx.state[5];
214 let mut x6 = ctx.state[6];
215 let mut x7 = ctx.state[7];
216 let mut x8 = ctx.state[8];
217 let mut x9 = ctx.state[9];
218 let mut x10 = ctx.state[10];
219 let mut x11 = ctx.state[11];
220 let mut x12 = ctx.state[12];
221 let mut x13 = ctx.state[13];
222 let mut x14 = ctx.state[14];
223 let mut x15 = ctx.state[15];
224 let mut ctr = QRC_CHACHA_ROUND_COUNT;
225
226 while ctr != 0 {
227 x0 = x0.wrapping_add(x4);
228 x12 = qrc_intutils_rotl32(x12 ^ x0, 16);
229 x8 = x8.wrapping_add(x12);
230 x4 = qrc_intutils_rotl32(x4 ^ x8, 12);
231 x0 = x0.wrapping_add(x4);
232 x12 = qrc_intutils_rotl32(x12 ^ x0, 8);
233 x8 = x8.wrapping_add(x12);
234 x4 = qrc_intutils_rotl32(x4 ^ x8, 7);
235 x1 = x1.wrapping_add(x5);
236 x13 = qrc_intutils_rotl32(x13 ^ x1, 16);
237 x9 = x9.wrapping_add(x13);
238 x5 = qrc_intutils_rotl32(x5 ^ x9, 12);
239 x1 = x1.wrapping_add(x5);
240 x13 = qrc_intutils_rotl32(x13 ^ x1, 8);
241 x9 = x9.wrapping_add(x13);
242 x5 = qrc_intutils_rotl32(x5 ^ x9, 7);
243 x2 = x2.wrapping_add(x6);
244 x14 = qrc_intutils_rotl32(x14 ^ x2, 16);
245 x10 = x10.wrapping_add(x14);
246 x6 = qrc_intutils_rotl32(x6 ^ x10, 12);
247 x2 = x2.wrapping_add(x6);
248 x14 = qrc_intutils_rotl32(x14 ^ x2, 8);
249 x10 = x10.wrapping_add(x14);
250 x6 = qrc_intutils_rotl32(x6 ^ x10, 7);
251 x3 = x3.wrapping_add(x7);
252 x15 = qrc_intutils_rotl32(x15 ^ x3, 16);
253 x11 = x11.wrapping_add(x15);
254 x7 = qrc_intutils_rotl32(x7 ^ x11, 12);
255 x3 = x3.wrapping_add(x7);
256 x15 = qrc_intutils_rotl32(x15 ^ x3, 8);
257 x11 = x11.wrapping_add(x15);
258 x7 = qrc_intutils_rotl32(x7 ^ x11, 7);
259 x0 = x0.wrapping_add(x5);
260 x15 = qrc_intutils_rotl32(x15 ^ x0, 16);
261 x10 = x10.wrapping_add(x15);
262 x5 = qrc_intutils_rotl32(x5 ^ x10, 12);
263 x0 = x0.wrapping_add(x5);
264 x15 = qrc_intutils_rotl32(x15 ^ x0, 8);
265 x10 = x10.wrapping_add(x15);
266 x5 = qrc_intutils_rotl32(x5 ^ x10, 7);
267 x1 = x1.wrapping_add(x6);
268 x12 = qrc_intutils_rotl32(x12 ^ x1, 16);
269 x11 = x11.wrapping_add(x12);
270 x6 = qrc_intutils_rotl32(x6 ^ x11, 12);
271 x1 = x1.wrapping_add(x6);
272 x12 = qrc_intutils_rotl32(x12 ^ x1, 8);
273 x11 = x11.wrapping_add(x12);
274 x6 = qrc_intutils_rotl32(x6 ^ x11, 7);
275 x2 = x2.wrapping_add(x7);
276 x13 = qrc_intutils_rotl32(x13 ^ x2, 16);
277 x8 = x8.wrapping_add(x13);
278 x7 = qrc_intutils_rotl32(x7 ^ x8, 12);
279 x2 = x2.wrapping_add(x7);
280 x13 = qrc_intutils_rotl32(x13 ^ x2, 8);
281 x8 = x8.wrapping_add(x13);
282 x7 = qrc_intutils_rotl32(x7 ^ x8, 7);
283 x3 = x3.wrapping_add(x4);
284 x14 = qrc_intutils_rotl32(x14 ^ x3, 16);
285 x9 = x9.wrapping_add(x14);
286 x4 = qrc_intutils_rotl32(x4 ^ x9, 12);
287 x3 = x3.wrapping_add(x4);
288 x14 = qrc_intutils_rotl32(x14 ^ x3, 8);
289 x9 = x9.wrapping_add(x14);
290 x4 = qrc_intutils_rotl32(x4 ^ x9, 7);
291 ctr -= 2;
292 }
293
294 qrc_intutils_le32to8(output, x0.wrapping_add(ctx.state[0]));
295 qrc_intutils_le32to8(&mut output[4..], x1.wrapping_add(ctx.state[1]));
296 qrc_intutils_le32to8(&mut output[8..], x2.wrapping_add(ctx.state[2]));
297 qrc_intutils_le32to8(&mut output[12..], x3.wrapping_add(ctx.state[3]));
298 qrc_intutils_le32to8(&mut output[16..], x4.wrapping_add(ctx.state[4]));
299 qrc_intutils_le32to8(&mut output[20..], x5.wrapping_add(ctx.state[5]));
300 qrc_intutils_le32to8(&mut output[24..], x6.wrapping_add(ctx.state[6]));
301 qrc_intutils_le32to8(&mut output[28..], x7.wrapping_add(ctx.state[7]));
302 qrc_intutils_le32to8(&mut output[32..], x8.wrapping_add(ctx.state[8]));
303 qrc_intutils_le32to8(&mut output[36..], x9.wrapping_add(ctx.state[9]));
304 qrc_intutils_le32to8(&mut output[40..], x10.wrapping_add(ctx.state[10]));
305 qrc_intutils_le32to8(&mut output[44..], x11.wrapping_add(ctx.state[11]));
306 qrc_intutils_le32to8(&mut output[48..], x12.wrapping_add(ctx.state[12]));
307 qrc_intutils_le32to8(&mut output[52..], x13.wrapping_add(ctx.state[13]));
308 qrc_intutils_le32to8(&mut output[56..], x14.wrapping_add(ctx.state[14]));
309 qrc_intutils_le32to8(&mut output[60..], x15.wrapping_add(ctx.state[15]));
310}