]> git.bitcoin.ninja Git - rust-lightning/blob - lightning/src/util/chacha20.rs
Merge pull request #1826 from TheBlueMatt/2022-10-idempotency-err
[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                 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",
166                                 _  => unreachable!(),
167                         };
168                         ChaChaState {
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])
173                                 } else {
174                                         u32x4::from_bytes(&key[16..32])
175                                 },
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)
182                                 } else {
183                                         let mut nonce4 = [0; 4*4];
184                                         nonce4[8..].copy_from_slice(nonce);
185                                         u32x4::from_bytes(&nonce4)
186                                 }
187                         }
188                 }
189
190                 // put the the next BLOCK_SIZE keystream bytes into self.output
191                 fn update(&mut self) {
192                         let mut state = self.state;
193
194                         for _ in 0..10 {
195                                 round!(state);
196                                 swizzle!(state.b, state.c, state.d);
197                                 round!(state);
198                                 swizzle!(state.d, state.c, state.b);
199                         }
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;
204
205                         state_to_buffer!(state, self.output);
206
207                         self.state.d = self.state.d + u32x4(1, 0, 0, 0);
208                         let u32x4(c12, _, _, _) = self.state.d;
209                         if c12 == 0 {
210                                 // we could increment the other counter word with an 8 byte nonce
211                                 // but other implementations like boringssl have this same
212                                 // limitation
213                                 panic!("counter is exhausted");
214                         }
215
216                         self.offset = 0;
217                 }
218
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();
223                         let mut i = 0;
224                         while i < len {
225                                 // If there is no keystream available in the output buffer,
226                                 // generate the next block.
227                                 if self.offset == BLOCK_SIZE {
228                                         self.update();
229                                 }
230
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);
237                                 for j in 0..count {
238                                         output[i + j] = input[i + j] ^ self.output[self.offset + j];
239                                 }
240                                 i += count;
241                                 self.offset += count;
242                         }
243                 }
244
245                 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
246                         let len = input_output.len();
247                         let mut i = 0;
248                         while i < len {
249                                 // If there is no keystream available in the output buffer,
250                                 // generate the next block.
251                                 if self.offset == BLOCK_SIZE {
252                                         self.update();
253                                 }
254
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);
260                                 for j in 0..count {
261                                         input_output[i + j] ^= self.output[self.offset + j];
262                                 }
263                                 i += count;
264                                 self.offset += count;
265                         }
266                 }
267
268                 #[cfg(test)]
269                 pub fn seek_to_block(&mut self, block_offset: u32) {
270                         self.state.d.0 = block_offset;
271                         self.update();
272                 }
273         }
274 }
275 #[cfg(not(fuzzing))]
276 pub use self::real_chacha::ChaCha20;
277
278 #[cfg(fuzzing)]
279 mod fuzzy_chacha {
280         pub struct ChaCha20 {}
281
282         impl 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);
286                         Self {}
287                 }
288
289                 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
290                         [0; 32]
291                 }
292
293                 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
294                         output.copy_from_slice(input);
295                 }
296
297                 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
298         }
299 }
300 #[cfg(fuzzing)]
301 pub use self::fuzzy_chacha::ChaCha20;
302
303 pub(crate) struct ChaChaReader<'a, R: io::Read> {
304         pub chacha: &'a mut ChaCha20,
305         pub read: R,
306 }
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)?;
310                 if res > 0 {
311                         self.chacha.process_in_place(&mut dest[0..res]);
312                 }
313                 Ok(res)
314         }
315 }
316
317 #[cfg(test)]
318 mod test {
319         use crate::prelude::*;
320         use core::iter::repeat;
321
322         use super::ChaCha20;
323         use std::convert::TryInto;
324
325         #[test]
326         fn test_chacha20_256_tls_vectors() {
327                 struct TestVector {
328                         key:   [u8; 32],
329                         nonce: [u8; 8],
330                         keystream: Vec<u8>,
331                 }
332                 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
333                 let test_vectors = vec!(
334                         TestVector{
335                                 key: [
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,
340                                 ],
341                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
342                                 keystream: vec!(
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,
351                                 ),
352                         }, TestVector{
353                                 key: [
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,
358                                 ],
359                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
360                                 keystream: vec!(
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,
369                                 ),
370                         }, TestVector{
371                                 key: [
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,
376                                 ],
377                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
378                                 keystream: vec!(
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,
387                                 ),
388                         }, TestVector{
389                                 key: [
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,
394                                 ],
395                                 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
396                                 keystream: vec!(
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,
405                                 ),
406                         }, TestVector{
407                                 key: [
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,
412                                 ],
413                                 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
414                                 keystream: vec!(
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,
447                                 ),
448                         },
449                 );
450
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);
457                 }
458         }
459
460         #[test]
461         fn test_chacha20_256_tls_vectors_96_nonce() {
462                 struct TestVector {
463                         key:   [u8; 32],
464                         nonce: [u8; 12],
465                         keystream: Vec<u8>,
466                 }
467                 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
468                 let test_vectors = vec!(
469                         TestVector{
470                                 key: [
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,
475                                 ],
476                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
477                                 keystream: vec!(
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,
486                                 ),
487                         }, TestVector{
488                                 key: [
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,
493                                 ],
494                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
495                                 keystream: vec!(
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,
504                                 ),
505                         }, TestVector{
506                                 key: [
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,
511                                 ],
512                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
513                                 keystream: vec!(
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,
522                                 ),
523                         }, TestVector{
524                                 key: [
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,
529                                 ],
530                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
531                                 keystream: vec!(
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,
540                                 ),
541                         }, TestVector{
542                                 key: [
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,
547                                 ],
548                                 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
549                                 keystream: vec!(
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,
582                                 ),
583                         },
584                 );
585
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);
592                 }
593         }
594
595         #[test]
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
599                 // bytes.
600                 let key = [
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,
605                 ];
606                 let nonce_16bytes = [
607                         0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
608                 ];
609                 let counter_pos = &nonce_16bytes[..4];
610                 let nonce_12bytes = &nonce_16bytes[4..];
611
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);
618
619                 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
620         }
621 }