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 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 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 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 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];