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