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