]> git.bitcoin.ninja Git - rust-lightning/blob - lightning/src/util/chacha20.rs
Add a ChaCha20 utility for encrypting a block
[rust-lightning] / lightning / src / util / chacha20.rs
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.
5 //
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
10 // licenses.
11
12 use crate::io;
13
14 #[cfg(not(fuzzing))]
15 mod real_chacha {
16         use core::cmp;
17         use core::convert::TryInto;
18
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 {
23                 type Output = 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))
29                 }
30         }
31         impl ::core::ops::Sub for u32x4 {
32                 type Output = 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))
38                 }
39         }
40         impl ::core::ops::BitXor for u32x4 {
41                 type Output = 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)
44                 }
45         }
46         impl ::core::ops::Shr<u32x4> for u32x4 {
47                 type Output = 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)
50                 }
51         }
52         impl ::core::ops::Shl<u32x4> for u32x4 {
53                 type Output = 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)
56                 }
57         }
58         impl u32x4 {
59                 fn from_bytes(bytes: &[u8]) -> Self {
60                         assert_eq!(bytes.len(), 4*4);
61                         Self (
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")),
66                         )
67                 }
68         }
69
70         const BLOCK_SIZE: usize = 64;
71
72         #[derive(Clone,Copy)]
73         struct ChaChaState {
74                 a: u32x4,
75                 b: u32x4,
76                 c: u32x4,
77                 d: u32x4
78         }
79
80         #[derive(Copy)]
81         pub struct ChaCha20 {
82                 state  : ChaChaState,
83                 output : [u8; BLOCK_SIZE],
84                 offset : usize,
85         }
86
87         impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
88
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);
97                 }}
98         }
99
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;
106                         let lens = [
107                                 a1,a2,a3,a4,
108                                 b1,b2,b3,b4,
109                                 c1,c2,c3,c4,
110                                 d1,d2,d3,d4
111                         ];
112                         for i in 0..lens.len() {
113                                 $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
114                         }
115                 }}
116         }
117
118         macro_rules! round{
119                 ($state: expr) => {{
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);
128                 }}
129         }
130
131         macro_rules! rotate {
132                 ($a: expr, $b: expr, $c:expr) => {{
133                         let v = $a ^ $b;
134                         let r = S32 - $c;
135                         let right = v >> r;
136                         $a = (v << $c) ^ right
137                 }}
138         }
139
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);
145
146         impl ChaCha20 {
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);
150
151                         ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
152                 }
153
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);
159                         chacha_bytes
160                 }
161
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]
166                 ) {
167                         debug_assert_eq!(dest.len(), src.len());
168                         debug_assert!(dest.len() <= 32);
169
170                         let block = ChaCha20::get_single_block(key, nonce);
171                         for i in 0..dest.len() {
172                                 dest[i] = block[i] ^ src[i];
173                         }
174                 }
175
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",
180                                 _  => unreachable!(),
181                         };
182                         ChaChaState {
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])
187                                 } else {
188                                         u32x4::from_bytes(&key[16..32])
189                                 },
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)
196                                 } else {
197                                         let mut nonce4 = [0; 4*4];
198                                         nonce4[8..].copy_from_slice(nonce);
199                                         u32x4::from_bytes(&nonce4)
200                                 }
201                         }
202                 }
203
204                 // put the the next BLOCK_SIZE keystream bytes into self.output
205                 fn update(&mut self) {
206                         let mut state = self.state;
207
208                         for _ in 0..10 {
209                                 round!(state);
210                                 swizzle!(state.b, state.c, state.d);
211                                 round!(state);
212                                 swizzle!(state.d, state.c, state.b);
213                         }
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;
218
219                         state_to_buffer!(state, self.output);
220
221                         self.state.d = self.state.d + u32x4(1, 0, 0, 0);
222                         let u32x4(c12, _, _, _) = self.state.d;
223                         if c12 == 0 {
224                                 // we could increment the other counter word with an 8 byte nonce
225                                 // but other implementations like boringssl have this same
226                                 // limitation
227                                 panic!("counter is exhausted");
228                         }
229
230                         self.offset = 0;
231                 }
232
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();
237                         let mut i = 0;
238                         while i < len {
239                                 // If there is no keystream available in the output buffer,
240                                 // generate the next block.
241                                 if self.offset == BLOCK_SIZE {
242                                         self.update();
243                                 }
244
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);
251                                 for j in 0..count {
252                                         output[i + j] = input[i + j] ^ self.output[self.offset + j];
253                                 }
254                                 i += count;
255                                 self.offset += count;
256                         }
257                 }
258
259                 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
260                         let len = input_output.len();
261                         let mut i = 0;
262                         while i < len {
263                                 // If there is no keystream available in the output buffer,
264                                 // generate the next block.
265                                 if self.offset == BLOCK_SIZE {
266                                         self.update();
267                                 }
268
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);
274                                 for j in 0..count {
275                                         input_output[i + j] ^= self.output[self.offset + j];
276                                 }
277                                 i += count;
278                                 self.offset += count;
279                         }
280                 }
281
282                 #[cfg(test)]
283                 pub fn seek_to_block(&mut self, block_offset: u32) {
284                         self.state.d.0 = block_offset;
285                         self.update();
286                 }
287         }
288 }
289 #[cfg(not(fuzzing))]
290 pub use self::real_chacha::ChaCha20;
291
292 #[cfg(fuzzing)]
293 mod fuzzy_chacha {
294         pub struct ChaCha20 {}
295
296         impl 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);
300                         Self {}
301                 }
302
303                 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
304                         [0; 32]
305                 }
306
307                 pub fn encrypt_single_block(
308                         _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
309                 ) {
310                         debug_assert_eq!(dest.len(), src.len());
311                         debug_assert!(dest.len() <= 32);
312                 }
313
314                 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
315                         output.copy_from_slice(input);
316                 }
317
318                 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
319         }
320 }
321 #[cfg(fuzzing)]
322 pub use self::fuzzy_chacha::ChaCha20;
323
324 pub(crate) struct ChaChaReader<'a, R: io::Read> {
325         pub chacha: &'a mut ChaCha20,
326         pub read: R,
327 }
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)?;
331                 if res > 0 {
332                         self.chacha.process_in_place(&mut dest[0..res]);
333                 }
334                 Ok(res)
335         }
336 }
337
338 #[cfg(test)]
339 mod test {
340         use crate::prelude::*;
341         use core::iter::repeat;
342
343         use super::ChaCha20;
344         use std::convert::TryInto;
345
346         #[test]
347         fn test_chacha20_256_tls_vectors() {
348                 struct TestVector {
349                         key:   [u8; 32],
350                         nonce: [u8; 8],
351                         keystream: Vec<u8>,
352                 }
353                 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
354                 let test_vectors = vec!(
355                         TestVector{
356                                 key: [
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,
361                                 ],
362                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
363                                 keystream: vec!(
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,
372                                 ),
373                         }, TestVector{
374                                 key: [
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,
379                                 ],
380                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
381                                 keystream: vec!(
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,
390                                 ),
391                         }, TestVector{
392                                 key: [
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,
397                                 ],
398                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
399                                 keystream: vec!(
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,
408                                 ),
409                         }, TestVector{
410                                 key: [
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,
415                                 ],
416                                 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
417                                 keystream: vec!(
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,
426                                 ),
427                         }, TestVector{
428                                 key: [
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,
433                                 ],
434                                 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
435                                 keystream: vec!(
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,
468                                 ),
469                         },
470                 );
471
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);
478                 }
479         }
480
481         #[test]
482         fn test_chacha20_256_tls_vectors_96_nonce() {
483                 struct TestVector {
484                         key:   [u8; 32],
485                         nonce: [u8; 12],
486                         keystream: Vec<u8>,
487                 }
488                 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
489                 let test_vectors = vec!(
490                         TestVector{
491                                 key: [
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,
496                                 ],
497                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
498                                 keystream: vec!(
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,
507                                 ),
508                         }, TestVector{
509                                 key: [
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,
514                                 ],
515                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
516                                 keystream: vec!(
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,
525                                 ),
526                         }, TestVector{
527                                 key: [
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,
532                                 ],
533                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
534                                 keystream: vec!(
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,
543                                 ),
544                         }, TestVector{
545                                 key: [
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,
550                                 ],
551                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
552                                 keystream: vec!(
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,
561                                 ),
562                         }, TestVector{
563                                 key: [
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,
568                                 ],
569                                 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
570                                 keystream: vec!(
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,
603                                 ),
604                         },
605                 );
606
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);
613                 }
614         }
615
616         #[test]
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
620                 // bytes.
621                 let key = [
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,
626                 ];
627                 let nonce_16bytes = [
628                         0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
629                 ];
630                 let counter_pos = &nonce_16bytes[..4];
631                 let nonce_12bytes = &nonce_16bytes[4..];
632
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);
639
640                 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
641         }
642
643         #[test]
644         fn encrypt_single_block() {
645                 let key = [
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,
650                 ];
651                 let nonce = [
652                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
653                         0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
654                 ];
655                 let bytes = [1; 32];
656
657                 let mut encrypted_bytes = [0; 32];
658                 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
659
660                 let mut decrypted_bytes = [0; 32];
661                 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
662
663                 assert_eq!(bytes, decrypted_bytes);
664         }
665 }