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 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
177 let constant = match key.len() {
178 16 => b"expand 16-byte k",
179 32 => b"expand 32-byte k",
183 a: u32x4::from_bytes(&constant[0..16]),
184 b: u32x4::from_bytes(&key[0..16]),
185 c: if key.len() == 16 {
186 u32x4::from_bytes(&key[0..16])
188 u32x4::from_bytes(&key[16..32])
190 d: if nonce.len() == 16 {
191 u32x4::from_bytes(&nonce[0..16])
192 } else if nonce.len() == 12 {
193 let mut nonce4 = [0; 4*4];
194 nonce4[4..].copy_from_slice(nonce);
195 u32x4::from_bytes(&nonce4)
197 let mut nonce4 = [0; 4*4];
198 nonce4[8..].copy_from_slice(nonce);
199 u32x4::from_bytes(&nonce4)
204 // put the the next BLOCK_SIZE keystream bytes into self.output
205 fn update(&mut self) {
206 let mut state = self.state;
210 swizzle!(state.b, state.c, state.d);
212 swizzle!(state.d, state.c, state.b);
214 state.a = state.a + self.state.a;
215 state.b = state.b + self.state.b;
216 state.c = state.c + self.state.c;
217 state.d = state.d + self.state.d;
219 state_to_buffer!(state, self.output);
221 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
222 let u32x4(c12, _, _, _) = self.state.d;
224 // we could increment the other counter word with an 8 byte nonce
225 // but other implementations like boringssl have this same
227 panic!("counter is exhausted");
233 #[inline] // Useful cause input may be 0s on stack that should be optimized out
234 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
235 assert!(input.len() == output.len());
236 let len = input.len();
239 // If there is no keystream available in the output buffer,
240 // generate the next block.
241 if self.offset == BLOCK_SIZE {
245 // Process the min(available keystream, remaining input length).
246 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
247 // explicitly assert lengths to avoid bounds checks:
248 assert!(output.len() >= i + count);
249 assert!(input.len() >= i + count);
250 assert!(self.output.len() >= self.offset + count);
252 output[i + j] = input[i + j] ^ self.output[self.offset + j];
255 self.offset += count;
259 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
260 let len = input_output.len();
263 // If there is no keystream available in the output buffer,
264 // generate the next block.
265 if self.offset == BLOCK_SIZE {
269 // Process the min(available keystream, remaining input length).
270 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
271 // explicitly assert lengths to avoid bounds checks:
272 assert!(input_output.len() >= i + count);
273 assert!(self.output.len() >= self.offset + count);
275 input_output[i + j] ^= self.output[self.offset + j];
278 self.offset += count;
283 pub fn seek_to_block(&mut self, block_offset: u32) {
284 self.state.d.0 = block_offset;
290 pub use self::real_chacha::ChaCha20;
294 pub struct ChaCha20 {}
297 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
298 assert!(key.len() == 16 || key.len() == 32);
299 assert!(nonce.len() == 8 || nonce.len() == 12);
303 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
307 pub fn encrypt_single_block(
308 _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
310 debug_assert_eq!(dest.len(), src.len());
311 debug_assert!(dest.len() <= 32);
314 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
315 output.copy_from_slice(input);
318 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
322 pub use self::fuzzy_chacha::ChaCha20;
324 pub(crate) struct ChaChaReader<'a, R: io::Read> {
325 pub chacha: &'a mut ChaCha20,
328 impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
329 fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
330 let res = self.read.read(dest)?;
332 self.chacha.process_in_place(&mut dest[0..res]);
340 use crate::prelude::*;
341 use core::iter::repeat;
344 use std::convert::TryInto;
347 fn test_chacha20_256_tls_vectors() {
353 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
354 let test_vectors = vec!(
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,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
364 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
365 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
366 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
367 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
368 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
369 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
370 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
371 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
380 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
382 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
383 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
384 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
385 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
386 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
387 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
388 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
389 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
400 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
401 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
402 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
403 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
404 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
405 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
406 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
407 0x44, 0x5f, 0x41, 0xe3,
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,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
418 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
419 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
420 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
421 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
422 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
423 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
424 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
425 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
429 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
430 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
431 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
432 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
434 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
436 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
437 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
438 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
439 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
440 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
441 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
442 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
443 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
444 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
445 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
446 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
447 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
448 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
449 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
450 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
451 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
452 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
453 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
454 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
455 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
456 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
457 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
458 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
459 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
460 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
461 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
462 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
463 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
464 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
465 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
466 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
467 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
472 for tv in test_vectors.iter() {
473 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
474 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
475 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
476 c.process(&input[..], &mut output[..]);
477 assert_eq!(output, tv.keystream);
482 fn test_chacha20_256_tls_vectors_96_nonce() {
488 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
489 let test_vectors = vec!(
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,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
499 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
500 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
501 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
502 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
503 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
504 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
505 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
506 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
515 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
517 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
518 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
519 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
520 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
521 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
522 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
523 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
524 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
535 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
536 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
537 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
538 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
539 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
540 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
541 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
542 0x44, 0x5f, 0x41, 0xe3,
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,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
553 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
554 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
555 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
556 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
557 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
558 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
559 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
560 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
564 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
565 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
566 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
567 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
569 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
571 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
572 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
573 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
574 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
575 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
576 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
577 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
578 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
579 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
580 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
581 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
582 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
583 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
584 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
585 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
586 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
587 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
588 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
589 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
590 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
591 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
592 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
593 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
594 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
595 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
596 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
597 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
598 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
599 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
600 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
601 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
602 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
607 for tv in test_vectors.iter() {
608 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
609 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
610 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
611 c.process(&input[..], &mut output[..]);
612 assert_eq!(output, tv.keystream);
617 fn get_single_block() {
618 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
619 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
622 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
623 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
624 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
625 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
627 let nonce_16bytes = [
628 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
630 let counter_pos = &nonce_16bytes[..4];
631 let nonce_12bytes = &nonce_16bytes[4..];
633 // Initialize a ChaCha20 instance with its counter starting at 0.
634 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
635 // Seek its counter to the block at counter_pos.
636 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
637 let mut block_bytes = [0; 32];
638 chacha20.process_in_place(&mut block_bytes);
640 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
644 fn encrypt_single_block() {
646 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
647 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
648 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
649 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
652 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
653 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
657 let mut encrypted_bytes = [0; 32];
658 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
660 let mut decrypted_bytes = [0; 32];
661 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
663 assert_eq!(bytes, decrypted_bytes);