lightning_storage_server/
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
12mod real_chacha {
13    use core::cmp;
14    use core::convert::TryInto;
15
16    #[derive(Clone, Copy, PartialEq, Eq)]
17    #[allow(non_camel_case_types)]
18    struct u32x4(pub u32, pub u32, pub u32, pub u32);
19    impl ::core::ops::Add for u32x4 {
20        type Output = u32x4;
21        fn add(self, rhs: u32x4) -> u32x4 {
22            u32x4(
23                self.0.wrapping_add(rhs.0),
24                self.1.wrapping_add(rhs.1),
25                self.2.wrapping_add(rhs.2),
26                self.3.wrapping_add(rhs.3),
27            )
28        }
29    }
30    impl ::core::ops::Sub for u32x4 {
31        type Output = u32x4;
32        fn sub(self, rhs: u32x4) -> u32x4 {
33            u32x4(
34                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    }
41    impl ::core::ops::BitXor for u32x4 {
42        type Output = u32x4;
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<u32x4> for u32x4 {
48        type Output = u32x4;
49        fn shr(self, rhs: u32x4) -> u32x4 {
50            u32x4(self.0 >> rhs.0, self.1 >> rhs.1, self.2 >> rhs.2, self.3 >> rhs.3)
51        }
52    }
53    impl ::core::ops::Shl<u32x4> for u32x4 {
54        type Output = u32x4;
55        fn shl(self, rhs: u32x4) -> u32x4 {
56            u32x4(self.0 << rhs.0, self.1 << rhs.1, self.2 << rhs.2, self.3 << rhs.3)
57        }
58    }
59    impl u32x4 {
60        fn from_bytes(bytes: &[u8]) -> Self {
61            assert_eq!(bytes.len(), 4 * 4);
62            Self(
63                u32::from_le_bytes(bytes[0 * 4..1 * 4].try_into().expect("len is 4")),
64                u32::from_le_bytes(bytes[1 * 4..2 * 4].try_into().expect("len is 4")),
65                u32::from_le_bytes(bytes[2 * 4..3 * 4].try_into().expect("len is 4")),
66                u32::from_le_bytes(bytes[3 * 4..4 * 4].try_into().expect("len is 4")),
67            )
68        }
69    }
70
71    const BLOCK_SIZE: usize = 64;
72
73    #[derive(Clone, Copy)]
74    struct ChaChaState {
75        a: u32x4,
76        b: u32x4,
77        c: u32x4,
78        d: u32x4,
79    }
80
81    #[derive(Copy)]
82    pub struct ChaCha20 {
83        state: ChaChaState,
84        output: [u8; BLOCK_SIZE],
85        offset: usize,
86    }
87
88    impl Clone for ChaCha20 {
89        fn clone(&self) -> ChaCha20 {
90            *self
91        }
92    }
93
94    macro_rules! swizzle {
95        ($b: expr, $c: expr, $d: expr) => {{
96            let u32x4(b10, b11, b12, b13) = $b;
97            $b = u32x4(b11, b12, b13, b10);
98            let u32x4(c10, c11, c12, c13) = $c;
99            $c = u32x4(c12, c13, c10, c11);
100            let u32x4(d10, d11, d12, d13) = $d;
101            $d = u32x4(d13, d10, d11, d12);
102        }};
103    }
104
105    macro_rules! state_to_buffer {
106        ($state: expr, $output: expr) => {{
107            let u32x4(a1, a2, a3, a4) = $state.a;
108            let u32x4(b1, b2, b3, b4) = $state.b;
109            let u32x4(c1, c2, c3, c4) = $state.c;
110            let u32x4(d1, d2, d3, d4) = $state.d;
111            let lens = [a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4];
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 {
157                state: ChaCha20::expand(key, nonce),
158                output: [0u8; BLOCK_SIZE],
159                offset: 64,
160            };
161            let mut chacha_bytes = [0; 32];
162            chacha.process_in_place(&mut chacha_bytes);
163            chacha_bytes
164        }
165
166        fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
167            let constant = match key.len() {
168                16 => b"expand 16-byte k",
169                32 => b"expand 32-byte k",
170                _ => unreachable!(),
171            };
172            ChaChaState {
173                a: u32x4::from_bytes(&constant[0..16]),
174                b: u32x4::from_bytes(&key[0..16]),
175                c: if key.len() == 16 {
176                    u32x4::from_bytes(&key[0..16])
177                } else {
178                    u32x4::from_bytes(&key[16..32])
179                },
180                d: if nonce.len() == 16 {
181                    u32x4::from_bytes(&nonce[0..16])
182                } else if nonce.len() == 12 {
183                    let mut nonce4 = [0; 4 * 4];
184                    nonce4[4..].copy_from_slice(nonce);
185                    u32x4::from_bytes(&nonce4)
186                } else {
187                    let mut nonce4 = [0; 4 * 4];
188                    nonce4[8..].copy_from_slice(nonce);
189                    u32x4::from_bytes(&nonce4)
190                },
191            }
192        }
193
194        // put the the next BLOCK_SIZE keystream bytes into self.output
195        fn update(&mut self) {
196            let mut state = self.state;
197
198            for _ in 0..10 {
199                round!(state);
200                swizzle!(state.b, state.c, state.d);
201                round!(state);
202                swizzle!(state.d, state.c, state.b);
203            }
204            state.a = state.a + self.state.a;
205            state.b = state.b + self.state.b;
206            state.c = state.c + self.state.c;
207            state.d = state.d + self.state.d;
208
209            state_to_buffer!(state, self.output);
210
211            self.state.d = self.state.d + u32x4(1, 0, 0, 0);
212            let u32x4(c12, _, _, _) = self.state.d;
213            if c12 == 0 {
214                // we could increment the other counter word with an 8 byte nonce
215                // but other implementations like boringssl have this same
216                // limitation
217                panic!("counter is exhausted");
218            }
219
220            self.offset = 0;
221        }
222
223        #[inline] // Useful cause input may be 0s on stack that should be optimized out
224        pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
225            assert!(input.len() == output.len());
226            let len = input.len();
227            let mut i = 0;
228            while i < len {
229                // If there is no keystream available in the output buffer,
230                // generate the next block.
231                if self.offset == BLOCK_SIZE {
232                    self.update();
233                }
234
235                // Process the min(available keystream, remaining input length).
236                let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
237                // explicitly assert lengths to avoid bounds checks:
238                assert!(output.len() >= i + count);
239                assert!(input.len() >= i + count);
240                assert!(self.output.len() >= self.offset + count);
241                for j in 0..count {
242                    output[i + j] = input[i + j] ^ self.output[self.offset + j];
243                }
244                i += count;
245                self.offset += count;
246            }
247        }
248
249        pub fn process_in_place(&mut self, input_output: &mut [u8]) {
250            let len = input_output.len();
251            let mut i = 0;
252            while i < len {
253                // If there is no keystream available in the output buffer,
254                // generate the next block.
255                if self.offset == BLOCK_SIZE {
256                    self.update();
257                }
258
259                // Process the min(available keystream, remaining input length).
260                let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
261                // explicitly assert lengths to avoid bounds checks:
262                assert!(input_output.len() >= i + count);
263                assert!(self.output.len() >= self.offset + count);
264                for j in 0..count {
265                    input_output[i + j] ^= self.output[self.offset + j];
266                }
267                i += count;
268                self.offset += count;
269            }
270        }
271
272        #[cfg(test)]
273        pub fn seek_to_block(&mut self, block_offset: u32) {
274            self.state.d.0 = block_offset;
275            self.update();
276        }
277    }
278}
279pub use self::real_chacha::ChaCha20;
280
281#[cfg(test)]
282mod test {
283    use core::iter::repeat;
284
285    use super::ChaCha20;
286    use std::convert::TryInto;
287
288    #[test]
289    fn test_chacha20_256_tls_vectors() {
290        struct TestVector {
291            key: [u8; 32],
292            nonce: [u8; 8],
293            keystream: Vec<u8>,
294        }
295        // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
296        let test_vectors = vec![
297            TestVector {
298                key: [
299                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302                ],
303                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
304                keystream: vec![
305                    0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53,
306                    0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36,
307                    0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48,
308                    0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4,
309                    0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
310                ],
311            },
312            TestVector {
313                key: [
314                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316                    0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
317                ],
318                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
319                keystream: vec![
320                    0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, 0xd7, 0x73, 0x6e, 0x7b, 0x20,
321                    0x8e, 0x3c, 0x96, 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, 0x4f, 0x45,
322                    0x09, 0x52, 0xed, 0x43, 0x2d, 0x41, 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66,
323                    0xd2, 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c, 0x53, 0xd7, 0x92, 0xb1,
324                    0xc4, 0x3f, 0xea, 0x81, 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
325                ],
326            },
327            TestVector {
328                key: [
329                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332                ],
333                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
334                keystream: vec![
335                    0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, 0xe7, 0x86, 0xdc, 0x63, 0x97,
336                    0x3f, 0x65, 0x3a, 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, 0x4f, 0xcb,
337                    0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31, 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08,
338                    0x45, 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b, 0x52, 0x77, 0x06, 0x2e,
339                    0xb7, 0xa0, 0x43, 0x3e, 0x44, 0x5f, 0x41, 0xe3,
340                ],
341            },
342            TestVector {
343                key: [
344                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347                ],
348                nonce: [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
349                keystream: vec![
350                    0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 0xf5, 0xcf, 0x35, 0xbd, 0x3d,
351                    0xd3, 0x3b, 0x80, 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 0x33, 0x96,
352                    0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5,
353                    0x3c, 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, 0x5d, 0xdc, 0x49, 0x7a,
354                    0x0b, 0x46, 0x6e, 0x7d, 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
355                ],
356            },
357            TestVector {
358                key: [
359                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
360                    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
361                    0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
362                ],
363                nonce: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07],
364                keystream: vec![
365                    0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, 0x82, 0x10, 0x5f, 0xfb, 0x64,
366                    0x0b, 0xb7, 0x75, 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, 0xec, 0x01,
367                    0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1, 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46,
368                    0x41, 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, 0x05, 0xd3, 0xbe, 0x59,
369                    0xea, 0x1c, 0x53, 0xf1, 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, 0x38,
370                    0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94, 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a,
371                    0xde, 0x66, 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58, 0x89, 0xfb, 0x60,
372                    0xe8, 0x46, 0x29, 0xc9, 0xbd, 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
373                    0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, 0x09, 0xa7, 0xe7, 0x78, 0x49,
374                    0x2b, 0x56, 0x2e, 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7, 0x9d, 0xb9,
375                    0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f,
376                    0xc3, 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, 0x97, 0xa5, 0xf5, 0x76,
377                    0xfe, 0x06, 0x40, 0x25, 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, 0x07,
378                    0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c,
379                    0xc9, 0xc4, 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, 0x0e, 0xaf, 0x46,
380                    0xf7, 0x6d, 0xad, 0x39, 0x79, 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
381                    0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, 0x94, 0xdf, 0x76, 0x28, 0xfe,
382                    0x4e, 0xaa, 0xf2, 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, 0xd0, 0xf9,
383                    0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09, 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40,
384                    0x7a, 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
385                ],
386            },
387        ];
388
389        for tv in test_vectors.iter() {
390            let mut c = ChaCha20::new(&tv.key, &tv.nonce);
391            let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
392            let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
393            c.process(&input[..], &mut output[..]);
394            assert_eq!(output, tv.keystream);
395        }
396    }
397
398    #[test]
399    fn test_chacha20_256_tls_vectors_96_nonce() {
400        struct TestVector {
401            key: [u8; 32],
402            nonce: [u8; 12],
403            keystream: Vec<u8>,
404        }
405        // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
406        let test_vectors = vec![
407            TestVector {
408                key: [
409                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412                ],
413                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
414                keystream: vec![
415                    0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53,
416                    0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36,
417                    0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48,
418                    0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4,
419                    0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
420                ],
421            },
422            TestVector {
423                key: [
424                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426                    0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
427                ],
428                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
429                keystream: vec![
430                    0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, 0xd7, 0x73, 0x6e, 0x7b, 0x20,
431                    0x8e, 0x3c, 0x96, 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, 0x4f, 0x45,
432                    0x09, 0x52, 0xed, 0x43, 0x2d, 0x41, 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66,
433                    0xd2, 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c, 0x53, 0xd7, 0x92, 0xb1,
434                    0xc4, 0x3f, 0xea, 0x81, 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
435                ],
436            },
437            TestVector {
438                key: [
439                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442                ],
443                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
444                keystream: vec![
445                    0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, 0xe7, 0x86, 0xdc, 0x63, 0x97,
446                    0x3f, 0x65, 0x3a, 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, 0x4f, 0xcb,
447                    0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31, 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08,
448                    0x45, 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b, 0x52, 0x77, 0x06, 0x2e,
449                    0xb7, 0xa0, 0x43, 0x3e, 0x44, 0x5f, 0x41, 0xe3,
450                ],
451            },
452            TestVector {
453                key: [
454                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457                ],
458                nonce: [0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
459                keystream: vec![
460                    0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 0xf5, 0xcf, 0x35, 0xbd, 0x3d,
461                    0xd3, 0x3b, 0x80, 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 0x33, 0x96,
462                    0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5,
463                    0x3c, 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, 0x5d, 0xdc, 0x49, 0x7a,
464                    0x0b, 0x46, 0x6e, 0x7d, 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
465                ],
466            },
467            TestVector {
468                key: [
469                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
470                    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
471                    0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
472                ],
473                nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07],
474                keystream: vec![
475                    0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, 0x82, 0x10, 0x5f, 0xfb, 0x64,
476                    0x0b, 0xb7, 0x75, 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, 0xec, 0x01,
477                    0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1, 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46,
478                    0x41, 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, 0x05, 0xd3, 0xbe, 0x59,
479                    0xea, 0x1c, 0x53, 0xf1, 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, 0x38,
480                    0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94, 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a,
481                    0xde, 0x66, 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58, 0x89, 0xfb, 0x60,
482                    0xe8, 0x46, 0x29, 0xc9, 0xbd, 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
483                    0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, 0x09, 0xa7, 0xe7, 0x78, 0x49,
484                    0x2b, 0x56, 0x2e, 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7, 0x9d, 0xb9,
485                    0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f,
486                    0xc3, 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, 0x97, 0xa5, 0xf5, 0x76,
487                    0xfe, 0x06, 0x40, 0x25, 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, 0x07,
488                    0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c,
489                    0xc9, 0xc4, 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, 0x0e, 0xaf, 0x46,
490                    0xf7, 0x6d, 0xad, 0x39, 0x79, 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
491                    0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, 0x94, 0xdf, 0x76, 0x28, 0xfe,
492                    0x4e, 0xaa, 0xf2, 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, 0xd0, 0xf9,
493                    0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09, 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40,
494                    0x7a, 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
495                ],
496            },
497        ];
498
499        for tv in test_vectors.iter() {
500            let mut c = ChaCha20::new(&tv.key, &tv.nonce);
501            let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
502            let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
503            c.process(&input[..], &mut output[..]);
504            assert_eq!(output, tv.keystream);
505        }
506    }
507
508    #[test]
509    fn get_single_block() {
510        // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
511        // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
512        // bytes.
513        let key = [
514            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
515            0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
516            0x1c, 0x1d, 0x1e, 0x1f,
517        ];
518        let nonce_16bytes = [
519            0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
520            0x0a, 0x0b,
521        ];
522        let counter_pos = &nonce_16bytes[..4];
523        let nonce_12bytes = &nonce_16bytes[4..];
524
525        // Initialize a ChaCha20 instance with its counter starting at 0.
526        let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
527        // Seek its counter to the block at counter_pos.
528        chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
529        let mut block_bytes = [0; 32];
530        chacha20.process_in_place(&mut block_bytes);
531
532        assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
533    }
534}