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<u8> for u32x4 {
48 fn shr(self, shr: u8) -> u32x4 {
49 u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
52 impl ::core::ops::Shl<u8> for u32x4 {
54 fn shl(self, shl: u8) -> u32x4 {
55 u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
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, 16);
122 $state.c = $state.c + $state.d;
123 rotate!($state.b, $state.c, 12);
124 $state.a = $state.a + $state.b;
125 rotate!($state.d, $state.a, 8);
126 $state.c = $state.c + $state.d;
127 rotate!($state.b, $state.c, 7);
131 macro_rules! rotate {
132 ($a: expr, $b: expr, $rot: expr) => {{
136 $a = (v << $rot) ^ right
141 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
142 assert!(key.len() == 16 || key.len() == 32);
143 assert!(nonce.len() == 8 || nonce.len() == 12);
145 ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
148 /// Get one block from a ChaCha stream.
149 pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
150 let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
151 let mut chacha_bytes = [0; 32];
152 chacha.process_in_place(&mut chacha_bytes);
156 /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
157 /// `src` in a second call will decrypt it.
158 pub fn encrypt_single_block(
159 key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
161 debug_assert_eq!(dest.len(), src.len());
162 debug_assert!(dest.len() <= 32);
164 let block = ChaCha20::get_single_block(key, nonce);
165 for i in 0..dest.len() {
166 dest[i] = block[i] ^ src[i];
170 /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
171 pub fn encrypt_single_block_in_place(
172 key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
174 let block = ChaCha20::get_single_block(key, nonce);
175 for i in 0..bytes.len() {
176 bytes[i] = block[i] ^ bytes[i];
180 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
181 let constant = match key.len() {
182 16 => b"expand 16-byte k",
183 32 => b"expand 32-byte k",
187 a: u32x4::from_bytes(&constant[0..16]),
188 b: u32x4::from_bytes(&key[0..16]),
189 c: if key.len() == 16 {
190 u32x4::from_bytes(&key[0..16])
192 u32x4::from_bytes(&key[16..32])
194 d: if nonce.len() == 16 {
195 u32x4::from_bytes(&nonce[0..16])
196 } else if nonce.len() == 12 {
197 let mut nonce4 = [0; 4*4];
198 nonce4[4..].copy_from_slice(nonce);
199 u32x4::from_bytes(&nonce4)
201 let mut nonce4 = [0; 4*4];
202 nonce4[8..].copy_from_slice(nonce);
203 u32x4::from_bytes(&nonce4)
208 // put the the next BLOCK_SIZE keystream bytes into self.output
209 fn update(&mut self) {
210 let mut state = self.state;
214 swizzle!(state.b, state.c, state.d);
216 swizzle!(state.d, state.c, state.b);
218 state.a = state.a + self.state.a;
219 state.b = state.b + self.state.b;
220 state.c = state.c + self.state.c;
221 state.d = state.d + self.state.d;
223 state_to_buffer!(state, self.output);
225 self.state.d = self.state.d + u32x4(1, 0, 0, 0);
226 let u32x4(c12, _, _, _) = self.state.d;
228 // we could increment the other counter word with an 8 byte nonce
229 // but other implementations like boringssl have this same
231 panic!("counter is exhausted");
237 #[inline] // Useful cause input may be 0s on stack that should be optimized out
238 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
239 assert!(input.len() == output.len());
240 let len = input.len();
243 // If there is no keystream available in the output buffer,
244 // generate the next block.
245 if self.offset == BLOCK_SIZE {
249 // Process the min(available keystream, remaining input length).
250 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
251 // explicitly assert lengths to avoid bounds checks:
252 assert!(output.len() >= i + count);
253 assert!(input.len() >= i + count);
254 assert!(self.output.len() >= self.offset + count);
256 output[i + j] = input[i + j] ^ self.output[self.offset + j];
259 self.offset += count;
263 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
264 let len = input_output.len();
267 // If there is no keystream available in the output buffer,
268 // generate the next block.
269 if self.offset == BLOCK_SIZE {
273 // Process the min(available keystream, remaining input length).
274 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
275 // explicitly assert lengths to avoid bounds checks:
276 assert!(input_output.len() >= i + count);
277 assert!(self.output.len() >= self.offset + count);
279 input_output[i + j] ^= self.output[self.offset + j];
282 self.offset += count;
287 pub fn seek_to_block(&mut self, block_offset: u32) {
288 self.state.d.0 = block_offset;
294 pub use self::real_chacha::ChaCha20;
298 pub struct ChaCha20 {}
301 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
302 assert!(key.len() == 16 || key.len() == 32);
303 assert!(nonce.len() == 8 || nonce.len() == 12);
307 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
311 pub fn encrypt_single_block(
312 _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
314 debug_assert_eq!(dest.len(), src.len());
315 debug_assert!(dest.len() <= 32);
318 pub fn encrypt_single_block_in_place(
319 _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
322 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
323 output.copy_from_slice(input);
326 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
330 pub use self::fuzzy_chacha::ChaCha20;
332 pub(crate) struct ChaChaReader<'a, R: io::Read> {
333 pub chacha: &'a mut ChaCha20,
336 impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
337 fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
338 let res = self.read.read(dest)?;
340 self.chacha.process_in_place(&mut dest[0..res]);
348 use crate::prelude::*;
349 use core::iter::repeat;
352 use std::convert::TryInto;
355 fn test_chacha20_256_tls_vectors() {
361 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
362 let test_vectors = vec!(
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
372 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
373 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
374 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
375 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
376 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
377 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
378 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
379 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
388 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
390 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
391 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
392 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
393 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
394 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
395 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
396 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
397 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
408 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
409 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
410 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
411 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
412 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
413 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
414 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
415 0x44, 0x5f, 0x41, 0xe3,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
426 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
427 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
428 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
429 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
430 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
431 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
432 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
433 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
437 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
438 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
439 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
440 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
442 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
444 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
445 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
446 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
447 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
448 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
449 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
450 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
451 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
452 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
453 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
454 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
455 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
456 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
457 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
458 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
459 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
460 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
461 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
462 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
463 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
464 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
465 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
466 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
467 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
468 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
469 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
470 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
471 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
472 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
473 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
474 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
475 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
480 for tv in test_vectors.iter() {
481 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
482 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
483 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
484 c.process(&input[..], &mut output[..]);
485 assert_eq!(output, tv.keystream);
490 fn test_chacha20_256_tls_vectors_96_nonce() {
496 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
497 let test_vectors = vec!(
500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
507 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
508 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
509 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
510 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
511 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
512 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
513 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
514 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
523 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
525 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
526 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
527 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
528 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
529 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
530 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
531 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
532 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
543 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
544 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
545 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
546 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
547 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
548 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
549 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
550 0x44, 0x5f, 0x41, 0xe3,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
561 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
562 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
563 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
564 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
565 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
566 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
567 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
568 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
572 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
573 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
574 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
575 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
577 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
579 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
580 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
581 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
582 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
583 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
584 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
585 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
586 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
587 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
588 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
589 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
590 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
591 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
592 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
593 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
594 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
595 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
596 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
597 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
598 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
599 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
600 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
601 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
602 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
603 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
604 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
605 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
606 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
607 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
608 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
609 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
610 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
615 for tv in test_vectors.iter() {
616 let mut c = ChaCha20::new(&tv.key, &tv.nonce);
617 let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
618 let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
619 c.process(&input[..], &mut output[..]);
620 assert_eq!(output, tv.keystream);
625 fn get_single_block() {
626 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
627 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
630 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
631 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
632 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
633 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
635 let nonce_16bytes = [
636 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
638 let counter_pos = &nonce_16bytes[..4];
639 let nonce_12bytes = &nonce_16bytes[4..];
641 // Initialize a ChaCha20 instance with its counter starting at 0.
642 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
643 // Seek its counter to the block at counter_pos.
644 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
645 let mut block_bytes = [0; 32];
646 chacha20.process_in_place(&mut block_bytes);
648 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
652 fn encrypt_single_block() {
654 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
655 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
656 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
657 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
660 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
661 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
665 let mut encrypted_bytes = [0; 32];
666 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
668 let mut decrypted_bytes = [0; 32];
669 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
671 assert_eq!(bytes, decrypted_bytes);
675 fn encrypt_single_block_in_place() {
677 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
678 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
679 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
680 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
683 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
684 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
686 let unencrypted_bytes = [1; 32];
687 let mut bytes = unencrypted_bytes;
689 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
690 assert_ne!(bytes, unencrypted_bytes);
692 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
693 assert_eq!(bytes, unencrypted_bytes);