rust_salsa20/
lib.rs

1//! # Salsa20
2//! Salsa20 is a stream cipher built on a pseudo-random function based on
3//! add-rotate-xor operations — 32-bit addition, bitwise addition and
4//! rotation operations
5//!
6//! ## Examples
7//!
8//! ### Generate
9//! ```
10//! extern crate rust_salsa20;
11//! use rust_salsa20::{Salsa20, Key::Key32};
12//!
13//! fn main() {
14//!     let key = Key32([
15//!         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
16//!         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
17//!     ]);
18//!     let nonce = [1, 2, 3, 4, 5, 6, 7, 8];
19//!     let mut salsa = Salsa20::new(key, nonce, 0);
20//!     let mut buffer = [0; 10];
21//!     salsa.generate(&mut buffer);
22//!
23//!     assert_eq!(buffer, [45, 134, 38, 166, 142, 36, 28, 146, 116, 157]);
24//! }
25//! ```
26//!
27//! ### Encrypt
28//! ```
29//! extern crate rust_salsa20;
30//! use rust_salsa20::{Salsa20, Key::Key32};
31//!
32//! fn main() {
33//!     let key = Key32([
34//!         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
35//!         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
36//!     ]);
37//!     let nonce = [1, 2, 3, 4, 5, 6, 7, 8];
38//!     let mut salsa = Salsa20::new(key, nonce, 0);
39//!     let mut buffer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
40//!     salsa.encrypt(&mut buffer);
41//!
42//!     assert_eq!(buffer, [44, 132, 37, 162, 139, 34, 27, 154, 125, 157]);
43//! }
44//! ```
45
46#![no_std]
47
48mod utils;
49use core::fmt;
50use crate::utils::{u8_to_u32, xor_from_slice};
51
52fn quarterround(y0: u32, y1: u32, y2: u32, y3: u32) -> [u32; 4] {
53    let y1 = y1 ^ y0.wrapping_add(y3).rotate_left(7);
54    let y2 = y2 ^ y1.wrapping_add(y0).rotate_left(9);
55    let y3 = y3 ^ y2.wrapping_add(y1).rotate_left(13);
56    let y0 = y0 ^ y3.wrapping_add(y2).rotate_left(18);
57
58    [y0, y1, y2, y3]
59}
60
61fn columnround(y: [u32; 16]) -> [u32; 16] {
62    let [
63        [z0, z4, z8, z12],
64        [z5, z9, z13, z1],
65        [z10, z14, z2, z6],
66        [z15, z3, z7, z11]
67    ] = [
68        quarterround(y[0], y[4], y[8], y[12]),
69        quarterround(y[5], y[9], y[13], y[1]),
70        quarterround(y[10], y[14], y[2], y[6]),
71        quarterround(y[15], y[3], y[7], y[11]),
72    ];
73
74    [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15]
75}
76
77fn rowround(y: [u32; 16]) -> [u32; 16] {
78    let [
79        [z0, z1, z2, z3],
80        [z5, z6, z7, z4],
81        [z10, z11, z8, z9],
82        [z15, z12, z13, z14]
83    ] = [
84        quarterround(y[0], y[1], y[2], y[3]),
85        quarterround(y[5], y[6], y[7], y[4]),
86        quarterround(y[10], y[11], y[8], y[9]),
87        quarterround(y[15], y[12], y[13], y[14])
88    ];
89
90    [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15]
91}
92
93fn doubleround(y: [u32; 16]) -> [u32; 16] {
94    rowround(columnround(y))
95}
96
97#[derive(Clone, Copy)]
98struct Overflow {
99    buffer: [u8; 64],
100    offset: usize
101}
102
103impl Overflow {
104    fn new(buffer: [u8; 64], offset: usize) -> Overflow {
105        Overflow { buffer, offset }
106    }
107
108    fn modify<F>(&mut self, buffer: &mut [u8], modifier: F)
109        where F: Fn(&mut [u8], &[u8])
110    {
111        let offset = self.offset;
112        self.offset += buffer.len();
113        modifier(buffer, &self.buffer[offset..self.offset]);
114    }
115}
116
117impl fmt::Debug for Overflow {
118    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
119        formatter
120            .debug_struct("Overflow")
121            .field("buffer", &&self.buffer[..])
122            .field("offset", &self.offset)
123            .finish()
124    }
125}
126
127/// Key for Salsa20, 32-byte or 16-byte sequence
128#[derive(Clone, Copy, Debug)]
129pub enum Key {
130    Key16([u8; 16]),
131    Key32([u8; 32])
132}
133
134#[derive(Clone, Copy, Debug)]
135struct Generator {
136    init_matrix: [u32; 16],
137    cround_matrix: [u32; 16],
138    dround_values: [u32; 4],
139    counter: u64
140}
141
142impl Generator {
143    fn new(key: Key, nonce: [u8; 8], counter: u64) -> Generator {
144        let mut init_matrix = [0; 16];
145        init_matrix[0] = 1634760805;
146        init_matrix[15] = 1797285236;
147        init_matrix[8] = counter as u32;
148        init_matrix[9] = (counter >> 32) as u32;
149        u8_to_u32(&nonce[..], &mut init_matrix[6..8]);
150
151        match key {
152            Key::Key16(key) => {
153                u8_to_u32(&key[..], &mut init_matrix[1..5]);
154                u8_to_u32(&key[..], &mut init_matrix[11..15]);
155                init_matrix[5] = 824206446;
156                init_matrix[10] = 2036477238;
157            }
158            Key::Key32(key) => {
159                u8_to_u32(&key[..16], &mut init_matrix[1..5]);
160                u8_to_u32(&key[16..], &mut init_matrix[11..15]);
161                init_matrix[5] = 857760878;
162                init_matrix[10] = 2036477234;
163            }
164        }
165
166        let cround_matrix = columnround(init_matrix);
167        let dround_values = quarterround(
168            cround_matrix[5],
169            cround_matrix[6],
170            cround_matrix[7],
171            cround_matrix[4]
172        );
173
174        Generator { init_matrix, cround_matrix, dround_values, counter }
175    }
176
177    fn first_doubleround(&self) -> [u32; 16] {
178        let [r5, r6, r7, r4] = self.dround_values;
179        let [
180            [r0, r1, r2, r3],
181            [r10, r11, r8, r9],
182            [r15, r12, r13, r14]
183        ] = [
184            quarterround(
185                self.cround_matrix[0],
186                self.cround_matrix[1],
187                self.cround_matrix[2],
188                self.cround_matrix[3]
189            ),
190            quarterround(
191                self.cround_matrix[10],
192                self.cround_matrix[11],
193                self.cround_matrix[8],
194                self.cround_matrix[9]
195            ),
196            quarterround(
197                self.cround_matrix[15],
198                self.cround_matrix[12],
199                self.cround_matrix[13],
200                self.cround_matrix[14]
201            )
202        ];
203
204        [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15]
205    }
206
207    fn set_counter(&mut self, counter: u64) {
208        self.counter = counter;
209        self.init_matrix[8] = counter as u32;
210        let [z0, z4, z8, z12] = quarterround(
211            self.init_matrix[0],
212            self.init_matrix[4],
213            self.init_matrix[8],
214            self.init_matrix[12]
215        );
216        self.cround_matrix[0] = z0;
217        self.cround_matrix[8] = z8;
218        self.cround_matrix[12] = z12;
219
220        if counter > 0xffffffff_u64 {
221            self.init_matrix[9] = (counter >> 32) as u32;
222            let [z5, z9, z13, z1] = quarterround(
223                self.init_matrix[5],
224                self.init_matrix[9],
225                self.init_matrix[13],
226                self.init_matrix[1]
227            );
228
229            self.cround_matrix[1] = z1;
230            self.cround_matrix[9] = z9;
231            self.cround_matrix[13] = z13;
232
233            self.dround_values = quarterround(
234                z5,
235                self.cround_matrix[6],
236                self.cround_matrix[7],
237                z4
238            );
239        }
240    }
241
242    fn next(&mut self) -> [u8; 64] {
243        let mut buffer = [0; 64];
244        (0..9)
245            .fold(self.first_doubleround(), |block, _| doubleround(block))
246            .iter()
247            .zip(self.init_matrix.iter())
248            .enumerate()
249            .for_each(|(index, (drounds_value, &init_value))| {
250                let offset = index * 4;
251                let sum = drounds_value.wrapping_add(init_value);
252                buffer[offset..offset + 4].copy_from_slice(&sum.to_le_bytes());
253            });
254
255        self.set_counter(self.counter.wrapping_add(1));
256        buffer
257    }
258}
259
260/// The Salsa20 stream cipher
261#[derive(Clone, Copy, Debug)]
262pub struct Salsa20 {
263    generator: Generator,
264    overflow: Overflow
265}
266
267impl Salsa20 {
268    /// creates Salsa20 stream cipher
269    /// # Arguments
270    /// * `key` - secret key, 32-byte or 16-byte sequence
271    /// * `nounce` - 8-byte unique sequence
272    /// * `counter` - 8-byte unique number of each 64-byte block
273    pub fn new(key: Key, nonce: [u8; 8], counter: u64) -> Salsa20 {
274        let overflow = Overflow::new([0; 64], 64);
275        let generator = Generator::new(key, nonce, counter);
276        Salsa20 { generator, overflow }
277    }
278
279    fn modify<F>(&mut self, buffer: &mut [u8], modifier: &F)
280        where F: Fn(&mut [u8], &[u8])
281    {
282        let buffer_len = buffer.len();
283        let overflow_len = 64 - self.overflow.offset;
284
285        if overflow_len != 0 {
286            if buffer_len >= overflow_len {
287                self.overflow.modify(&mut buffer[..overflow_len], modifier);
288            } else {
289                self.overflow.modify(&mut buffer[..], modifier);
290                return;
291            }
292        }
293
294        let last_block_offset = buffer_len - (buffer_len - overflow_len) % 64;
295
296        for offset in (overflow_len..last_block_offset).step_by(64) {
297            modifier(&mut buffer[offset..offset + 64], &self.generator.next());
298        }
299
300        if last_block_offset != buffer_len {
301            self.overflow = Overflow::new(self.generator.next(), 0);
302            self.overflow.modify(&mut buffer[last_block_offset..], modifier);
303        }
304    }
305
306    /// sets unique number of next 64-byte block
307    pub fn set_counter(&mut self, counter: u64) {
308        if counter != self.generator.counter {
309            self.generator.set_counter(counter);
310        }
311        self.overflow = Overflow::new([0; 64], 64);
312    }
313
314    /// generates sequence to `buffer` with `nonce` under the `key`
315    pub fn generate(&mut self, buffer: &mut [u8]) {
316        self.modify(buffer, &<[u8]>::copy_from_slice);
317    }
318
319    /// encrypts a `buffer` with `nonce` under the `key`
320    pub fn encrypt(&mut self, buffer: &mut [u8]) {
321        self.modify(buffer, &xor_from_slice);
322    }
323}
324
325#[cfg(test)]
326mod tests {
327    use super::*;
328
329    #[test]
330    fn quarterround_test() {
331        assert_eq!(
332            quarterround(0x00000000, 0x00000000, 0x00000000, 0x00000000),
333            [0x00000000, 0x00000000, 0x00000000, 0x00000000]
334        );
335        assert_eq!(
336            quarterround(0xe7e8c006, 0xc4f9417d, 0x6479b4b2, 0x68c67137),
337            [0xe876d72b, 0x9361dfd5, 0xf1460244, 0x948541a3]
338        );
339    }
340
341    #[test]
342    fn rowround_test() {
343        test([
344            0x00000001, 0x00000000, 0x00000000, 0x00000000,
345            0x00000001, 0x00000000, 0x00000000, 0x00000000,
346            0x00000001, 0x00000000, 0x00000000, 0x00000000,
347            0x00000001, 0x00000000, 0x00000000, 0x00000000
348        ], [
349            0x08008145, 0x00000080, 0x00010200, 0x20500000,
350            0x20100001, 0x00048044, 0x00000080, 0x00010000,
351            0x00000001, 0x00002000, 0x80040000, 0x00000000,
352            0x00000001, 0x00000200, 0x00402000, 0x88000100
353        ]);
354
355        test([
356             0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365,
357             0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6,
358             0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e,
359             0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a
360        ], [
361            0xa890d39d, 0x65d71596, 0xe9487daa, 0xc8ca6a86,
362            0x949d2192, 0x764b7754, 0xe408d9b9, 0x7a41b4d1,
363            0x3402e183, 0x3c3af432, 0x50669f96, 0xd89ef0a8,
364            0x0040ede5, 0xb545fbce, 0xd257ed4f, 0x1818882d
365        ]);
366
367        fn test(input_data: [u32; 16], expected_data: [u32; 16]) {
368            assert_eq!(rowround(input_data), expected_data);
369        }
370    }
371
372    #[test]
373    fn columnround_test() {
374        test([
375            0x00000001, 0x00000000, 0x00000000, 0x00000000,
376            0x00000001, 0x00000000, 0x00000000, 0x00000000,
377            0x00000001, 0x00000000, 0x00000000, 0x00000000,
378            0x00000001, 0x00000000, 0x00000000, 0x00000000
379        ], [
380            0x10090288, 0x00000000, 0x00000000, 0x00000000,
381            0x00000101, 0x00000000, 0x00000000, 0x00000000,
382            0x00020401, 0x00000000, 0x00000000, 0x00000000,
383            0x40a04001, 0x00000000, 0x00000000, 0x00000000
384        ]);
385
386        test([
387            0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365,
388            0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6,
389            0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e,
390            0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a
391        ], [
392            0x8c9d190a, 0xce8e4c90, 0x1ef8e9d3, 0x1326a71a,
393            0x90a20123, 0xead3c4f3, 0x63a091a0, 0xf0708d69,
394            0x789b010c, 0xd195a681, 0xeb7d5504, 0xa774135c,
395            0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8
396        ]);
397
398        fn test(input_data: [u32; 16], expected_data: [u32; 16]) {
399            assert_eq!(columnround(input_data), expected_data);
400        }
401    }
402
403    #[test]
404    fn doubleround_test() {
405        test([
406            0x00000001, 0x00000000, 0x00000000, 0x00000000,
407            0x00000000, 0x00000000, 0x00000000, 0x00000000,
408            0x00000000, 0x00000000, 0x00000000, 0x00000000,
409            0x00000000, 0x00000000, 0x00000000, 0x00000000
410        ], [
411            0x8186a22d, 0x0040a284, 0x82479210, 0x06929051,
412            0x08000090, 0x02402200, 0x00004000, 0x00800000,
413            0x00010200, 0x20400000, 0x08008104, 0x00000000,
414            0x20500000, 0xa0000040, 0x0008180a, 0x612a8020
415        ]);
416
417        test([
418            0xde501066, 0x6f9eb8f7, 0xe4fbbd9b, 0x454e3f57,
419            0xb75540d3, 0x43e93a4c, 0x3a6f2aa0, 0x726d6b36,
420            0x9243f484, 0x9145d1e8, 0x4fa9d247, 0xdc8dee11,
421            0x054bf545, 0x254dd653, 0xd9421b6d, 0x67b276c1
422        ], [
423            0xccaaf672, 0x23d960f7, 0x9153e63a, 0xcd9a60d0,
424            0x50440492, 0xf07cad19, 0xae344aa0, 0xdf4cfdfc,
425            0xca531c29, 0x8e7943db, 0xac1680cd, 0xd503ca00,
426            0xa74b2ad6, 0xbc331c5c, 0x1dda24c7, 0xee928277
427        ]);
428
429        fn test(input_data: [u32; 16], expected_data: [u32; 16]) {
430            assert_eq!(doubleround(input_data), expected_data);
431        }
432    }
433
434    #[test]
435    fn create_init_matrix_test() {
436        test(Key::Key16([
437            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
438        ]), [
439            101, 120, 112, 97, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
440            15, 16, 110, 100, 32, 49, 101, 102, 103, 104, 105, 106, 107, 108,
441            109, 110, 111, 112, 113, 114, 115, 116, 54, 45, 98, 121, 1, 2, 3,
442            4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 116, 101, 32, 107
443        ]);
444
445        test(Key::Key32([
446            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 201, 202,
447            203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216
448        ]), [
449            101, 120, 112, 97, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
450            15, 16, 110, 100, 32, 51, 101, 102, 103, 104, 105, 106, 107, 108,
451            109, 110, 111, 112, 113, 114, 115, 116, 50, 45, 98, 121, 201, 202,
452            203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
453            216, 116, 101, 32, 107
454        ]);
455
456        fn test(key: Key, expected_data: [u8; 64]) {
457            let nonce = [101, 102, 103, 104, 105, 106, 107, 108];
458            let counter = u64::from_le_bytes(
459                [109, 110, 111, 112, 113, 114, 115, 116]
460            );
461            let generator = Generator::new(key, nonce, counter);
462
463            let mut expected_data_u32 = [0; 16];
464            u8_to_u32(&expected_data, &mut expected_data_u32);
465            assert_eq!(generator.init_matrix, expected_data_u32);
466        }
467    }
468
469    #[test]
470    fn first_doubleround_test() {
471        test(0x00000000, [0x00000000, 0x00000000]);
472        test(0x00000001, [0x00000001, 0x00000000]);
473        test(0x1234567f, [0x1234567f, 0x00000000]);
474        test(0xffffffff, [0xffffffff, 0x00000000]);
475        test(0x100000000, [0x00000000, 0x00000001]);
476        test(0x012345678abcdef, [0x78abcdef, 0x123456]);
477
478        fn test(counter: u64, counter_as_u32: [u32; 2]) {
479            let key = Key::Key16([0; 16]);
480            let mut generator = Generator::new(key, [0; 8], 0);
481            generator.set_counter(counter);
482            assert_eq!(generator.init_matrix[8..10], counter_as_u32);
483            assert_eq!(
484                generator.first_doubleround(),
485                doubleround(generator.init_matrix)
486            );
487        };
488    }
489
490    #[test]
491    fn generate_test() {
492        test(Key::Key16([
493            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
494        ]), [
495            39, 173, 46, 248, 30, 200, 82, 17, 48, 67, 254, 239, 37, 18, 13,
496            247, 241, 200, 61, 144, 10, 55, 50, 185, 6, 47, 246, 253, 143, 86,
497            187, 225, 134, 85, 110, 246, 161, 163, 43, 235, 231, 94, 171, 51,
498            145, 214, 112, 29, 14, 232, 5, 16, 151, 140, 183, 141, 171, 9, 122,
499            181, 104, 182, 177, 193
500        ]);
501
502        test(Key::Key32([
503            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 201, 202,
504            203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216
505        ]), [
506            69, 37, 68, 39, 41, 15, 107, 193, 255, 139, 122, 6, 170, 233, 217,
507            98, 89, 144, 182, 106, 21, 51, 200, 65, 239, 49, 222, 34, 215, 114,
508            40, 126, 104, 197, 7, 225, 197, 153, 31, 2, 102, 78, 76, 176, 84,
509            245, 246, 184, 177, 160, 133, 130, 6, 72, 149, 119, 192, 195, 132,
510            236, 234, 103, 246, 74
511        ]);
512
513        fn test(key: Key, expected_data: [u8; 64]) {
514            let nonce = [101, 102, 103, 104, 105, 106, 107, 108];
515            let counter = u64::from_le_bytes(
516                [109, 110, 111, 112, 113, 114, 115, 116]
517            );
518            let mut generator = Generator::new(key, nonce, counter);
519
520            let buffer = generator.next();
521            assert_eq!(buffer.to_vec(), expected_data.to_vec());
522        }
523    }
524}