25 #include "utility/ProgMemUtil.h"
49 static uint8_t
const sbox[256] PROGMEM = {
50 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
51 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
52 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
53 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
54 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
55 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
56 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
57 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
58 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
59 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
60 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
61 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
62 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
63 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
64 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
65 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
66 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
67 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
68 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
69 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
70 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
71 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
72 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
73 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
74 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
75 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
76 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
77 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
78 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
79 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
80 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
81 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
85 static uint8_t
const sbox_inverse[256] PROGMEM = {
86 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
87 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
88 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
89 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
90 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
91 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
92 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
93 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
94 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
95 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
96 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
97 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
98 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
99 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
100 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
101 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
102 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
103 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
104 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
105 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
106 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
107 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
108 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
109 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
110 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
111 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
112 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
113 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
114 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
115 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
116 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
117 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
126 : rounds(0), schedule(0)
149 static uint8_t
const K[8] = {
156 (0x1B << 2) ^ (0x1B << 1),
157 (0x1B << 2) ^ (0x1B << 1) ^ 0x1B
170 #define gmul2(x) (t = ((uint16_t)(x)) << 1, \
171 ((uint8_t)t) ^ (uint8_t)(0x1B * ((uint8_t)(t >> 8))))
174 #define gmul4(x) (t = ((uint16_t)(x)) << 2, ((uint8_t)t) ^ K[t >> 8])
177 #define gmul8(x) (t = ((uint16_t)(x)) << 3, ((uint8_t)t) ^ K[t >> 8])
179 #define OUT(col, row) output[(col) * 4 + (row)]
180 #define IN(col, row) input[(col) * 4 + (row)]
184 void AESCommon::subBytesAndShiftRows(uint8_t *output,
const uint8_t *input)
186 OUT(0, 0) = pgm_read_byte(sbox + IN(0, 0));
187 OUT(0, 1) = pgm_read_byte(sbox + IN(1, 1));
188 OUT(0, 2) = pgm_read_byte(sbox + IN(2, 2));
189 OUT(0, 3) = pgm_read_byte(sbox + IN(3, 3));
190 OUT(1, 0) = pgm_read_byte(sbox + IN(1, 0));
191 OUT(1, 1) = pgm_read_byte(sbox + IN(2, 1));
192 OUT(1, 2) = pgm_read_byte(sbox + IN(3, 2));
193 OUT(1, 3) = pgm_read_byte(sbox + IN(0, 3));
194 OUT(2, 0) = pgm_read_byte(sbox + IN(2, 0));
195 OUT(2, 1) = pgm_read_byte(sbox + IN(3, 1));
196 OUT(2, 2) = pgm_read_byte(sbox + IN(0, 2));
197 OUT(2, 3) = pgm_read_byte(sbox + IN(1, 3));
198 OUT(3, 0) = pgm_read_byte(sbox + IN(3, 0));
199 OUT(3, 1) = pgm_read_byte(sbox + IN(0, 1));
200 OUT(3, 2) = pgm_read_byte(sbox + IN(1, 2));
201 OUT(3, 3) = pgm_read_byte(sbox + IN(2, 3));
204 void AESCommon::inverseShiftRowsAndSubBytes(uint8_t *output,
const uint8_t *input)
206 OUT(0, 0) = pgm_read_byte(sbox_inverse + IN(0, 0));
207 OUT(0, 1) = pgm_read_byte(sbox_inverse + IN(3, 1));
208 OUT(0, 2) = pgm_read_byte(sbox_inverse + IN(2, 2));
209 OUT(0, 3) = pgm_read_byte(sbox_inverse + IN(1, 3));
210 OUT(1, 0) = pgm_read_byte(sbox_inverse + IN(1, 0));
211 OUT(1, 1) = pgm_read_byte(sbox_inverse + IN(0, 1));
212 OUT(1, 2) = pgm_read_byte(sbox_inverse + IN(3, 2));
213 OUT(1, 3) = pgm_read_byte(sbox_inverse + IN(2, 3));
214 OUT(2, 0) = pgm_read_byte(sbox_inverse + IN(2, 0));
215 OUT(2, 1) = pgm_read_byte(sbox_inverse + IN(1, 1));
216 OUT(2, 2) = pgm_read_byte(sbox_inverse + IN(0, 2));
217 OUT(2, 3) = pgm_read_byte(sbox_inverse + IN(3, 3));
218 OUT(3, 0) = pgm_read_byte(sbox_inverse + IN(3, 0));
219 OUT(3, 1) = pgm_read_byte(sbox_inverse + IN(2, 1));
220 OUT(3, 2) = pgm_read_byte(sbox_inverse + IN(1, 2));
221 OUT(3, 3) = pgm_read_byte(sbox_inverse + IN(0, 3));
224 void AESCommon::mixColumn(uint8_t *output, uint8_t *input)
227 uint8_t a = input[0];
228 uint8_t b = input[1];
229 uint8_t c = input[2];
230 uint8_t d = input[3];
231 uint8_t a2 = gmul2(a);
232 uint8_t b2 = gmul2(b);
233 uint8_t c2 = gmul2(c);
234 uint8_t d2 = gmul2(d);
235 output[0] = a2 ^ b2 ^ b ^ c ^ d;
236 output[1] = a ^ b2 ^ c2 ^ c ^ d;
237 output[2] = a ^ b ^ c2 ^ d2 ^ d;
238 output[3] = a2 ^ a ^ b ^ c ^ d2;
241 void AESCommon::inverseMixColumn(uint8_t *output,
const uint8_t *input)
244 uint8_t a = input[0];
245 uint8_t b = input[1];
246 uint8_t c = input[2];
247 uint8_t d = input[3];
248 uint8_t a2 = gmul2(a);
249 uint8_t b2 = gmul2(b);
250 uint8_t c2 = gmul2(c);
251 uint8_t d2 = gmul2(d);
252 uint8_t a4 = gmul4(a);
253 uint8_t b4 = gmul4(b);
254 uint8_t c4 = gmul4(c);
255 uint8_t d4 = gmul4(d);
256 uint8_t a8 = gmul8(a);
257 uint8_t b8 = gmul8(b);
258 uint8_t c8 = gmul8(c);
259 uint8_t d8 = gmul8(d);
260 output[0] = a8 ^ a4 ^ a2 ^ b8 ^ b2 ^ b ^ c8 ^ c4 ^ c ^ d8 ^ d;
261 output[1] = a8 ^ a ^ b8 ^ b4 ^ b2 ^ c8 ^ c2 ^ c ^ d8 ^ d4 ^ d;
262 output[2] = a8 ^ a4 ^ a ^ b8 ^ b ^ c8 ^ c4 ^ c2 ^ d8 ^ d2 ^ d;
263 output[3] = a8 ^ a2 ^ a ^ b8 ^ b4 ^ b ^ c8 ^ c ^ d8 ^ d4 ^ d2;
270 const uint8_t *roundKey = schedule;
277 for (posn = 0; posn < 16; ++posn)
278 state1[posn] = input[posn] ^ roundKey[posn];
282 for (round = rounds; round > 1; --round) {
283 subBytesAndShiftRows(state2, state1);
284 mixColumn(state1, state2);
285 mixColumn(state1 + 4, state2 + 4);
286 mixColumn(state1 + 8, state2 + 8);
287 mixColumn(state1 + 12, state2 + 12);
288 for (posn = 0; posn < 16; ++posn)
289 state1[posn] ^= roundKey[posn];
294 subBytesAndShiftRows(state2, state1);
295 for (posn = 0; posn < 16; ++posn)
296 output[posn] = state2[posn] ^ roundKey[posn];
301 const uint8_t *roundKey = schedule + rounds * 16;
308 for (posn = 0; posn < 16; ++posn)
309 state1[posn] = input[posn] ^ roundKey[posn];
310 inverseShiftRowsAndSubBytes(state2, state1);
313 for (round = rounds; round > 1; --round) {
315 for (posn = 0; posn < 16; ++posn)
316 state2[posn] ^= roundKey[posn];
317 inverseMixColumn(state1, state2);
318 inverseMixColumn(state1 + 4, state2 + 4);
319 inverseMixColumn(state1 + 8, state2 + 8);
320 inverseMixColumn(state1 + 12, state2 + 12);
321 inverseShiftRowsAndSubBytes(state2, state1);
326 for (posn = 0; posn < 16; ++posn)
327 output[posn] = state2[posn] ^ roundKey[posn];
332 clean(schedule, (rounds + 1) * 16);
337 void AESCommon::keyScheduleCore(uint8_t *output,
const uint8_t *input, uint8_t iteration)
341 static uint8_t
const rcon[11] PROGMEM = {
342 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
345 output[0] = pgm_read_byte(sbox + input[1]) ^ pgm_read_byte(rcon + iteration);
346 output[1] = pgm_read_byte(sbox + input[2]);
347 output[2] = pgm_read_byte(sbox + input[3]);
348 output[3] = pgm_read_byte(sbox + input[0]);
351 void AESCommon::applySbox(uint8_t *output,
const uint8_t *input)
353 output[0] = pgm_read_byte(sbox + input[0]);
354 output[1] = pgm_read_byte(sbox + input[1]);
355 output[2] = pgm_read_byte(sbox + input[2]);
356 output[3] = pgm_read_byte(sbox + input[3]);
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
AESCommon()
Constructs an AES block cipher object.
size_t blockSize() const
Size of an AES block in bytes.
virtual ~AESCommon()
Destroys this AES block cipher object after clearing sensitive information.
void clear()
Clears all security-sensitive state from this block cipher.
void encryptBlock(uint8_t *output, const uint8_t *input)
Encrypts a single block using this cipher.