1 // This file was stolen from rust-crypto.
2 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
3 // file at the top-level directory of this distribution and at
4 // http://rust-lang.org/COPYRIGHT.
6 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9 // You may not use this file except in accordance with one or both of these
16 #[derive(Clone, Copy, PartialEq, Eq)]
17 #[allow(non_camel_case_types)]
18 struct u32x4(pub u32, pub u32, pub u32, pub u32);
19 impl ::core::ops::Add for u32x4 {
22 fn add(self, rhs: u32x4) -> u32x4 {
23 u32x4(self.0.wrapping_add(rhs.0),
24 self.1.wrapping_add(rhs.1),
25 self.2.wrapping_add(rhs.2),
26 self.3.wrapping_add(rhs.3))
29 impl ::core::ops::Sub for u32x4 {
32 fn sub(self, rhs: u32x4) -> u32x4 {
33 u32x4(self.0.wrapping_sub(rhs.0),
34 self.1.wrapping_sub(rhs.1),
35 self.2.wrapping_sub(rhs.2),
36 self.3.wrapping_sub(rhs.3))
39 impl ::core::ops::BitXor for u32x4 {
42 fn bitxor(self, rhs: u32x4) -> u32x4 {
43 u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
46 impl ::core::ops::Shr<u8> for u32x4 {
49 fn shr(self, shr: u8) -> u32x4 {
50 u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
53 impl ::core::ops::Shl<u8> for u32x4 {
56 fn shl(self, shl: u8) -> u32x4 {
57 u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
62 fn from_bytes(bytes: &[u8]) -> Self {
63 assert_eq!(bytes.len(), 4*4);
65 u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
66 u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
67 u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
68 u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
73 const BLOCK_SIZE: usize = 64;
86 output : [u8; BLOCK_SIZE],
90 impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
92 macro_rules! swizzle {
93 ($b: expr, $c: expr, $d: expr) => {{
94 let u32x4(b10, b11, b12, b13) = $b;
95 $b = u32x4(b11, b12, b13, b10);
96 let u32x4(c10, c11, c12, c13) = $c;
97 $c = u32x4(c12, c13,c10, c11);
98 let u32x4(d10, d11, d12, d13) = $d;
99 $d = u32x4(d13, d10, d11, d12);
103 macro_rules! state_to_buffer {
104 ($state: expr, $output: expr) => {{
105 let u32x4(a1, a2, a3, a4) = $state.a;
106 let u32x4(b1, b2, b3, b4) = $state.b;
107 let u32x4(c1, c2, c3, c4) = $state.c;
108 let u32x4(d1, d2, d3, d4) = $state.d;
115 for i in 0..lens.len() {
116 $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
123 $state.a = $state.a + $state.b;
124 rotate!($state.d, $state.a, 16);
125 $state.c = $state.c + $state.d;
126 rotate!($state.b, $state.c, 12);
127 $state.a = $state.a + $state.b;
128 rotate!($state.d, $state.a, 8);
129 $state.c = $state.c + $state.d;
130 rotate!($state.b, $state.c, 7);
134 macro_rules! rotate {
135 ($a: expr, $b: expr, $rot: expr) => {{
139 $a = (v << $rot) ^ right
144 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
145 assert!(key.len() == 16 || key.len() == 32);
146 assert!(nonce.len() == 8 || nonce.len() == 12);
148 ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
151 /// Get one block from a ChaCha stream.
152 pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
153 let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
154 let mut chacha_bytes = [0; 32];
155 chacha.process_in_place(&mut chacha_bytes);
159 /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
160 /// `src` in a second call will decrypt it.
161 pub fn encrypt_single_block(
162 key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
164 debug_assert_eq!(dest.len(), src.len());
165 debug_assert!(dest.len() <= 32);
167 let block = ChaCha20::get_single_block(key, nonce);
168 for i in 0..dest.len() {
169 dest[i] = block[i] ^ src[i];
173 /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
174 pub fn encrypt_single_block_in_place(
175 key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
177 let block = ChaCha20::get_single_block(key, nonce);
178 for i in 0..bytes.len() {
179 bytes[i] = block[i] ^ bytes[i];
183 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
184 let constant = match key.len() {
185 16 => b"expand 16-byte k",
186 32 => b"expand 32-byte k",
190 a: u32x4::from_bytes(&constant[0..16]),
191 b: u32x4::from_bytes(&key[0..16]),
192 c: if key.len() == 16 {
193 u32x4::from_bytes(&key[0..16])
195 u32x4::from_bytes(&key[16..32])
197 d: if nonce.len() == 16 {
198 u32x4::from_bytes(&nonce[0..16])
199 } else if nonce.len() == 12 {
200 let mut nonce4 = [0; 4*4];
201 nonce4[4..].copy_from_slice(nonce);
202 u32x4::from_bytes(&nonce4)
204 let mut nonce4 = [0; 4*4];
205 nonce4[8..].copy_from_slice(nonce);
206 u32x4::from_bytes(&nonce4)
211 // put the the next BLOCK_SIZE keystream bytes into self.output
212 fn update(&mut self) {
213 let mut state = self.state;
217 swizzle!(state.b, state.c, state.d);
219 swizzle!(state.d, state.c, state.b);
221 state.a = state.a + self.state.a;
222 state.b = state.b + self.state.b;
223 state.c = state.c + self.state.c;
224 state.d = state.d + self.state.d;
226 state_to_buffer!(state, self.output);
228 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
229 let u32x4(c12, _, _, _) = self.state.d;
231 // we could increment the other counter word with an 8 byte nonce
232 // but other implementations like boringssl have this same
234 panic!("counter is exhausted");
240 #[inline] // Useful cause input may be 0s on stack that should be optimized out
241 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
242 assert!(input.len() == output.len());
243 let len = input.len();
246 // If there is no keystream available in the output buffer,
247 // generate the next block.
248 if self.offset == BLOCK_SIZE {
252 // Process the min(available keystream, remaining input length).
253 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
254 // explicitly assert lengths to avoid bounds checks:
255 assert!(output.len() >= i + count);
256 assert!(input.len() >= i + count);
257 assert!(self.output.len() >= self.offset + count);
259 output[i + j] = input[i + j] ^ self.output[self.offset + j];
262 self.offset += count;
266 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
267 let len = input_output.len();
270 // If there is no keystream available in the output buffer,
271 // generate the next block.
272 if self.offset == BLOCK_SIZE {
276 // Process the min(available keystream, remaining input length).
277 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
278 // explicitly assert lengths to avoid bounds checks:
279 assert!(input_output.len() >= i + count);
280 assert!(self.output.len() >= self.offset + count);
282 input_output[i + j] ^= self.output[self.offset + j];
285 self.offset += count;
290 pub fn seek_to_block(&mut self, block_offset: u32) {
291 self.state.d.0 = block_offset;
297 pub use self::real_chacha::ChaCha20;
301 pub struct ChaCha20 {}
304 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
305 assert!(key.len() == 16 || key.len() == 32);
306 assert!(nonce.len() == 8 || nonce.len() == 12);
310 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
314 pub fn encrypt_single_block(
315 _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
317 debug_assert_eq!(dest.len(), src.len());
318 debug_assert!(dest.len() <= 32);
321 pub fn encrypt_single_block_in_place(
322 _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
325 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
326 output.copy_from_slice(input);
329 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
333 pub use self::fuzzy_chacha::ChaCha20;
337 use core::iter::repeat;
339 use crate::prelude::*;
344 fn test_chacha20_256_tls_vectors() {
350 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
351 let test_vectors = vec!(
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
361 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
362 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
363 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
364 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
365 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
366 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
367 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
368 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
377 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
379 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
380 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
381 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
382 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
383 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
384 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
385 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
386 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
397 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
398 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
399 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
400 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
401 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
402 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
403 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
404 0x44, 0x5f, 0x41, 0xe3,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
415 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
416 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
417 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
418 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
419 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
420 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
421 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
422 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
426 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
427 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
428 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
429 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
431 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
433 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
434 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
435 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
436 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
437 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
438 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
439 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
440 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
441 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
442 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
443 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
444 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
445 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
446 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
447 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
448 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
449 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
450 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
451 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
452 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
453 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
454 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
455 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
456 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
457 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
458 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
459 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
460 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
461 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
462 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
463 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
464 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
469 for tv in test_vectors.iter() {
470 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
471 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
472 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
473 c.process(&input[..], &mut output[..]);
474 assert_eq!(output, tv.keystream);
479 fn test_chacha20_256_tls_vectors_96_nonce() {
485 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
486 let test_vectors = vec!(
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, 0x00,
494 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
496 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
497 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
498 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
499 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
500 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
501 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
502 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
503 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x01,
512 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
514 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
515 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
516 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
517 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
518 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
519 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
520 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
521 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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,
530 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
532 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
533 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
534 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
535 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
536 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
537 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
538 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
539 0x44, 0x5f, 0x41, 0xe3,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
550 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
551 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
552 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
553 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
554 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
555 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
556 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
557 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
561 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
562 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
563 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
564 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
566 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
568 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
569 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
570 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
571 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
572 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
573 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
574 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
575 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
576 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
577 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
578 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
579 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
580 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
581 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
582 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
583 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
584 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
585 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
586 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
587 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
588 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
589 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
590 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
591 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
592 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
593 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
594 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
595 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
596 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
597 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
598 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
599 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
604 for tv in test_vectors.iter() {
605 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
606 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
607 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
608 c.process(&input[..], &mut output[..]);
609 assert_eq!(output, tv.keystream);
614 fn get_single_block() {
615 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
616 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
619 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
620 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
621 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
622 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
624 let nonce_16bytes = [
625 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
627 let counter_pos = &nonce_16bytes[..4];
628 let nonce_12bytes = &nonce_16bytes[4..];
630 // Initialize a ChaCha20 instance with its counter starting at 0.
631 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
632 // Seek its counter to the block at counter_pos.
633 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
634 let mut block_bytes = [0; 32];
635 chacha20.process_in_place(&mut block_bytes);
637 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
641 fn encrypt_single_block() {
643 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
644 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
645 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
646 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
649 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
650 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
654 let mut encrypted_bytes = [0; 32];
655 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
657 let mut decrypted_bytes = [0; 32];
658 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
660 assert_eq!(bytes, decrypted_bytes);
664 fn encrypt_single_block_in_place() {
666 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
667 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
668 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
669 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
672 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
673 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
675 let unencrypted_bytes = [1; 32];
676 let mut bytes = unencrypted_bytes;
678 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
679 assert_ne!(bytes, unencrypted_bytes);
681 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
682 assert_eq!(bytes, unencrypted_bytes);