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 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
163 let constant = match key.len() {
164 16 => b"expand 16-byte k",
165 32 => b"expand 32-byte k",
169 a: u32x4::from_bytes(&constant[0..16]),
170 b: u32x4::from_bytes(&key[0..16]),
171 c: if key.len() == 16 {
172 u32x4::from_bytes(&key[0..16])
174 u32x4::from_bytes(&key[16..32])
176 d: if nonce.len() == 16 {
177 u32x4::from_bytes(&nonce[0..16])
178 } else if nonce.len() == 12 {
179 let mut nonce4 = [0; 4*4];
180 nonce4[4..].copy_from_slice(nonce);
181 u32x4::from_bytes(&nonce4)
183 let mut nonce4 = [0; 4*4];
184 nonce4[8..].copy_from_slice(nonce);
185 u32x4::from_bytes(&nonce4)
190 // put the the next BLOCK_SIZE keystream bytes into self.output
191 fn update(&mut self) {
192 let mut state = self.state;
196 swizzle!(state.b, state.c, state.d);
198 swizzle!(state.d, state.c, state.b);
200 state.a = state.a + self.state.a;
201 state.b = state.b + self.state.b;
202 state.c = state.c + self.state.c;
203 state.d = state.d + self.state.d;
205 state_to_buffer!(state, self.output);
207 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
208 let u32x4(c12, _, _, _) = self.state.d;
210 // we could increment the other counter word with an 8 byte nonce
211 // but other implementations like boringssl have this same
213 panic!("counter is exhausted");
219 #[inline] // Useful cause input may be 0s on stack that should be optimized out
220 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
221 assert!(input.len() == output.len());
222 let len = input.len();
225 // If there is no keystream available in the output buffer,
226 // generate the next block.
227 if self.offset == BLOCK_SIZE {
231 // Process the min(available keystream, remaining input length).
232 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
233 // explicitly assert lengths to avoid bounds checks:
234 assert!(output.len() >= i + count);
235 assert!(input.len() >= i + count);
236 assert!(self.output.len() >= self.offset + count);
238 output[i + j] = input[i + j] ^ self.output[self.offset + j];
241 self.offset += count;
245 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
246 let len = input_output.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!(input_output.len() >= i + count);
259 assert!(self.output.len() >= self.offset + count);
261 input_output[i + j] ^= self.output[self.offset + j];
264 self.offset += count;
269 pub fn seek_to_block(&mut self, block_offset: u32) {
270 self.state.d.0 = block_offset;
276 pub use self::real_chacha::ChaCha20;
280 pub struct ChaCha20 {}
283 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
284 assert!(key.len() == 16 || key.len() == 32);
285 assert!(nonce.len() == 8 || nonce.len() == 12);
289 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
293 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
294 output.copy_from_slice(input);
297 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
301 pub use self::fuzzy_chacha::ChaCha20;
303 pub(crate) struct ChaChaReader<'a, R: io::Read> {
304 pub chacha: &'a mut ChaCha20,
307 impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
308 fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
309 let res = self.read.read(dest)?;
311 self.chacha.process_in_place(&mut dest[0..res]);
319 use crate::prelude::*;
320 use core::iter::repeat;
323 use std::convert::TryInto;
326 fn test_chacha20_256_tls_vectors() {
332 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
333 let test_vectors = vec!(
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
343 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
344 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
345 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
346 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
347 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
348 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
349 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
350 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x01,
359 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
361 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
362 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
363 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
364 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
365 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
366 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
367 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
368 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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, 0x00,
377 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
379 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
380 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
381 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
382 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
383 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
384 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
385 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
386 0x44, 0x5f, 0x41, 0xe3,
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: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
397 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
398 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
399 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
400 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
401 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
402 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
403 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
404 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
408 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
409 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
410 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
411 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
413 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
415 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
416 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
417 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
418 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
419 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
420 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
421 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
422 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
423 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
424 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
425 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
426 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
427 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
428 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
429 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
430 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
431 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
432 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
433 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
434 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
435 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
436 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
437 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
438 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
439 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
440 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
441 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
442 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
443 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
444 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
445 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
446 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
451 for tv in test_vectors.iter() {
452 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
453 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
454 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
455 c.process(&input[..], &mut output[..]);
456 assert_eq!(output, tv.keystream);
461 fn test_chacha20_256_tls_vectors_96_nonce() {
467 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
468 let test_vectors = vec!(
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
478 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
479 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
480 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
481 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
482 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
483 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
484 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
485 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
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, 0x01,
494 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
496 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
497 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
498 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
499 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
500 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
501 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
502 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
503 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
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, 0x00,
512 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
514 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
515 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
516 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
517 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
518 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
519 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
520 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
521 0x44, 0x5f, 0x41, 0xe3,
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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
532 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
533 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
534 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
535 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
536 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
537 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
538 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
539 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
543 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
544 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
545 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
546 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
548 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
550 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
551 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
552 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
553 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
554 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
555 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
556 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
557 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
558 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
559 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
560 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
561 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
562 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
563 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
564 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
565 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
566 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
567 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
568 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
569 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
570 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
571 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
572 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
573 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
574 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
575 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
576 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
577 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
578 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
579 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
580 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
581 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
586 for tv in test_vectors.iter() {
587 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
588 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
589 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
590 c.process(&input[..], &mut output[..]);
591 assert_eq!(output, tv.keystream);
596 fn get_single_block() {
597 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
598 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
601 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
602 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
603 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
604 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
606 let nonce_16bytes = [
607 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
609 let counter_pos = &nonce_16bytes[..4];
610 let nonce_12bytes = &nonce_16bytes[4..];
612 // Initialize a ChaCha20 instance with its counter starting at 0.
613 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
614 // Seek its counter to the block at counter_pos.
615 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
616 let mut block_bytes = [0; 32];
617 chacha20.process_in_place(&mut block_bytes);
619 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);