gimli_aead/
lib.rs

1#![no_std]
2
3use gimli_permutation::{ SIZE, gimli, state_with as with };
4
5#[derive(Clone)]
6pub struct GimliAead([u32; SIZE]);
7
8impl GimliAead {
9    pub fn new(key: &[u8; 32], nonce: &[u8; 16]) -> GimliAead {
10        let mut state = [0; SIZE];
11        with(&mut state, |state| {
12            state[..16].copy_from_slice(nonce);
13            state[16..].copy_from_slice(key);
14        });
15        gimli(&mut state);
16        GimliAead(state)
17    }
18
19    fn process_aad(&mut self, aad: &[u8]) {
20        let state = &mut self.0;
21
22        let mut iter = aad.chunks_exact(16);
23
24        for chunk in &mut iter {
25            with(state, |state| {
26                for i in 0..16 {
27                    state[i] ^= chunk[i];
28                }
29            });
30            gimli(state);
31        }
32
33        with(state, |state| {
34            let chunk = iter.remainder();
35            for i in 0..chunk.len() {
36                state[i] ^= chunk[i];
37            }
38
39            state[chunk.len()] ^= 1;
40            state[47] ^= 1;
41        });
42        gimli(state);
43    }
44
45    pub fn encrypt(mut self, aad: &[u8], m: &mut [u8]) -> [u8; 16] {
46        self.process_aad(aad);
47
48        let state = &mut self.0;
49        let mut iter = m.chunks_exact_mut(16);
50
51        for chunk in &mut iter {
52            with(state, |state| {
53                for i in 0..16 {
54                    state[i] ^= chunk[i];
55                }
56                chunk.copy_from_slice(&state[..16]);
57            });
58            gimli(state);
59        }
60
61        with(state, |state| {
62            let chunk = iter.into_remainder();
63            for i in 0..chunk.len() {
64                state[i] ^= chunk[i];
65            }
66            chunk.copy_from_slice(&state[..chunk.len()]);
67
68            state[chunk.len()] ^= 1;
69            state[47] ^= 1;
70        });
71        gimli(state);
72
73        let mut tag = [0; 16];
74        with(state, |state| tag.copy_from_slice(&state[..16]));
75        tag
76    }
77
78    pub fn decrypt(mut self, aad: &[u8], c: &mut [u8], tag: &[u8; 16]) -> bool {
79        self.process_aad(aad);
80
81        let state = &mut self.0;
82        let mut iter = c.chunks_exact_mut(16);
83
84        for chunk in &mut iter {
85            with(state, |state| {
86                for i in 0..16 {
87                    let c = chunk[i];
88                    chunk[i] = state[i] ^ c;
89                    state[i] = c;
90                }
91            });
92            gimli(state);
93        }
94
95        with(state, |state| {
96            let chunk = iter.into_remainder();
97            for i in 0..chunk.len() {
98                let c = chunk[i];
99                chunk[i] = state[i] ^ c;
100                state[i] = c;
101            }
102
103            state[chunk.len()] ^= 1;
104            state[47] ^= 1;
105        });
106        gimli(state);
107
108        let mut result = 0;
109        with(state, |state| {
110            for i in 0..16 {
111                result |= state[i] ^ tag[i];
112            }
113        });
114
115        result == 0
116    }
117}