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; 32] {
154 let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
155 let mut chacha_bytes = [0; 32];
156 chacha.process_in_place(&mut chacha_bytes);
160 /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
161 /// `src` in a second call will decrypt it.
162 pub fn encrypt_single_block(
163 key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
165 debug_assert_eq!(dest.len(), src.len());
166 debug_assert!(dest.len() <= 32);
168 let block = ChaCha20::get_single_block(key, nonce);
169 for i in 0..dest.len() {
170 dest[i] = block[i] ^ src[i];
174 /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
175 pub fn encrypt_single_block_in_place(
176 key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
178 let block = ChaCha20::get_single_block(key, nonce);
179 for i in 0..bytes.len() {
180 bytes[i] = block[i] ^ bytes[i];
184 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
185 let constant = match key.len() {
186 16 => b"expand 16-byte k",
187 32 => b"expand 32-byte k",
191 a: u32x4::from_bytes(&constant[0..16]),
192 b: u32x4::from_bytes(&key[0..16]),
193 c: if key.len() == 16 {
194 u32x4::from_bytes(&key[0..16])
196 u32x4::from_bytes(&key[16..32])
198 d: if nonce.len() == 16 {
199 u32x4::from_bytes(&nonce[0..16])
200 } else if nonce.len() == 12 {
201 let mut nonce4 = [0; 4*4];
202 nonce4[4..].copy_from_slice(nonce);
203 u32x4::from_bytes(&nonce4)
205 let mut nonce4 = [0; 4*4];
206 nonce4[8..].copy_from_slice(nonce);
207 u32x4::from_bytes(&nonce4)
212 // put the the next BLOCK_SIZE keystream bytes into self.output
213 fn update(&mut self) {
214 let mut state = self.state;
218 swizzle!(state.b, state.c, state.d);
220 swizzle!(state.d, state.c, state.b);
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;
227 state_to_buffer!(state, self.output);
229 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
230 let u32x4(c12, _, _, _) = self.state.d;
232 // we could increment the other counter word with an 8 byte nonce
233 // but other implementations like boringssl have this same
235 panic!("counter is exhausted");
241 #[inline] // Useful cause input may be 0s on stack that should be optimized out
242 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
243 assert!(input.len() == output.len());
244 let len = input.len();
247 // If there is no keystream available in the output buffer,
248 // generate the next block.
249 if self.offset == BLOCK_SIZE {
253 // Process the min(available keystream, remaining input length).
254 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
255 // explicitly assert lengths to avoid bounds checks:
256 assert!(output.len() >= i + count);
257 assert!(input.len() >= i + count);
258 assert!(self.output.len() >= self.offset + count);
260 output[i + j] = input[i + j] ^ self.output[self.offset + j];
263 self.offset += count;
267 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
268 let len = input_output.len();
271 // If there is no keystream available in the output buffer,
272 // generate the next block.
273 if self.offset == BLOCK_SIZE {
277 // Process the min(available keystream, remaining input length).
278 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
279 // explicitly assert lengths to avoid bounds checks:
280 assert!(input_output.len() >= i + count);
281 assert!(self.output.len() >= self.offset + count);
283 input_output[i + j] ^= self.output[self.offset + j];
286 self.offset += count;
291 pub fn seek_to_block(&mut self, block_offset: u32) {
292 self.state.d.0 = block_offset;
298 pub use self::real_chacha::ChaCha20;
302 pub struct ChaCha20 {}
305 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
306 assert!(key.len() == 16 || key.len() == 32);
307 assert!(nonce.len() == 8 || nonce.len() == 12);
311 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
315 pub fn encrypt_single_block(
316 _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
318 debug_assert_eq!(dest.len(), src.len());
319 debug_assert!(dest.len() <= 32);
322 pub fn encrypt_single_block_in_place(
323 _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
326 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
327 output.copy_from_slice(input);
330 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
334 pub use self::fuzzy_chacha::ChaCha20;
339 use alloc::vec::{Vec};
340 use core::convert::TryInto;
341 use core::iter::repeat;
346 fn test_chacha20_256_tls_vectors() {
352 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
353 let test_vectors = vec!(
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,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
363 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
364 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
365 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
366 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
367 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
368 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
369 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
370 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
379 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
381 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
382 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
383 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
384 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
385 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
386 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
387 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
388 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
399 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
400 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
401 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
402 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
403 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
404 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
405 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
406 0x44, 0x5f, 0x41, 0xe3,
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,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
417 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
418 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
419 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
420 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
421 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
422 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
423 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
424 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
428 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
429 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
430 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
431 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
433 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
435 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
436 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
437 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
438 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
439 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
440 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
441 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
442 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
443 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
444 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
445 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
446 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
447 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
448 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
449 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
450 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
451 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
452 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
453 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
454 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
455 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
456 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
457 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
458 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
459 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
460 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
461 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
462 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
463 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
464 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
465 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
466 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
471 for tv in test_vectors.iter() {
472 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
473 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
474 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
475 c.process(&input[..], &mut output[..]);
476 assert_eq!(output, tv.keystream);
481 fn test_chacha20_256_tls_vectors_96_nonce() {
487 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
488 let test_vectors = vec!(
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,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
498 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
499 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
500 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
501 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
502 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
503 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
504 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
505 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
514 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
516 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
517 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
518 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
519 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
520 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
521 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
522 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
523 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
534 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
535 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
536 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
537 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
538 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
539 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
540 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
541 0x44, 0x5f, 0x41, 0xe3,
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,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
552 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
553 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
554 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
555 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
556 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
557 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
558 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
559 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
563 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
564 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
565 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
566 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
568 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
570 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
571 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
572 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
573 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
574 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
575 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
576 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
577 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
578 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
579 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
580 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
581 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
582 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
583 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
584 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
585 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
586 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
587 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
588 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
589 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
590 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
591 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
592 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
593 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
594 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
595 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
596 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
597 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
598 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
599 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
600 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
601 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
606 for tv in test_vectors.iter() {
607 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
608 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
609 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
610 c.process(&input[..], &mut output[..]);
611 assert_eq!(output, tv.keystream);
616 fn get_single_block() {
617 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
618 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
621 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
622 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
623 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
624 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
626 let nonce_16bytes = [
627 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
629 let counter_pos = &nonce_16bytes[..4];
630 let nonce_12bytes = &nonce_16bytes[4..];
632 // Initialize a ChaCha20 instance with its counter starting at 0.
633 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
634 // Seek its counter to the block at counter_pos.
635 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
636 let mut block_bytes = [0; 32];
637 chacha20.process_in_place(&mut block_bytes);
639 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
643 fn encrypt_single_block() {
645 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
646 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
647 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
648 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
651 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
652 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
656 let mut encrypted_bytes = [0; 32];
657 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
659 let mut decrypted_bytes = [0; 32];
660 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
662 assert_eq!(bytes, decrypted_bytes);
666 fn encrypt_single_block_in_place() {
668 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
669 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
670 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
671 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
674 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
675 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
677 let unencrypted_bytes = [1; 32];
678 let mut bytes = unencrypted_bytes;
680 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
681 assert_ne!(bytes, unencrypted_bytes);
683 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
684 assert_eq!(bytes, unencrypted_bytes);