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)]
182 static void subBytesAndShiftRows(uint8_t *output,
const uint8_t *input)
184 OUT(0, 0) = pgm_read_byte(sbox + IN(0, 0));
185 OUT(0, 1) = pgm_read_byte(sbox + IN(1, 1));
186 OUT(0, 2) = pgm_read_byte(sbox + IN(2, 2));
187 OUT(0, 3) = pgm_read_byte(sbox + IN(3, 3));
188 OUT(1, 0) = pgm_read_byte(sbox + IN(1, 0));
189 OUT(1, 1) = pgm_read_byte(sbox + IN(2, 1));
190 OUT(1, 2) = pgm_read_byte(sbox + IN(3, 2));
191 OUT(1, 3) = pgm_read_byte(sbox + IN(0, 3));
192 OUT(2, 0) = pgm_read_byte(sbox + IN(2, 0));
193 OUT(2, 1) = pgm_read_byte(sbox + IN(3, 1));
194 OUT(2, 2) = pgm_read_byte(sbox + IN(0, 2));
195 OUT(2, 3) = pgm_read_byte(sbox + IN(1, 3));
196 OUT(3, 0) = pgm_read_byte(sbox + IN(3, 0));
197 OUT(3, 1) = pgm_read_byte(sbox + IN(0, 1));
198 OUT(3, 2) = pgm_read_byte(sbox + IN(1, 2));
199 OUT(3, 3) = pgm_read_byte(sbox + IN(2, 3));
202 static void inverseShiftRowsAndSubBytes(uint8_t *output,
const uint8_t *input)
204 OUT(0, 0) = pgm_read_byte(sbox_inverse + IN(0, 0));
205 OUT(0, 1) = pgm_read_byte(sbox_inverse + IN(3, 1));
206 OUT(0, 2) = pgm_read_byte(sbox_inverse + IN(2, 2));
207 OUT(0, 3) = pgm_read_byte(sbox_inverse + IN(1, 3));
208 OUT(1, 0) = pgm_read_byte(sbox_inverse + IN(1, 0));
209 OUT(1, 1) = pgm_read_byte(sbox_inverse + IN(0, 1));
210 OUT(1, 2) = pgm_read_byte(sbox_inverse + IN(3, 2));
211 OUT(1, 3) = pgm_read_byte(sbox_inverse + IN(2, 3));
212 OUT(2, 0) = pgm_read_byte(sbox_inverse + IN(2, 0));
213 OUT(2, 1) = pgm_read_byte(sbox_inverse + IN(1, 1));
214 OUT(2, 2) = pgm_read_byte(sbox_inverse + IN(0, 2));
215 OUT(2, 3) = pgm_read_byte(sbox_inverse + IN(3, 3));
216 OUT(3, 0) = pgm_read_byte(sbox_inverse + IN(3, 0));
217 OUT(3, 1) = pgm_read_byte(sbox_inverse + IN(2, 1));
218 OUT(3, 2) = pgm_read_byte(sbox_inverse + IN(1, 2));
219 OUT(3, 3) = pgm_read_byte(sbox_inverse + IN(0, 3));
222 static void mixColumn(uint8_t *output, uint8_t *input)
225 uint8_t a = input[0];
226 uint8_t b = input[1];
227 uint8_t c = input[2];
228 uint8_t d = input[3];
229 uint8_t a2 = gmul2(a);
230 uint8_t b2 = gmul2(b);
231 uint8_t c2 = gmul2(c);
232 uint8_t d2 = gmul2(d);
233 output[0] = a2 ^ b2 ^ b ^ c ^ d;
234 output[1] = a ^ b2 ^ c2 ^ c ^ d;
235 output[2] = a ^ b ^ c2 ^ d2 ^ d;
236 output[3] = a2 ^ a ^ b ^ c ^ d2;
239 static void inverseMixColumn(uint8_t *output,
const uint8_t *input)
242 uint8_t a = input[0];
243 uint8_t b = input[1];
244 uint8_t c = input[2];
245 uint8_t d = input[3];
246 uint8_t a2 = gmul2(a);
247 uint8_t b2 = gmul2(b);
248 uint8_t c2 = gmul2(c);
249 uint8_t d2 = gmul2(d);
250 uint8_t a4 = gmul4(a);
251 uint8_t b4 = gmul4(b);
252 uint8_t c4 = gmul4(c);
253 uint8_t d4 = gmul4(d);
254 uint8_t a8 = gmul8(a);
255 uint8_t b8 = gmul8(b);
256 uint8_t c8 = gmul8(c);
257 uint8_t d8 = gmul8(d);
258 output[0] = a8 ^ a4 ^ a2 ^ b8 ^ b2 ^ b ^ c8 ^ c4 ^ c ^ d8 ^ d;
259 output[1] = a8 ^ a ^ b8 ^ b4 ^ b2 ^ c8 ^ c2 ^ c ^ d8 ^ d4 ^ d;
260 output[2] = a8 ^ a4 ^ a ^ b8 ^ b ^ c8 ^ c4 ^ c2 ^ d8 ^ d2 ^ d;
261 output[3] = a8 ^ a2 ^ a ^ b8 ^ b4 ^ b ^ c8 ^ c ^ d8 ^ d4 ^ d2;
266 const uint8_t *roundKey = schedule;
273 for (posn = 0; posn < 16; ++posn)
274 state1[posn] = input[posn] ^ roundKey[posn];
278 for (round = rounds; round > 1; --round) {
279 subBytesAndShiftRows(state2, state1);
280 mixColumn(state1, state2);
281 mixColumn(state1 + 4, state2 + 4);
282 mixColumn(state1 + 8, state2 + 8);
283 mixColumn(state1 + 12, state2 + 12);
284 for (posn = 0; posn < 16; ++posn)
285 state1[posn] ^= roundKey[posn];
290 subBytesAndShiftRows(state2, state1);
291 for (posn = 0; posn < 16; ++posn)
292 output[posn] = state2[posn] ^ roundKey[posn];
297 const uint8_t *roundKey = schedule + rounds * 16;
304 for (posn = 0; posn < 16; ++posn)
305 state1[posn] = input[posn] ^ roundKey[posn];
306 inverseShiftRowsAndSubBytes(state2, state1);
309 for (round = rounds; round > 1; --round) {
311 for (posn = 0; posn < 16; ++posn)
312 state2[posn] ^= roundKey[posn];
313 inverseMixColumn(state1, state2);
314 inverseMixColumn(state1 + 4, state2 + 4);
315 inverseMixColumn(state1 + 8, state2 + 8);
316 inverseMixColumn(state1 + 12, state2 + 12);
317 inverseShiftRowsAndSubBytes(state2, state1);
322 for (posn = 0; posn < 16; ++posn)
323 output[posn] = state2[posn] ^ roundKey[posn];
328 clean(schedule, (rounds + 1) * 16);
333 void AESCommon::keyScheduleCore(uint8_t *output,
const uint8_t *input, uint8_t iteration)
337 static uint8_t
const rcon[11] PROGMEM = {
338 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
341 output[0] = pgm_read_byte(sbox + input[1]) ^ pgm_read_byte(rcon + iteration);
342 output[1] = pgm_read_byte(sbox + input[2]);
343 output[2] = pgm_read_byte(sbox + input[3]);
344 output[3] = pgm_read_byte(sbox + input[0]);
347 void AESCommon::applySbox(uint8_t *output,
const uint8_t *input)
349 output[0] = pgm_read_byte(sbox + input[0]);
350 output[1] = pgm_read_byte(sbox + input[1]);
351 output[2] = pgm_read_byte(sbox + input[2]);
352 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.