Arduino Cryptography Library
AES128.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 = 10;
45  schedule = sched;
46 }
47 
48 AES128::~AES128()
49 {
50  clean(sched);
51 }
52 
57 size_t AES128::keySize() const
58 {
59  return 16;
60 }
61 
62 bool AES128::setKey(const uint8_t *key, size_t len)
63 {
64  if (len != 16)
65  return false;
66 
67  // Copy the key itself into the first 16 bytes of the schedule.
68  uint8_t *schedule = sched;
69  memcpy(schedule, key, 16);
70 
71  // Expand the key schedule until we have 176 bytes of expanded key.
72  uint8_t iteration = 1;
73  uint8_t n = 16;
74  uint8_t w = 4;
75  while (n < 176) {
76  if (w == 4) {
77  // Every 16 bytes (4 words) we need to apply the key schedule core.
78  keyScheduleCore(schedule + 16, schedule + 12, iteration);
79  schedule[16] ^= schedule[0];
80  schedule[17] ^= schedule[1];
81  schedule[18] ^= schedule[2];
82  schedule[19] ^= schedule[3];
83  ++iteration;
84  w = 0;
85  } else {
86  // Otherwise just XOR the word with the one 16 bytes previous.
87  schedule[16] = schedule[12] ^ schedule[0];
88  schedule[17] = schedule[13] ^ schedule[1];
89  schedule[18] = schedule[14] ^ schedule[2];
90  schedule[19] = schedule[15] ^ schedule[3];
91  }
92 
93  // Advance to the next word in the schedule.
94  schedule += 4;
95  n += 4;
96  ++w;
97  }
98 
99  return true;
100 }
101 
127 // Helper macros.
128 #define KCORE(n) \
129  do { \
130  AESCommon::keyScheduleCore(temp, schedule + 12, (n)); \
131  schedule[0] ^= temp[0]; \
132  schedule[1] ^= temp[1]; \
133  schedule[2] ^= temp[2]; \
134  schedule[3] ^= temp[3]; \
135  } while (0)
136 #define KXOR(a, b) \
137  do { \
138  schedule[(a) * 4] ^= schedule[(b) * 4]; \
139  schedule[(a) * 4 + 1] ^= schedule[(b) * 4 + 1]; \
140  schedule[(a) * 4 + 2] ^= schedule[(b) * 4 + 2]; \
141  schedule[(a) * 4 + 3] ^= schedule[(b) * 4 + 3]; \
142  } while (0)
143 
153 {
154 }
155 
156 AESTiny128::~AESTiny128()
157 {
158  clean(schedule);
159 }
160 
165 size_t AESTiny128::blockSize() const
166 {
167  return 16;
168 }
169 
174 size_t AESTiny128::keySize() const
175 {
176  return 16;
177 }
178 
179 bool AESTiny128::setKey(const uint8_t *key, size_t len)
180 {
181  if (len == 16) {
182  // Make a copy of the key - it will be expanded in encryptBlock().
183  memcpy(schedule, key, 16);
184  return true;
185  }
186  return false;
187 }
188 
189 void AESTiny128::encryptBlock(uint8_t *output, const uint8_t *input)
190 {
191  uint8_t schedule[16];
192  uint8_t posn;
193  uint8_t round;
194  uint8_t state1[16];
195  uint8_t state2[16];
196  uint8_t temp[4];
197 
198  // Start with the key in the schedule buffer.
199  memcpy(schedule, this->schedule, 16);
200 
201  // Copy the input into the state and XOR with the key schedule.
202  for (posn = 0; posn < 16; ++posn)
203  state1[posn] = input[posn] ^ schedule[posn];
204 
205  // Perform the first 9 rounds of the cipher.
206  for (round = 1; round <= 9; ++round) {
207  // Expand the next 16 bytes of the key schedule.
208  KCORE(round);
209  KXOR(1, 0);
210  KXOR(2, 1);
211  KXOR(3, 2);
212 
213  // Encrypt using the key schedule.
214  AESCommon::subBytesAndShiftRows(state2, state1);
215  AESCommon::mixColumn(state1, state2);
216  AESCommon::mixColumn(state1 + 4, state2 + 4);
217  AESCommon::mixColumn(state1 + 8, state2 + 8);
218  AESCommon::mixColumn(state1 + 12, state2 + 12);
219  for (posn = 0; posn < 16; ++posn)
220  state1[posn] ^= schedule[posn];
221  }
222 
223  // Expand the final 16 bytes of the key schedule.
224  KCORE(10);
225  KXOR(1, 0);
226  KXOR(2, 1);
227  KXOR(3, 2);
228 
229  // Perform the final round.
230  AESCommon::subBytesAndShiftRows(state2, state1);
231  for (posn = 0; posn < 16; ++posn)
232  output[posn] = state2[posn] ^ schedule[posn];
233 }
234 
235 void AESTiny128::decryptBlock(uint8_t *output, const uint8_t *input)
236 {
237  // Decryption is not supported by AESTiny128.
238 }
239 
241 {
242  clean(schedule);
243 }
244 
272 {
273 }
274 
275 AESSmall128::~AESSmall128()
276 {
277  clean(reverse);
278 }
279 
280 bool AESSmall128::setKey(const uint8_t *key, size_t len)
281 {
282  uint8_t *schedule;
283  uint8_t round;
284  uint8_t temp[4];
285 
286  // Set the encryption key first.
287  if (!AESTiny128::setKey(key, len))
288  return false;
289 
290  // Expand the key schedule up to the last round which gives
291  // us the round keys to use for the final two rounds. We can
292  // then work backwards from there in decryptBlock().
293  schedule = reverse;
294  memcpy(schedule, key, 16);
295  for (round = 1; round <= 10; ++round) {
296  KCORE(round);
297  KXOR(1, 0);
298  KXOR(2, 1);
299  KXOR(3, 2);
300  }
301 
302  // Key is ready to go.
303  return true;
304 }
305 
306 void AESSmall128::decryptBlock(uint8_t *output, const uint8_t *input)
307 {
308  uint8_t schedule[16];
309  uint8_t round;
310  uint8_t posn;
311  uint8_t state1[16];
312  uint8_t state2[16];
313  uint8_t temp[4];
314 
315  // Start with the end of the decryption schedule.
316  memcpy(schedule, reverse, 16);
317 
318  // Copy the input into the state and reverse the final round.
319  for (posn = 0; posn < 16; ++posn)
320  state1[posn] = input[posn] ^ schedule[posn];
321  AESCommon::inverseShiftRowsAndSubBytes(state2, state1);
322  KXOR(3, 2);
323  KXOR(2, 1);
324  KXOR(1, 0);
325  KCORE(10);
326 
327  // Perform the next 9 rounds of the decryption process.
328  for (round = 9; round >= 1; --round) {
329  // Decrypt using the key schedule.
330  for (posn = 0; posn < 16; ++posn)
331  state2[posn] ^= schedule[posn];
332  AESCommon::inverseMixColumn(state1, state2);
333  AESCommon::inverseMixColumn(state1 + 4, state2 + 4);
334  AESCommon::inverseMixColumn(state1 + 8, state2 + 8);
335  AESCommon::inverseMixColumn(state1 + 12, state2 + 12);
336  AESCommon::inverseShiftRowsAndSubBytes(state2, state1);
337 
338  // Expand the next 16 bytes of the key schedule in reverse.
339  KXOR(3, 2);
340  KXOR(2, 1);
341  KXOR(1, 0);
342  KCORE(round);
343  }
344 
345  // Reverse the initial round and create the output words.
346  for (posn = 0; posn < 16; ++posn)
347  output[posn] = state2[posn] ^ schedule[posn];
348 }
349 
351 {
352  clean(reverse);
354 }
355 
356 #endif // CRYPTO_AES_DEFAULT
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: AES128.cpp:62
size_t keySize() const
Size of a 128-bit AES key in bytes.
Definition: AES128.cpp:57
AES128()
Constructs an AES 128-bit block cipher with no initial key.
Definition: AES128.cpp:42
void clear()
Clears all security-sensitive state from this block cipher.
Definition: AES128.cpp:350
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: AES128.cpp:280
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
Definition: AES128.cpp:306
AESSmall128()
Constructs an AES 128-bit block cipher with no initial key.
Definition: AES128.cpp:271
void clear()
Clears all security-sensitive state from this block cipher.
Definition: AES128.cpp:240
AESTiny128()
Constructs an AES 128-bit block cipher with no initial key.
Definition: AES128.cpp:152
size_t blockSize() const
Size of an AES block in bytes.
Definition: AES128.cpp:165
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: AES128.cpp:179
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
Definition: AES128.cpp:235
void encryptBlock(uint8_t *output, const uint8_t *input)
Encrypts a single block using this cipher.
Definition: AES128.cpp:189
size_t keySize() const
Size of a 128-bit AES key in bytes.
Definition: AES128.cpp:174