]> git.bitcoin.ninja Git - rust-lightning/blob - lightning/src/crypto/chacha20.rs
Merge pull request #2905 from tnull/2024-02-expose-init-features
[rust-lightning] / lightning / src / crypto / 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 #[cfg(not(fuzzing))]
13 mod real_chacha {
14         use core::cmp;
15         use core::convert::TryInto;
16
17         #[derive(Clone, Copy, PartialEq, Eq)]
18         #[allow(non_camel_case_types)]
19         struct u32x4(pub u32, pub u32, pub u32, pub u32);
20         impl ::core::ops::Add for u32x4 {
21                 type Output = u32x4;
22                 #[inline]
23                 fn add(self, rhs: u32x4) -> u32x4 {
24                         u32x4(self.0.wrapping_add(rhs.0),
25                               self.1.wrapping_add(rhs.1),
26                               self.2.wrapping_add(rhs.2),
27                               self.3.wrapping_add(rhs.3))
28                 }
29         }
30         impl ::core::ops::Sub for u32x4 {
31                 type Output = u32x4;
32                 #[inline]
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                 #[inline]
43                 fn bitxor(self, rhs: u32x4) -> u32x4 {
44                         u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
45                 }
46         }
47         impl ::core::ops::Shr<u8> for u32x4 {
48                 type Output = u32x4;
49                 #[inline]
50                 fn shr(self, shr: u8) -> u32x4 {
51                         u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
52                 }
53         }
54         impl ::core::ops::Shl<u8> for u32x4 {
55                 type Output = u32x4;
56                 #[inline]
57                 fn shl(self, shl: u8) -> u32x4 {
58                         u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
59                 }
60         }
61         impl u32x4 {
62                 #[inline]
63                 fn from_bytes(bytes: &[u8]) -> Self {
64                         assert_eq!(bytes.len(), 4*4);
65                         Self (
66                                 u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
67                                 u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
68                                 u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
69                                 u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
70                         )
71                 }
72         }
73
74         const BLOCK_SIZE: usize = 64;
75
76         #[derive(Clone,Copy)]
77         struct ChaChaState {
78                 a: u32x4,
79                 b: u32x4,
80                 c: u32x4,
81                 d: u32x4
82         }
83
84         #[derive(Copy)]
85         pub struct ChaCha20 {
86                 state  : ChaChaState,
87                 output : [u8; BLOCK_SIZE],
88                 offset : usize,
89         }
90
91         impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
92
93         macro_rules! swizzle {
94                 ($b: expr, $c: expr, $d: expr) => {{
95                         let u32x4(b10, b11, b12, b13) = $b;
96                         $b = u32x4(b11, b12, b13, b10);
97                         let u32x4(c10, c11, c12, c13) = $c;
98                         $c = u32x4(c12, c13,c10, c11);
99                         let u32x4(d10, d11, d12, d13) = $d;
100                         $d = u32x4(d13, d10, d11, d12);
101                 }}
102         }
103
104         macro_rules! state_to_buffer {
105                 ($state: expr, $output: expr) => {{
106                         let u32x4(a1, a2, a3, a4) = $state.a;
107                         let u32x4(b1, b2, b3, b4) = $state.b;
108                         let u32x4(c1, c2, c3, c4) = $state.c;
109                         let u32x4(d1, d2, d3, d4) = $state.d;
110                         let lens = [
111                                 a1,a2,a3,a4,
112                                 b1,b2,b3,b4,
113                                 c1,c2,c3,c4,
114                                 d1,d2,d3,d4
115                         ];
116                         for i in 0..lens.len() {
117                                 $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
118                         }
119                 }}
120         }
121
122         macro_rules! round{
123                 ($state: expr) => {{
124                         $state.a = $state.a + $state.b;
125                         rotate!($state.d, $state.a, 16);
126                         $state.c = $state.c + $state.d;
127                         rotate!($state.b, $state.c, 12);
128                         $state.a = $state.a + $state.b;
129                         rotate!($state.d, $state.a, 8);
130                         $state.c = $state.c + $state.d;
131                         rotate!($state.b, $state.c, 7);
132                 }}
133         }
134
135         macro_rules! rotate {
136                 ($a: expr, $b: expr, $rot: expr) => {{
137                         let v = $a ^ $b;
138                         let r = 32 - $rot;
139                         let right = v >> r;
140                         $a = (v << $rot) ^ right
141                 }}
142         }
143
144         impl ChaCha20 {
145                 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
146                         assert!(key.len() == 16 || key.len() == 32);
147                         assert!(nonce.len() == 8 || nonce.len() == 12);
148
149                         ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
150                 }
151
152                 /// Get one block from a ChaCha stream.
153                 pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
154                         let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
155                         let mut chacha_bytes = [0; 32];
156                         chacha.process_in_place(&mut chacha_bytes);
157                         chacha_bytes
158                 }
159
160                 /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
161                 /// `src` in a second call will decrypt it.
162                 pub fn encrypt_single_block(
163                         key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
164                 ) {
165                         debug_assert_eq!(dest.len(), src.len());
166                         debug_assert!(dest.len() <= 32);
167
168                         let block = ChaCha20::get_single_block(key, nonce);
169                         for i in 0..dest.len() {
170                                 dest[i] = block[i] ^ src[i];
171                         }
172                 }
173
174                 /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
175                 pub fn encrypt_single_block_in_place(
176                         key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
177                 ) {
178                         let block = ChaCha20::get_single_block(key, nonce);
179                         for i in 0..bytes.len() {
180                                 bytes[i] = block[i] ^ bytes[i];
181                         }
182                 }
183
184                 fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
185                         let constant = match key.len() {
186                                 16 => b"expand 16-byte k",
187                                 32 => b"expand 32-byte k",
188                                 _  => unreachable!(),
189                         };
190                         ChaChaState {
191                                 a: u32x4::from_bytes(&constant[0..16]),
192                                 b: u32x4::from_bytes(&key[0..16]),
193                                 c: if key.len() == 16 {
194                                         u32x4::from_bytes(&key[0..16])
195                                 } else {
196                                         u32x4::from_bytes(&key[16..32])
197                                 },
198                                 d: if nonce.len() == 16 {
199                                         u32x4::from_bytes(&nonce[0..16])
200                                 } else if nonce.len() == 12 {
201                                         let mut nonce4 = [0; 4*4];
202                                         nonce4[4..].copy_from_slice(nonce);
203                                         u32x4::from_bytes(&nonce4)
204                                 } else {
205                                         let mut nonce4 = [0; 4*4];
206                                         nonce4[8..].copy_from_slice(nonce);
207                                         u32x4::from_bytes(&nonce4)
208                                 }
209                         }
210                 }
211
212                 // put the the next BLOCK_SIZE keystream bytes into self.output
213                 fn update(&mut self) {
214                         let mut state = self.state;
215
216                         for _ in 0..10 {
217                                 round!(state);
218                                 swizzle!(state.b, state.c, state.d);
219                                 round!(state);
220                                 swizzle!(state.d, state.c, state.b);
221                         }
222                         state.a = state.a + self.state.a;
223                         state.b = state.b + self.state.b;
224                         state.c = state.c + self.state.c;
225                         state.d = state.d + self.state.d;
226
227                         state_to_buffer!(state, self.output);
228
229                         self.state.d = self.state.d + u32x4(1, 0, 0, 0);
230                         let u32x4(c12, _, _, _) = self.state.d;
231                         if c12 == 0 {
232                                 // we could increment the other counter word with an 8 byte nonce
233                                 // but other implementations like boringssl have this same
234                                 // limitation
235                                 panic!("counter is exhausted");
236                         }
237
238                         self.offset = 0;
239                 }
240
241                 #[inline] // Useful cause input may be 0s on stack that should be optimized out
242                 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
243                         assert!(input.len() == output.len());
244                         let len = input.len();
245                         let mut i = 0;
246                         while i < len {
247                                 // If there is no keystream available in the output buffer,
248                                 // generate the next block.
249                                 if self.offset == BLOCK_SIZE {
250                                         self.update();
251                                 }
252
253                                 // Process the min(available keystream, remaining input length).
254                                 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
255                                 // explicitly assert lengths to avoid bounds checks:
256                                 assert!(output.len() >= i + count);
257                                 assert!(input.len() >= i + count);
258                                 assert!(self.output.len() >= self.offset + count);
259                                 for j in 0..count {
260                                         output[i + j] = input[i + j] ^ self.output[self.offset + j];
261                                 }
262                                 i += count;
263                                 self.offset += count;
264                         }
265                 }
266
267                 pub fn process_in_place(&mut self, input_output: &mut [u8]) {
268                         let len = input_output.len();
269                         let mut i = 0;
270                         while i < len {
271                                 // If there is no keystream available in the output buffer,
272                                 // generate the next block.
273                                 if self.offset == BLOCK_SIZE {
274                                         self.update();
275                                 }
276
277                                 // Process the min(available keystream, remaining input length).
278                                 let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
279                                 // explicitly assert lengths to avoid bounds checks:
280                                 assert!(input_output.len() >= i + count);
281                                 assert!(self.output.len() >= self.offset + count);
282                                 for j in 0..count {
283                                         input_output[i + j] ^= self.output[self.offset + j];
284                                 }
285                                 i += count;
286                                 self.offset += count;
287                         }
288                 }
289
290                 #[cfg(test)]
291                 pub fn seek_to_block(&mut self, block_offset: u32) {
292                         self.state.d.0 = block_offset;
293                         self.update();
294                 }
295         }
296 }
297 #[cfg(not(fuzzing))]
298 pub use self::real_chacha::ChaCha20;
299
300 #[cfg(fuzzing)]
301 mod fuzzy_chacha {
302         pub struct ChaCha20 {}
303
304         impl ChaCha20 {
305                 pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
306                         assert!(key.len() == 16 || key.len() == 32);
307                         assert!(nonce.len() == 8 || nonce.len() == 12);
308                         Self {}
309                 }
310
311                 pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
312                         [0; 32]
313                 }
314
315                 pub fn encrypt_single_block(
316                         _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
317                 ) {
318                         debug_assert_eq!(dest.len(), src.len());
319                         debug_assert!(dest.len() <= 32);
320                 }
321
322                 pub fn encrypt_single_block_in_place(
323                         _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
324                 ) {}
325
326                 pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
327                         output.copy_from_slice(input);
328                 }
329
330                 pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
331         }
332 }
333 #[cfg(fuzzing)]
334 pub use self::fuzzy_chacha::ChaCha20;
335
336 #[cfg(test)]
337 mod test {
338         use alloc::vec;
339         use alloc::vec::{Vec};
340         use core::convert::TryInto;
341         use core::iter::repeat;
342
343         use super::ChaCha20;
344
345         #[test]
346         fn test_chacha20_256_tls_vectors() {
347                 struct TestVector {
348                         key:   [u8; 32],
349                         nonce: [u8; 8],
350                         keystream: Vec<u8>,
351                 }
352                 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
353                 let test_vectors = vec!(
354                         TestVector{
355                                 key: [
356                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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                                 ],
361                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
362                                 keystream: vec!(
363                                         0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
364                                         0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
365                                         0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
366                                         0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
367                                         0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
368                                         0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
369                                         0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
370                                         0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
371                                 ),
372                         }, TestVector{
373                                 key: [
374                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01,
378                                 ],
379                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
380                                 keystream: vec!(
381                                         0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
382                                         0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
383                                         0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
384                                         0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
385                                         0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
386                                         0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
387                                         0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
388                                         0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
389                                 ),
390                         }, TestVector{
391                                 key: [
392                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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                                 ],
397                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
398                                 keystream: vec!(
399                                         0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
400                                         0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
401                                         0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
402                                         0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
403                                         0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
404                                         0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
405                                         0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
406                                         0x44, 0x5f, 0x41, 0xe3,
407                                 ),
408                         }, TestVector{
409                                 key: [
410                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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                                 ],
415                                 nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
416                                 keystream: vec!(
417                                         0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
418                                         0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
419                                         0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
420                                         0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
421                                         0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
422                                         0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
423                                         0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
424                                         0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
425                                 ),
426                         }, TestVector{
427                                 key: [
428                                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
429                                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
430                                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
431                                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
432                                 ],
433                                 nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
434                                 keystream: vec!(
435                                         0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
436                                         0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
437                                         0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
438                                         0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
439                                         0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
440                                         0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
441                                         0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
442                                         0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
443                                         0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
444                                         0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
445                                         0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
446                                         0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
447                                         0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
448                                         0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
449                                         0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
450                                         0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
451                                         0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
452                                         0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
453                                         0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
454                                         0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
455                                         0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
456                                         0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
457                                         0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
458                                         0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
459                                         0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
460                                         0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
461                                         0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
462                                         0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
463                                         0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
464                                         0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
465                                         0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
466                                         0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
467                                 ),
468                         },
469                 );
470
471                 for tv in test_vectors.iter() {
472                         let mut c = ChaCha20::new(&tv.key, &tv.nonce);
473                         let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
474                         let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
475                         c.process(&input[..], &mut output[..]);
476                         assert_eq!(output, tv.keystream);
477                 }
478         }
479
480         #[test]
481         fn test_chacha20_256_tls_vectors_96_nonce() {
482                 struct TestVector {
483                         key:   [u8; 32],
484                         nonce: [u8; 12],
485                         keystream: Vec<u8>,
486                 }
487                 // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
488                 let test_vectors = vec!(
489                         TestVector{
490                                 key: [
491                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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                                 ],
496                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
497                                 keystream: vec!(
498                                         0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
499                                         0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
500                                         0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
501                                         0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
502                                         0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
503                                         0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
504                                         0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
505                                         0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
506                                 ),
507                         }, TestVector{
508                                 key: [
509                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01,
513                                 ],
514                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
515                                 keystream: vec!(
516                                         0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
517                                         0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
518                                         0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
519                                         0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
520                                         0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
521                                         0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
522                                         0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
523                                         0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
524                                 ),
525                         }, TestVector{
526                                 key: [
527                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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                                 ],
532                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
533                                 keystream: vec!(
534                                         0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
535                                         0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
536                                         0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
537                                         0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
538                                         0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
539                                         0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
540                                         0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
541                                         0x44, 0x5f, 0x41, 0xe3,
542                                 ),
543                         }, TestVector{
544                                 key: [
545                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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                                 ],
550                                 nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
551                                 keystream: vec!(
552                                         0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
553                                         0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
554                                         0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
555                                         0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
556                                         0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
557                                         0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
558                                         0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
559                                         0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
560                                 ),
561                         }, TestVector{
562                                 key: [
563                                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
564                                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
565                                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
566                                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
567                                 ],
568                                 nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
569                                 keystream: vec!(
570                                         0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
571                                         0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
572                                         0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
573                                         0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
574                                         0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
575                                         0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
576                                         0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
577                                         0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
578                                         0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
579                                         0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
580                                         0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
581                                         0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
582                                         0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
583                                         0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
584                                         0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
585                                         0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
586                                         0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
587                                         0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
588                                         0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
589                                         0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
590                                         0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
591                                         0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
592                                         0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
593                                         0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
594                                         0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
595                                         0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
596                                         0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
597                                         0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
598                                         0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
599                                         0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
600                                         0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
601                                         0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
602                                 ),
603                         },
604                 );
605
606                 for tv in test_vectors.iter() {
607                         let mut c = ChaCha20::new(&tv.key, &tv.nonce);
608                         let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
609                         let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
610                         c.process(&input[..], &mut output[..]);
611                         assert_eq!(output, tv.keystream);
612                 }
613         }
614
615         #[test]
616         fn get_single_block() {
617                 // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
618                 // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
619                 // bytes.
620                 let key = [
621                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
622                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
623                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
624                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
625                 ];
626                 let nonce_16bytes = [
627                         0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
628                 ];
629                 let counter_pos = &nonce_16bytes[..4];
630                 let nonce_12bytes = &nonce_16bytes[4..];
631
632                 // Initialize a ChaCha20 instance with its counter starting at 0.
633                 let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
634                 // Seek its counter to the block at counter_pos.
635                 chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
636                 let mut block_bytes = [0; 32];
637                 chacha20.process_in_place(&mut block_bytes);
638
639                 assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
640         }
641
642         #[test]
643         fn encrypt_single_block() {
644                 let key = [
645                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
646                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
647                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
648                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
649                 ];
650                 let nonce = [
651                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
652                         0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
653                 ];
654                 let bytes = [1; 32];
655
656                 let mut encrypted_bytes = [0; 32];
657                 ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
658
659                 let mut decrypted_bytes = [0; 32];
660                 ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
661
662                 assert_eq!(bytes, decrypted_bytes);
663         }
664
665         #[test]
666         fn encrypt_single_block_in_place() {
667                 let key = [
668                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
669                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
670                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
671                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
672                 ];
673                 let nonce = [
674                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
675                         0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
676                 ];
677                 let unencrypted_bytes = [1; 32];
678                 let mut bytes = unencrypted_bytes;
679
680                 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
681                 assert_ne!(bytes, unencrypted_bytes);
682
683                 ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
684                 assert_eq!(bytes, unencrypted_bytes);
685         }
686 }