Skip to main content

eva_crypto/
aes.rs

1use super::generic::{create_u8x4x4, transpose, u8x4x4, Ops, Permutation};
2
3pub struct AES {
4    pub round_keys: Vec<AESstate>,
5    pub sbox: [u8; 256],
6    pub rsbox: [u8; 256],
7}
8
9type AESstate = u8x4x4;
10
11impl AES {
12    /// Initialize an AES cipher.
13    pub fn new(key: &[u8]) -> AES {
14        let rounds = 10 + (key.len() / 4) - 4;
15        let mut round_keys = vec![[[0; 4]; 4]; rounds + 1];
16        key_expansion(key, &mut round_keys);
17
18        AES {
19            round_keys,
20            sbox: SBOX,
21            rsbox: RSBOX,
22        }
23    }
24
25    /// Encrypt a block.
26    pub fn encrypt(&self, data: &[u8]) -> Vec<u8> {
27        let rounds = self.round_keys.len() - 1;
28        let mut state = create_u8x4x4(data);
29        state = add_round_key(&state, &self.round_keys[0]);
30
31        for i in 1..rounds {
32            state = sub_bytes(&state, &self.sbox);
33            state = shift_rows(&state);
34            state = mix_columns(&state);
35            state = add_round_key(&state, &self.round_keys[i]);
36        }
37
38        state = sub_bytes(&state, &self.sbox);
39        state = shift_rows(&state);
40        state = add_round_key(&state, &self.round_keys[rounds]);
41
42        state.concat()
43    }
44
45    /// Decrypt a block.
46    pub fn decrypt(&self, data: &[u8]) -> Vec<u8> {
47        let rounds = self.round_keys.len() - 1;
48        let mut state = create_u8x4x4(data);
49        state = add_round_key(&state, &self.round_keys[rounds]);
50
51        for i in (1..rounds).rev() {
52            state = inv_shift_rows(&state);
53            state = inv_sub_bytes(&state, &self.rsbox);
54            state = add_round_key(&state, &self.round_keys[i]);
55            state = inv_mix_columns(&state);
56        }
57
58        state = inv_sub_bytes(&state, &self.rsbox);
59        state = inv_shift_rows(&state);
60        state = add_round_key(&state, &self.round_keys[0]);
61
62        state.concat()
63    }
64
65    // Injection of faults
66
67    pub fn with_sbox(mut self, faulty_sbox: [u8; 256]) -> Self {
68        self.sbox = faulty_sbox;
69        self
70    }
71
72    pub fn with_rsbox(mut self, faulty_rsbox: [u8; 256]) -> Self {
73        self.rsbox = faulty_rsbox;
74        self
75    }
76
77    pub fn with_sbox_byte(mut self, faulty_idx: usize, faulty_val: u8) -> Self {
78        let mut sbox = SBOX;
79        sbox[faulty_idx] = faulty_val;
80        self.sbox = sbox;
81        self
82    }
83
84    pub fn with_rsbox_byte(mut self, faulty_idx: usize, faulty_val: u8) -> Self {
85        let mut rsbox = RSBOX;
86        rsbox[faulty_idx] = faulty_val;
87        self.sbox = rsbox;
88        self
89    }
90}
91
92fn key_expansion(key: &[u8], round_keys: &mut [AESstate]) {
93    let key_words = key.len() / 4;
94    debug_assert!(match key_words {
95        4 | 6 | 8 => true,
96        _ => false,
97    });
98    let rounds = 10 + key_words - 4;
99
100    for (i, j) in (0..key.len()).step_by(4).enumerate() {
101        for n in 0..4 {
102            round_keys[i / 4][i % 4][j % 4 + n] = key[j + n];
103        }
104    }
105
106    for i in key_words..(rounds + 1) * 4 {
107        let mut tmp = round_keys[(i - 1) / 4][(i - 1) % 4];
108        if i % key_words == 0 {
109            tmp = tmp.lrot().sub_sbox(&SBOX);
110            tmp[0] ^= RCON[i / key_words - 1];
111        } else if key_words > 6 && i % key_words == 4 {
112            tmp = tmp.sub_sbox(&SBOX);
113        };
114        round_keys[i / 4][i % 4] = round_keys[(i - key_words) / 4][(i - key_words) % 4].xor(&tmp);
115    }
116}
117
118fn add_round_key(state: &AESstate, round_key: &AESstate) -> AESstate {
119    state.xor(round_key)
120}
121fn sub_bytes(state: &AESstate, sbox: &[u8]) -> AESstate {
122    state.sub_sbox(sbox)
123}
124fn inv_sub_bytes(state: &AESstate, rsbox: &[u8]) -> AESstate {
125    state.sub_sbox(rsbox)
126}
127fn shift_rows(state: &AESstate) -> AESstate {
128    transpose(&transpose(state).lrot())
129}
130fn inv_shift_rows(state: &AESstate) -> AESstate {
131    transpose(&transpose(state).rrot())
132}
133fn mix_columns(state: &AESstate) -> AESstate {
134    [
135        [0x02, 0x01, 0x01, 0x03],
136        [0x03, 0x02, 0x01, 0x01],
137        [0x01, 0x03, 0x02, 0x01],
138        [0x01, 0x01, 0x03, 0x02],
139    ]
140    .gmul(&state, 8)
141}
142fn inv_mix_columns(state: &AESstate) -> AESstate {
143    [
144        [0x0e, 0x09, 0x0d, 0x0b],
145        [0x0b, 0x0e, 0x09, 0x0d],
146        [0x0d, 0x0b, 0x0e, 0x09],
147        [0x09, 0x0d, 0x0b, 0x0e],
148    ]
149    .gmul(&state, 8)
150}
151
152pub static SBOX: [u8; 256] = [
153    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
154    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
155    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
156    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
157    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
158    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
159    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
160    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
161    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
162    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
163    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
164    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
165    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
166    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
167    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
168    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
169];
170
171pub static RSBOX: [u8; 256] = [
172    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
173    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
174    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
175    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
176    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
177    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
178    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
179    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
180    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
181    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
182    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
183    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
184    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
185    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
186    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
187    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
188];
189
190pub static RCON: [u8; 10] = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];