Arduino Cryptography Library
AES256.cpp
1 /*
2  * Copyright (C) 2015,2018 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "AES.h"
24 #include "Crypto.h"
25 #include <string.h>
26 
27 #if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC)
28 
43 {
44  rounds = 14;
45  schedule = sched;
46 }
47 
48 AES256::~AES256()
49 {
50  clean(sched);
51 }
52 
57 size_t AES256::keySize() const
58 {
59  return 32;
60 }
61 
62 bool AES256::setKey(const uint8_t *key, size_t len)
63 {
64  if (len != 32)
65  return false;
66 
67  // Copy the key itself into the first 32 bytes of the schedule.
68  uint8_t *schedule = sched;
69  memcpy(schedule, key, 32);
70 
71  // Expand the key schedule until we have 240 bytes of expanded key.
72  uint8_t iteration = 1;
73  uint8_t n = 32;
74  uint8_t w = 8;
75  while (n < 240) {
76  if (w == 8) {
77  // Every 32 bytes (8 words) we need to apply the key schedule core.
78  keyScheduleCore(schedule + 32, schedule + 28, iteration);
79  schedule[32] ^= schedule[0];
80  schedule[33] ^= schedule[1];
81  schedule[34] ^= schedule[2];
82  schedule[35] ^= schedule[3];
83  ++iteration;
84  w = 0;
85  } else if (w == 4) {
86  // At the 16 byte mark we need to apply the S-box.
87  applySbox(schedule + 32, schedule + 28);
88  schedule[32] ^= schedule[0];
89  schedule[33] ^= schedule[1];
90  schedule[34] ^= schedule[2];
91  schedule[35] ^= schedule[3];
92  } else {
93  // Otherwise just XOR the word with the one 32 bytes previous.
94  schedule[32] = schedule[28] ^ schedule[0];
95  schedule[33] = schedule[29] ^ schedule[1];
96  schedule[34] = schedule[30] ^ schedule[2];
97  schedule[35] = schedule[31] ^ schedule[3];
98  }
99 
100  // Advance to the next word in the schedule.
101  schedule += 4;
102  n += 4;
103  ++w;
104  }
105 
106  return true;
107 }
108 
134 // Helper macros.
135 #define LEFT 0
136 #define RIGHT 16
137 #define ENCRYPT(phase) \
138  do { \
139  AESCommon::subBytesAndShiftRows(state2, state1); \
140  AESCommon::mixColumn(state1, state2); \
141  AESCommon::mixColumn(state1 + 4, state2 + 4); \
142  AESCommon::mixColumn(state1 + 8, state2 + 8); \
143  AESCommon::mixColumn(state1 + 12, state2 + 12); \
144  for (posn = 0; posn < 16; ++posn) \
145  state1[posn] ^= schedule[posn + (phase)]; \
146  } while (0)
147 #define DECRYPT(phase) \
148  do { \
149  for (posn = 0; posn < 16; ++posn) \
150  state2[posn] ^= schedule[posn + (phase)]; \
151  AESCommon::inverseMixColumn(state1, state2); \
152  AESCommon::inverseMixColumn(state1 + 4, state2 + 4); \
153  AESCommon::inverseMixColumn(state1 + 8, state2 + 8); \
154  AESCommon::inverseMixColumn(state1 + 12, state2 + 12); \
155  AESCommon::inverseShiftRowsAndSubBytes(state2, state1); \
156  } while (0)
157 #define KCORE(n) \
158  do { \
159  AESCommon::keyScheduleCore(temp, schedule + 28, (n)); \
160  schedule[0] ^= temp[0]; \
161  schedule[1] ^= temp[1]; \
162  schedule[2] ^= temp[2]; \
163  schedule[3] ^= temp[3]; \
164  } while (0)
165 #define KXOR(a, b) \
166  do { \
167  schedule[(a) * 4] ^= schedule[(b) * 4]; \
168  schedule[(a) * 4 + 1] ^= schedule[(b) * 4 + 1]; \
169  schedule[(a) * 4 + 2] ^= schedule[(b) * 4 + 2]; \
170  schedule[(a) * 4 + 3] ^= schedule[(b) * 4 + 3]; \
171  } while (0)
172 #define KSBOX() \
173  do { \
174  AESCommon::applySbox(temp, schedule + 12); \
175  schedule[16] ^= temp[0]; \
176  schedule[17] ^= temp[1]; \
177  schedule[18] ^= temp[2]; \
178  schedule[19] ^= temp[3]; \
179  } while (0)
180 
190 {
191 }
192 
193 AESTiny256::~AESTiny256()
194 {
195  clean(schedule);
196 }
197 
202 size_t AESTiny256::blockSize() const
203 {
204  return 16;
205 }
206 
211 size_t AESTiny256::keySize() const
212 {
213  return 32;
214 }
215 
216 bool AESTiny256::setKey(const uint8_t *key, size_t len)
217 {
218  if (len == 32) {
219  // Make a copy of the key - it will be expanded in encryptBlock().
220  memcpy(schedule, key, 32);
221  return true;
222  }
223  return false;
224 }
225 
226 void AESTiny256::encryptBlock(uint8_t *output, const uint8_t *input)
227 {
228  uint8_t schedule[32];
229  uint8_t posn;
230  uint8_t round;
231  uint8_t state1[16];
232  uint8_t state2[16];
233  uint8_t temp[4];
234 
235  // Start with the key in the schedule buffer.
236  memcpy(schedule, this->schedule, 32);
237 
238  // Copy the input into the state and perform the first round.
239  for (posn = 0; posn < 16; ++posn)
240  state1[posn] = input[posn] ^ schedule[posn];
241  ENCRYPT(RIGHT);
242 
243  // Perform the next 12 rounds of the cipher two at a time.
244  for (round = 1; round <= 6; ++round) {
245  // Expand the next 32 bytes of the key schedule.
246  KCORE(round);
247  KXOR(1, 0);
248  KXOR(2, 1);
249  KXOR(3, 2);
250  KSBOX();
251  KXOR(5, 4);
252  KXOR(6, 5);
253  KXOR(7, 6);
254 
255  // Encrypt using the left and right halves of the key schedule.
256  ENCRYPT(LEFT);
257  ENCRYPT(RIGHT);
258  }
259 
260  // Expand the final 16 bytes of the key schedule.
261  KCORE(7);
262  KXOR(1, 0);
263  KXOR(2, 1);
264  KXOR(3, 2);
265 
266  // Perform the final round.
267  AESCommon::subBytesAndShiftRows(state2, state1);
268  for (posn = 0; posn < 16; ++posn)
269  output[posn] = state2[posn] ^ schedule[posn];
270 }
271 
272 void AESTiny256::decryptBlock(uint8_t *output, const uint8_t *input)
273 {
274  // Decryption is not supported by AESTiny256.
275 }
276 
278 {
279  clean(schedule);
280 }
281 
309 {
310 }
311 
312 AESSmall256::~AESSmall256()
313 {
314  clean(reverse);
315 }
316 
317 bool AESSmall256::setKey(const uint8_t *key, size_t len)
318 {
319  uint8_t *schedule;
320  uint8_t round;
321  uint8_t temp[4];
322 
323  // Set the encryption key first.
324  if (!AESTiny256::setKey(key, len))
325  return false;
326 
327  // Expand the key schedule up to the last round which gives
328  // us the round keys to use for the final two rounds. We can
329  // then work backwards from there in decryptBlock().
330  schedule = reverse;
331  memcpy(schedule, key, 32);
332  for (round = 1; round <= 6; ++round) {
333  KCORE(round);
334  KXOR(1, 0);
335  KXOR(2, 1);
336  KXOR(3, 2);
337  KSBOX();
338  KXOR(5, 4);
339  KXOR(6, 5);
340  KXOR(7, 6);
341  }
342  KCORE(7);
343  KXOR(1, 0);
344  KXOR(2, 1);
345  KXOR(3, 2);
346 
347  // Key is ready to go.
348  return true;
349 }
350 
351 void AESSmall256::decryptBlock(uint8_t *output, const uint8_t *input)
352 {
353  uint8_t schedule[32];
354  uint8_t round;
355  uint8_t posn;
356  uint8_t state1[16];
357  uint8_t state2[16];
358  uint8_t temp[4];
359 
360  // Start with the end of the decryption schedule.
361  memcpy(schedule, reverse, 32);
362 
363  // Copy the input into the state and reverse the final round.
364  for (posn = 0; posn < 16; ++posn)
365  state1[posn] = input[posn] ^ schedule[posn];
366  AESCommon::inverseShiftRowsAndSubBytes(state2, state1);
367  KXOR(3, 2);
368  KXOR(2, 1);
369  KXOR(1, 0);
370  KCORE(7);
371 
372  // Perform the next 12 rounds of the decryption process two at a time.
373  for (round = 6; round >= 1; --round) {
374  // Decrypt using the right and left halves of the key schedule.
375  DECRYPT(RIGHT);
376  DECRYPT(LEFT);
377 
378  // Expand the next 32 bytes of the key schedule in reverse.
379  KXOR(7, 6);
380  KXOR(6, 5);
381  KXOR(5, 4);
382  KSBOX();
383  KXOR(3, 2);
384  KXOR(2, 1);
385  KXOR(1, 0);
386  KCORE(round);
387  }
388 
389  // Reverse the initial round and create the output words.
390  DECRYPT(RIGHT);
391  for (posn = 0; posn < 16; ++posn)
392  output[posn] = state2[posn] ^ schedule[posn];
393 }
394 
396 {
397  clean(reverse);
399 }
400 
401 #endif // CRYPTO_AES_DEFAULT
AES256()
Constructs an AES 256-bit block cipher with no initial key.
Definition: AES256.cpp:42
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: AES256.cpp:62
size_t keySize() const
Size of a 256-bit AES key in bytes.
Definition: AES256.cpp:57
AESSmall256()
Constructs an AES 256-bit block cipher with no initial key.
Definition: AES256.cpp:308
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
Definition: AES256.cpp:351
void clear()
Clears all security-sensitive state from this block cipher.
Definition: AES256.cpp:395
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: AES256.cpp:317
void encryptBlock(uint8_t *output, const uint8_t *input)
Encrypts a single block using this cipher.
Definition: AES256.cpp:226
size_t keySize() const
Size of a 256-bit AES key in bytes.
Definition: AES256.cpp:211
AESTiny256()
Constructs an AES 256-bit block cipher with no initial key.
Definition: AES256.cpp:189
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: AES256.cpp:216
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
Definition: AES256.cpp:272
void clear()
Clears all security-sensitive state from this block cipher.
Definition: AES256.cpp:277
size_t blockSize() const
Size of an AES block in bytes.
Definition: AES256.cpp:202