1use std::cmp;
7
8use buffer::{BufferResult, RefReadBuffer, RefWriteBuffer};
9use symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher, SymmetricCipherError};
10use cryptoutil::{read_u32_le, symm_enc_or_dec, write_u32_le, xor_keystream};
11use simd::u32x4;
12
13#[derive(Clone,Copy)]
14struct ChaChaState {
15 a: u32x4,
16 b: u32x4,
17 c: u32x4,
18 d: u32x4
19}
20
21#[derive(Copy)]
22pub struct ChaCha20 {
23 state : ChaChaState,
24 output : [u8; 64],
25 offset : usize,
26}
27
28impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
29
30macro_rules! swizzle{
31 ($b: expr, $c: expr, $d: expr) => {{
32 let u32x4(b10, b11, b12, b13) = $b;
33 $b = u32x4(b11, b12, b13, b10);
34 let u32x4(c10, c11, c12, c13) = $c;
35 $c = u32x4(c12, c13,c10, c11);
36 let u32x4(d10, d11, d12, d13) = $d;
37 $d = u32x4(d13, d10, d11, d12);
38 }}
39}
40
41macro_rules! state_to_buffer {
42 ($state: expr, $output: expr) => {{
43 let u32x4(a1, a2, a3, a4) = $state.a;
44 let u32x4(b1, b2, b3, b4) = $state.b;
45 let u32x4(c1, c2, c3, c4) = $state.c;
46 let u32x4(d1, d2, d3, d4) = $state.d;
47 let lens = [
48 a1,a2,a3,a4,
49 b1,b2,b3,b4,
50 c1,c2,c3,c4,
51 d1,d2,d3,d4
52 ];
53 for i in 0..lens.len() {
54 write_u32_le(&mut $output[i*4..(i+1)*4], lens[i]);
55 }
56 }}
57}
58
59macro_rules! round{
60 ($state: expr) => {{
61 $state.a = $state.a + $state.b;
62 rotate!($state.d, $state.a, S16);
63 $state.c = $state.c + $state.d;
64 rotate!($state.b, $state.c, S12);
65 $state.a = $state.a + $state.b;
66 rotate!($state.d, $state.a, S8);
67 $state.c = $state.c + $state.d;
68 rotate!($state.b, $state.c, S7);
69 }}
70}
71
72macro_rules! rotate {
73 ($a: expr, $b: expr, $c:expr) => {{
74 let v = $a ^ $b;
75 let r = S32 - $c;
76 let right = v >> r;
77 $a = (v << $c) ^ right
78 }}
79}
80
81static S32:u32x4 = u32x4(32, 32, 32, 32);
82static S16:u32x4 = u32x4(16, 16, 16, 16);
83static S12:u32x4 = u32x4(12, 12, 12, 12);
84static S8:u32x4 = u32x4(8, 8, 8, 8);
85static S7:u32x4 = u32x4(7, 7, 7, 7);
86
87impl ChaCha20 {
88 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
89 assert!(key.len() == 16 || key.len() == 32);
90 assert!(nonce.len() == 8 || nonce.len() == 12);
91
92 ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; 64], offset: 64 }
93 }
94
95 pub fn new_xchacha20(key: &[u8], nonce: &[u8]) -> ChaCha20 {
96 assert!(key.len() == 32);
97 assert!(nonce.len() == 24);
98
99 let mut xchacha20 = ChaCha20{ state: ChaCha20::expand(key, &nonce[0..16]), output: [0u8; 64], offset: 64 };
106
107 let mut new_key = [0; 32];
110 xchacha20.hchacha20(&mut new_key);
111 xchacha20.state = ChaCha20::expand(&new_key, &nonce[16..24]);
112
113 xchacha20
114 }
115
116 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
117
118 let constant = match key.len() {
119 16 => b"expand 16-byte k",
120 32 => b"expand 32-byte k",
121 _ => unreachable!(),
122 };
123 ChaChaState {
124 a: u32x4(
125 read_u32_le(&constant[0..4]),
126 read_u32_le(&constant[4..8]),
127 read_u32_le(&constant[8..12]),
128 read_u32_le(&constant[12..16])
129 ),
130 b: u32x4(
131 read_u32_le(&key[0..4]),
132 read_u32_le(&key[4..8]),
133 read_u32_le(&key[8..12]),
134 read_u32_le(&key[12..16])
135 ),
136 c: if key.len() == 16 {
137 u32x4(
138 read_u32_le(&key[0..4]),
139 read_u32_le(&key[4..8]),
140 read_u32_le(&key[8..12]),
141 read_u32_le(&key[12..16])
142 )
143 } else {
144 u32x4(
145 read_u32_le(&key[16..20]),
146 read_u32_le(&key[20..24]),
147 read_u32_le(&key[24..28]),
148 read_u32_le(&key[28..32])
149 )
150 },
151 d: if nonce.len() == 16 {
152 u32x4(
153 read_u32_le(&nonce[0..4]),
154 read_u32_le(&nonce[4..8]),
155 read_u32_le(&nonce[8..12]),
156 read_u32_le(&nonce[12..16])
157 )
158 } else if nonce.len() == 12 {
159 u32x4(
160 0,
161 read_u32_le(&nonce[0..4]),
162 read_u32_le(&nonce[4..8]),
163 read_u32_le(&nonce[8..12])
164 )
165 } else {
166 u32x4(
167 0,
168 0,
169 read_u32_le(&nonce[0..4]),
170 read_u32_le(&nonce[4..8])
171 )
172 }
173 }
174 }
175
176 fn hchacha20(&mut self, out: &mut [u8]) -> () {
177 let mut state = self.state;
178
179 for _ in 0..10 {
182 round!(state);
183 let u32x4(b10, b11, b12, b13) = state.b;
184 state.b = u32x4(b11, b12, b13, b10);
185 let u32x4(c10, c11, c12, c13) = state.c;
186 state.c = u32x4(c12, c13,c10, c11);
187 let u32x4(d10, d11, d12, d13) = state.d;
188 state.d = u32x4(d13, d10, d11, d12);
189 round!(state);
190 let u32x4(b20, b21, b22, b23) = state.b;
191 state.b = u32x4(b23, b20, b21, b22);
192 let u32x4(c20, c21, c22, c23) = state.c;
193 state.c = u32x4(c22, c23, c20, c21);
194 let u32x4(d20, d21, d22, d23) = state.d;
195 state.d = u32x4(d21, d22, d23, d20);
196 }
197
198 let u32x4(a1, a2, a3, a4) = state.a;
202 let u32x4(d1, d2, d3, d4) = state.d;
203 let lens = [
204 a1,a2,a3,a4,
205 d1,d2,d3,d4
206 ];
207 for i in 0..lens.len() {
208 write_u32_le(&mut out[i*4..(i+1)*4], lens[i]);
209 }
210 }
211
212 fn update(&mut self) {
214 let mut state = self.state;
215
216 for _ in 0..10 {
217 round!(state);
218 swizzle!(state.b, state.c, state.d);
219 round!(state);
220 swizzle!(state.d, state.c, state.b);
221 }
222 state.a = state.a + self.state.a;
223 state.b = state.b + self.state.b;
224 state.c = state.c + self.state.c;
225 state.d = state.d + self.state.d;
226
227 state_to_buffer!(state, self.output);
228
229 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
230 let u32x4(c12, _, _, _) = self.state.d;
231 if c12 == 0 {
232 panic!("counter is exhausted");
236 }
237
238 self.offset = 0;
239 }
240}
241
242impl SynchronousStreamCipher for ChaCha20 {
243 fn process(&mut self, input: &[u8], output: &mut [u8]) {
244 assert!(input.len() == output.len());
245 let len = input.len();
246 let mut i = 0;
247 while i < len {
248 if self.offset == 64 {
251 self.update();
252 }
253
254 let count = cmp::min(64 - self.offset, len - i);
256 xor_keystream(&mut output[i..i+count], &input[i..i+count], &self.output[self.offset..]);
257 i += count;
258 self.offset += count;
259 }
260 }
261}
262
263impl Encryptor for ChaCha20 {
264 fn encrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
265 -> Result<BufferResult, SymmetricCipherError> {
266 symm_enc_or_dec(self, input, output)
267 }
268}
269
270impl Decryptor for ChaCha20 {
271 fn decrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
272 -> Result<BufferResult, SymmetricCipherError> {
273 symm_enc_or_dec(self, input, output)
274 }
275}
276
277#[cfg(test)]
278mod test {
279 use std::iter::repeat;
280
281 use chacha20::ChaCha20;
282 use symmetriccipher::SynchronousStreamCipher;
283
284 #[test]
285 fn test_chacha20_256_tls_vectors() {
286 struct TestVector {
287 key: [u8; 32],
288 nonce: [u8; 8],
289 keystream: Vec<u8>,
290 };
291 let test_vectors = vec!(
293 TestVector{
294 key: [
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 ],
300 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
301 keystream: vec!(
302 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
303 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
304 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
305 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
306 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
307 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
308 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
309 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
310 ),
311 }, TestVector{
312 key: [
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
317 ],
318 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
319 keystream: vec!(
320 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
321 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
322 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
323 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
324 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
325 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
326 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
327 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
328 ),
329 }, TestVector{
330 key: [
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 ],
336 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
337 keystream: vec!(
338 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
339 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
340 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
341 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
342 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
343 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
344 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
345 0x44, 0x5f, 0x41, 0xe3,
346 ),
347 }, TestVector{
348 key: [
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 ],
354 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
355 keystream: vec!(
356 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
357 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
358 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
359 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
360 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
361 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
362 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
363 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
364 ),
365 }, TestVector{
366 key: [
367 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
368 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
369 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
370 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
371 ],
372 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
373 keystream: vec!(
374 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
375 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
376 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
377 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
378 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
379 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
380 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
381 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
382 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
383 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
384 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
385 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
386 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
387 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
388 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
389 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
390 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
391 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
392 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
393 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
394 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
395 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
396 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
397 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
398 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
399 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
400 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
401 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
402 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
403 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
404 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
405 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
406 ),
407 },
408 );
409
410 for tv in test_vectors.iter() {
411 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
412 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
413 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
414 c.process(&input[..], &mut output[..]);
415 assert_eq!(output, tv.keystream);
416 }
417 }
418
419 #[test]
420 fn test_xchacha20_basic() {
421 let key =
425 [0x1b, 0x27, 0x55, 0x64, 0x73, 0xe9, 0x85, 0xd4,
426 0x62, 0xcd, 0x51, 0x19, 0x7a, 0x9a, 0x46, 0xc7,
427 0x60, 0x09, 0x54, 0x9e, 0xac, 0x64, 0x74, 0xf2,
428 0x06, 0xc4, 0xee, 0x08, 0x44, 0xf6, 0x83, 0x89];
429 let nonce =
430 [0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73,
431 0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6,
432 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37];
433 let input = [0u8; 139];
434 let mut stream = [0u8; 139];
435 let result =
436 [0x4f, 0xeb, 0xf2, 0xfe, 0x4b, 0x35, 0x9c, 0x50,
437 0x8d, 0xc5, 0xe8, 0xb5, 0x98, 0x0c, 0x88, 0xe3,
438 0x89, 0x46, 0xd8, 0xf1, 0x8f, 0x31, 0x34, 0x65,
439 0xc8, 0x62, 0xa0, 0x87, 0x82, 0x64, 0x82, 0x48,
440 0x01, 0x8d, 0xac, 0xdc, 0xb9, 0x04, 0x17, 0x88,
441 0x53, 0xa4, 0x6d, 0xca, 0x3a, 0x0e, 0xaa, 0xee,
442 0x74, 0x7c, 0xba, 0x97, 0x43, 0x4e, 0xaf, 0xfa,
443 0xd5, 0x8f, 0xea, 0x82, 0x22, 0x04, 0x7e, 0x0d,
444 0xe6, 0xc3, 0xa6, 0x77, 0x51, 0x06, 0xe0, 0x33,
445 0x1a, 0xd7, 0x14, 0xd2, 0xf2, 0x7a, 0x55, 0x64,
446 0x13, 0x40, 0xa1, 0xf1, 0xdd, 0x9f, 0x94, 0x53,
447 0x2e, 0x68, 0xcb, 0x24, 0x1c, 0xbd, 0xd1, 0x50,
448 0x97, 0x0d, 0x14, 0xe0, 0x5c, 0x5b, 0x17, 0x31,
449 0x93, 0xfb, 0x14, 0xf5, 0x1c, 0x41, 0xf3, 0x93,
450 0x83, 0x5b, 0xf7, 0xf4, 0x16, 0xa7, 0xe0, 0xbb,
451 0xa8, 0x1f, 0xfb, 0x8b, 0x13, 0xaf, 0x0e, 0x21,
452 0x69, 0x1d, 0x7e, 0xce, 0xc9, 0x3b, 0x75, 0xe6,
453 0xe4, 0x18, 0x3a];
454
455 let mut xchacha20 = ChaCha20::new_xchacha20(&key, &nonce);
456 xchacha20.process(&input, &mut stream);
457 assert!(stream[..] == result[..]);
458 }
459
460 #[test]
461 fn test_chacha20_256_tls_vectors_96_nonce() {
462 struct TestVector {
463 key: [u8; 32],
464 nonce: [u8; 12],
465 keystream: Vec<u8>,
466 };
467 let test_vectors = vec!(
469 TestVector{
470 key: [
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 ],
476 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
477 keystream: vec!(
478 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
479 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
480 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
481 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
482 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
483 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
484 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
485 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
486 ),
487 }, TestVector{
488 key: [
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
493 ],
494 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
495 keystream: vec!(
496 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
497 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
498 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
499 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
500 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
501 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
502 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
503 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
504 ),
505 }, TestVector{
506 key: [
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 ],
512 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
513 keystream: vec!(
514 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
515 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
516 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
517 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
518 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
519 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
520 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
521 0x44, 0x5f, 0x41, 0xe3,
522 ),
523 }, TestVector{
524 key: [
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 ],
530 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
531 keystream: vec!(
532 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
533 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
534 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
535 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
536 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
537 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
538 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
539 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
540 ),
541 }, TestVector{
542 key: [
543 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
544 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
545 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
546 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
547 ],
548 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
549 keystream: vec!(
550 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
551 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
552 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
553 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
554 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
555 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
556 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
557 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
558 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
559 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
560 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
561 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
562 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
563 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
564 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
565 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
566 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
567 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
568 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
569 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
570 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
571 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
572 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
573 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
574 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
575 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
576 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
577 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
578 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
579 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
580 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
581 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
582 ),
583 },
584 );
585
586 for tv in test_vectors.iter() {
587 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
588 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
589 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
590 c.process(&input[..], &mut output[..]);
591 assert_eq!(output, tv.keystream);
592 }
593 }
594}
595
596#[cfg(all(test, feature = "with-bench"))]
597mod bench {
598 use test::Bencher;
599 use symmetriccipher::SynchronousStreamCipher;
600 use chacha20::ChaCha20;
601
602 #[bench]
603 pub fn chacha20_10(bh: & mut Bencher) {
604 let mut chacha20 = ChaCha20::new(&[0; 32], &[0; 8]);
605 let input = [1u8; 10];
606 let mut output = [0u8; 10];
607 bh.iter( || {
608 chacha20.process(&input, &mut output);
609 });
610 bh.bytes = input.len() as u64;
611 }
612
613 #[bench]
614 pub fn chacha20_1k(bh: & mut Bencher) {
615 let mut chacha20 = ChaCha20::new(&[0; 32], &[0; 8]);
616 let input = [1u8; 1024];
617 let mut output = [0u8; 1024];
618 bh.iter( || {
619 chacha20.process(&input, &mut output);
620 });
621 bh.bytes = input.len() as u64;
622 }
623
624 #[bench]
625 pub fn chacha20_64k(bh: & mut Bencher) {
626 let mut chacha20 = ChaCha20::new(&[0; 32], &[0; 8]);
627 let input = [1u8; 65536];
628 let mut output = [0u8; 65536];
629 bh.iter( || {
630 chacha20.process(&input, &mut output);
631 });
632 bh.bytes = input.len() as u64;
633 }
634}