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
17 use core::convert::TryInto;
19 #[derive(Clone, Copy, PartialEq, Eq)]
20 #[allow(non_camel_case_types)]
21 struct u32x4(pub u32, pub u32, pub u32, pub u32);
22 impl ::core::ops::Add for u32x4 {
24 fn add(self, rhs: u32x4) -> u32x4 {
25 u32x4(self.0.wrapping_add(rhs.0),
26 self.1.wrapping_add(rhs.1),
27 self.2.wrapping_add(rhs.2),
28 self.3.wrapping_add(rhs.3))
31 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 {
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<u32x4> for u32x4 {
48 fn shr(self, rhs: u32x4) -> u32x4 {
49 u32x4(self.0 >> rhs.0, self.1 >> rhs.1, self.2 >> rhs.2, self.3 >> rhs.3)
52 impl ::core::ops::Shl<u32x4> for u32x4 {
54 fn shl(self, rhs: u32x4) -> u32x4 {
55 u32x4(self.0 << rhs.0, self.1 << rhs.1, self.2 << rhs.2, self.3 << rhs.3)
59 fn from_bytes(bytes: &[u8]) -> Self {
60 assert_eq!(bytes.len(), 4*4);
62 u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
63 u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
64 u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
65 u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
70 const BLOCK_SIZE: usize = 64;
83 output : [u8; BLOCK_SIZE],
87 impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
89 macro_rules! swizzle {
90 ($b: expr, $c: expr, $d: expr) => {{
91 let u32x4(b10, b11, b12, b13) = $b;
92 $b = u32x4(b11, b12, b13, b10);
93 let u32x4(c10, c11, c12, c13) = $c;
94 $c = u32x4(c12, c13,c10, c11);
95 let u32x4(d10, d11, d12, d13) = $d;
96 $d = u32x4(d13, d10, d11, d12);
100 macro_rules! state_to_buffer {
101 ($state: expr, $output: expr) => {{
102 let u32x4(a1, a2, a3, a4) = $state.a;
103 let u32x4(b1, b2, b3, b4) = $state.b;
104 let u32x4(c1, c2, c3, c4) = $state.c;
105 let u32x4(d1, d2, d3, d4) = $state.d;
112 for i in 0..lens.len() {
113 $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
120 $state.a = $state.a + $state.b;
121 rotate!($state.d, $state.a, S16);
122 $state.c = $state.c + $state.d;
123 rotate!($state.b, $state.c, S12);
124 $state.a = $state.a + $state.b;
125 rotate!($state.d, $state.a, S8);
126 $state.c = $state.c + $state.d;
127 rotate!($state.b, $state.c, S7);
131 macro_rules! rotate {
132 ($a: expr, $b: expr, $c:expr) => {{
136 $a = (v << $c) ^ right
140 const S32:u32x4 = u32x4(32, 32, 32, 32);
141 const S16:u32x4 = u32x4(16, 16, 16, 16);
142 const S12:u32x4 = u32x4(12, 12, 12, 12);
143 const S8:u32x4 = u32x4(8, 8, 8, 8);
144 const S7:u32x4 = u32x4(7, 7, 7, 7);
147 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
148 assert!(key.len() == 16 || key.len() == 32);
149 assert!(nonce.len() == 8 || nonce.len() == 12);
151 ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
154 /// Get one block from a ChaCha stream.
155 pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
156 let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
157 let mut chacha_bytes = [0; 32];
158 chacha.process_in_place(&mut chacha_bytes);
162 /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
163 /// `src` in a second call will decrypt it.
164 pub fn encrypt_single_block(
165 key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
167 debug_assert_eq!(dest.len(), src.len());
168 debug_assert!(dest.len() <= 32);
170 let block = ChaCha20::get_single_block(key, nonce);
171 for i in 0..dest.len() {
172 dest[i] = block[i] ^ src[i];
176 /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
177 pub fn encrypt_single_block_in_place(
178 key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
180 let block = ChaCha20::get_single_block(key, nonce);
181 for i in 0..bytes.len() {
182 bytes[i] = block[i] ^ bytes[i];
186 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
187 let constant = match key.len() {
188 16 => b"expand 16-byte k",
189 32 => b"expand 32-byte k",
193 a: u32x4::from_bytes(&constant[0..16]),
194 b: u32x4::from_bytes(&key[0..16]),
195 c: if key.len() == 16 {
196 u32x4::from_bytes(&key[0..16])
198 u32x4::from_bytes(&key[16..32])
200 d: if nonce.len() == 16 {
201 u32x4::from_bytes(&nonce[0..16])
202 } else if nonce.len() == 12 {
203 let mut nonce4 = [0; 4*4];
204 nonce4[4..].copy_from_slice(nonce);
205 u32x4::from_bytes(&nonce4)
207 let mut nonce4 = [0; 4*4];
208 nonce4[8..].copy_from_slice(nonce);
209 u32x4::from_bytes(&nonce4)
214 // put the the next BLOCK_SIZE keystream bytes into self.output
215 fn update(&mut self) {
216 let mut state = self.state;
220 swizzle!(state.b, state.c, state.d);
222 swizzle!(state.d, state.c, state.b);
224 state.a = state.a + self.state.a;
225 state.b = state.b + self.state.b;
226 state.c = state.c + self.state.c;
227 state.d = state.d + self.state.d;
229 state_to_buffer!(state, self.output);
231 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
232 let u32x4(c12, _, _, _) = self.state.d;
234 // we could increment the other counter word with an 8 byte nonce
235 // but other implementations like boringssl have this same
237 panic!("counter is exhausted");
243 #[inline] // Useful cause input may be 0s on stack that should be optimized out
244 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
245 assert!(input.len() == output.len());
246 let len = input.len();
249 // If there is no keystream available in the output buffer,
250 // generate the next block.
251 if self.offset == BLOCK_SIZE {
255 // Process the min(available keystream, remaining input length).
256 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
257 // explicitly assert lengths to avoid bounds checks:
258 assert!(output.len() >= i + count);
259 assert!(input.len() >= i + count);
260 assert!(self.output.len() >= self.offset + count);
262 output[i + j] = input[i + j] ^ self.output[self.offset + j];
265 self.offset += count;
269 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
270 let len = input_output.len();
273 // If there is no keystream available in the output buffer,
274 // generate the next block.
275 if self.offset == BLOCK_SIZE {
279 // Process the min(available keystream, remaining input length).
280 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
281 // explicitly assert lengths to avoid bounds checks:
282 assert!(input_output.len() >= i + count);
283 assert!(self.output.len() >= self.offset + count);
285 input_output[i + j] ^= self.output[self.offset + j];
288 self.offset += count;
293 pub fn seek_to_block(&mut self, block_offset: u32) {
294 self.state.d.0 = block_offset;
300 pub use self::real_chacha::ChaCha20;
304 pub struct ChaCha20 {}
307 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
308 assert!(key.len() == 16 || key.len() == 32);
309 assert!(nonce.len() == 8 || nonce.len() == 12);
313 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
317 pub fn encrypt_single_block(
318 _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
320 debug_assert_eq!(dest.len(), src.len());
321 debug_assert!(dest.len() <= 32);
324 pub fn encrypt_single_block_in_place(
325 _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
328 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
329 output.copy_from_slice(input);
332 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
336 pub use self::fuzzy_chacha::ChaCha20;
338 pub(crate) struct ChaChaReader<'a, R: io::Read> {
339 pub chacha: &'a mut ChaCha20,
342 impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
343 fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
344 let res = self.read.read(dest)?;
346 self.chacha.process_in_place(&mut dest[0..res]);
354 use crate::prelude::*;
355 use core::iter::repeat;
358 use std::convert::TryInto;
361 fn test_chacha20_256_tls_vectors() {
367 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
368 let test_vectors = vec!(
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
376 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
378 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
379 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
380 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
381 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
382 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
383 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
384 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
385 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01,
394 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
396 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
397 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
398 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
399 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
400 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
401 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
402 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
403 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
412 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
414 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
415 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
416 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
417 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
418 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
419 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
420 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
421 0x44, 0x5f, 0x41, 0xe3,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
432 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
433 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
434 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
435 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
436 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
437 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
438 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
439 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
443 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
444 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
445 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
446 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
448 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
450 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
451 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
452 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
453 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
454 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
455 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
456 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
457 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
458 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
459 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
460 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
461 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
462 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
463 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
464 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
465 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
466 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
467 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
468 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
469 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
470 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
471 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
472 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
473 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
474 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
475 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
476 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
477 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
478 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
479 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
480 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
481 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
486 for tv in test_vectors.iter() {
487 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
488 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
489 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
490 c.process(&input[..], &mut output[..]);
491 assert_eq!(output, tv.keystream);
496 fn test_chacha20_256_tls_vectors_96_nonce() {
502 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
503 let test_vectors = vec!(
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
511 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
513 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
514 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
515 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
516 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
517 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
518 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
519 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
520 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01,
529 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
531 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
532 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
533 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
534 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
535 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
536 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
537 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
538 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
547 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
549 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
550 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
551 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
552 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
553 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
554 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
555 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
556 0x44, 0x5f, 0x41, 0xe3,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
567 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
568 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
569 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
570 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
571 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
572 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
573 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
574 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
578 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
579 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
580 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
581 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
583 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
585 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
586 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
587 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
588 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
589 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
590 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
591 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
592 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
593 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
594 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
595 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
596 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
597 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
598 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
599 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
600 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
601 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
602 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
603 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
604 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
605 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
606 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
607 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
608 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
609 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
610 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
611 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
612 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
613 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
614 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
615 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
616 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
621 for tv in test_vectors.iter() {
622 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
623 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
624 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
625 c.process(&input[..], &mut output[..]);
626 assert_eq!(output, tv.keystream);
631 fn get_single_block() {
632 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
633 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
636 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
637 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
638 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
639 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
641 let nonce_16bytes = [
642 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
644 let counter_pos = &nonce_16bytes[..4];
645 let nonce_12bytes = &nonce_16bytes[4..];
647 // Initialize a ChaCha20 instance with its counter starting at 0.
648 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
649 // Seek its counter to the block at counter_pos.
650 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
651 let mut block_bytes = [0; 32];
652 chacha20.process_in_place(&mut block_bytes);
654 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
658 fn encrypt_single_block() {
660 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
661 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
662 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
663 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
666 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
667 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
671 let mut encrypted_bytes = [0; 32];
672 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
674 let mut decrypted_bytes = [0; 32];
675 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
677 assert_eq!(bytes, decrypted_bytes);
681 fn encrypt_single_block_in_place() {
683 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
684 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
685 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
686 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
689 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
690 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
692 let unencrypted_bytes = [1; 32];
693 let mut bytes = unencrypted_bytes;
695 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
696 assert_ne!(bytes, unencrypted_bytes);
698 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
699 assert_eq!(bytes, unencrypted_bytes);