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
15 use core::convert::TryInto;
17 #[derive(Clone, Copy, PartialEq, Eq)]
18 #[allow(non_camel_case_types)]
19 struct u32x4(pub u32, pub u32, pub u32, pub u32);
20 impl ::core::ops::Add for u32x4 {
23 fn add(self, rhs: u32x4) -> u32x4 {
24 u32x4(self.0.wrapping_add(rhs.0),
25 self.1.wrapping_add(rhs.1),
26 self.2.wrapping_add(rhs.2),
27 self.3.wrapping_add(rhs.3))
30 impl ::core::ops::Sub for u32x4 {
33 fn sub(self, rhs: u32x4) -> u32x4 {
34 u32x4(self.0.wrapping_sub(rhs.0),
35 self.1.wrapping_sub(rhs.1),
36 self.2.wrapping_sub(rhs.2),
37 self.3.wrapping_sub(rhs.3))
40 impl ::core::ops::BitXor for u32x4 {
43 fn bitxor(self, rhs: u32x4) -> u32x4 {
44 u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
47 impl ::core::ops::Shr<u8> for u32x4 {
50 fn shr(self, shr: u8) -> u32x4 {
51 u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
54 impl ::core::ops::Shl<u8> for u32x4 {
57 fn shl(self, shl: u8) -> u32x4 {
58 u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
63 fn from_bytes(bytes: &[u8]) -> Self {
64 assert_eq!(bytes.len(), 4*4);
66 u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
67 u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
68 u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
69 u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
74 const BLOCK_SIZE: usize = 64;
87 output : [u8; BLOCK_SIZE],
91 impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
93 macro_rules! swizzle {
94 ($b: expr, $c: expr, $d: expr) => {{
95 let u32x4(b10, b11, b12, b13) = $b;
96 $b = u32x4(b11, b12, b13, b10);
97 let u32x4(c10, c11, c12, c13) = $c;
98 $c = u32x4(c12, c13,c10, c11);
99 let u32x4(d10, d11, d12, d13) = $d;
100 $d = u32x4(d13, d10, d11, d12);
104 macro_rules! state_to_buffer {
105 ($state: expr, $output: expr) => {{
106 let u32x4(a1, a2, a3, a4) = $state.a;
107 let u32x4(b1, b2, b3, b4) = $state.b;
108 let u32x4(c1, c2, c3, c4) = $state.c;
109 let u32x4(d1, d2, d3, d4) = $state.d;
116 for i in 0..lens.len() {
117 $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
124 $state.a = $state.a + $state.b;
125 rotate!($state.d, $state.a, 16);
126 $state.c = $state.c + $state.d;
127 rotate!($state.b, $state.c, 12);
128 $state.a = $state.a + $state.b;
129 rotate!($state.d, $state.a, 8);
130 $state.c = $state.c + $state.d;
131 rotate!($state.b, $state.c, 7);
135 macro_rules! rotate {
136 ($a: expr, $b: expr, $rot: expr) => {{
140 $a = (v << $rot) ^ right
145 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
146 assert!(key.len() == 16 || key.len() == 32);
147 assert!(nonce.len() == 8 || nonce.len() == 12);
149 ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
152 /// Get one block from a ChaCha stream.
153 pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 64] {
154 let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
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;
338 use alloc::vec::{Vec};
339 use core::convert::TryInto;
340 use core::iter::repeat;
345 fn test_chacha20_256_tls_vectors() {
351 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
352 let test_vectors = vec!(
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,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
362 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
363 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
364 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
365 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
366 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
367 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
368 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
369 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
378 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
380 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
381 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
382 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
383 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
384 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
385 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
386 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
387 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
398 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
399 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
400 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
401 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
402 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
403 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
404 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
405 0x44, 0x5f, 0x41, 0xe3,
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,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
416 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
417 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
418 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
419 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
420 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
421 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
422 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
423 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
427 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
428 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
429 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
430 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
432 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
434 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
435 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
436 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
437 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
438 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
439 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
440 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
441 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
442 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
443 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
444 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
445 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
446 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
447 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
448 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
449 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
450 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
451 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
452 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
453 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
454 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
455 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
456 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
457 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
458 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
459 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
460 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
461 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
462 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
463 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
464 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
465 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
470 for tv in test_vectors.iter() {
471 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
472 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
473 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
474 c.process(&input[..], &mut output[..]);
475 assert_eq!(output, tv.keystream);
480 fn test_chacha20_256_tls_vectors_96_nonce() {
486 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
487 let test_vectors = vec!(
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,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
497 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
498 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
499 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
500 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
501 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
502 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
503 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
504 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
513 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
515 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
516 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
517 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
518 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
519 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
520 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
521 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
522 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
533 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
534 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
535 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
536 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
537 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
538 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
539 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
540 0x44, 0x5f, 0x41, 0xe3,
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,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
551 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
552 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
553 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
554 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
555 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
556 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
557 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
558 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
562 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
563 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
564 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
565 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
567 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
569 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
570 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
571 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
572 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
573 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
574 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
575 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
576 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
577 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
578 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
579 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
580 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
581 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
582 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
583 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
584 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
585 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
586 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
587 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
588 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
589 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
590 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
591 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
592 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
593 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
594 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
595 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
596 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
597 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
598 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
599 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
600 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
605 for tv in test_vectors.iter() {
606 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
607 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
608 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
609 c.process(&input[..], &mut output[..]);
610 assert_eq!(output, tv.keystream);
615 fn get_single_block() {
616 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
617 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
620 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
621 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
622 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
623 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
625 let nonce_16bytes = [
626 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
628 let counter_pos = &nonce_16bytes[..4];
629 let nonce_12bytes = &nonce_16bytes[4..];
631 // Initialize a ChaCha20 instance with its counter starting at 0.
632 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
633 // Seek its counter to the block at counter_pos.
634 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
635 let mut block_bytes = [0; 64];
636 chacha20.process_in_place(&mut block_bytes);
638 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
642 fn encrypt_single_block() {
644 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
645 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
646 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
647 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
650 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
651 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
655 let mut encrypted_bytes = [0; 32];
656 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
658 let mut decrypted_bytes = [0; 32];
659 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
661 assert_eq!(bytes, decrypted_bytes);
665 fn encrypt_single_block_in_place() {
667 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
668 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
669 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
670 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
673 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
674 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
676 let unencrypted_bytes = [1; 32];
677 let mut bytes = unencrypted_bytes;
679 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
680 assert_ne!(bytes, unencrypted_bytes);
682 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
683 assert_eq!(bytes, unencrypted_bytes);