knx
ETS configurable knx-stack
aes.c
Go to the documentation of this file.
1 /*
2 
3 This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
4 Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
5 
6 The implementation is verified against the test vectors in:
7  National Institute of Standards and Technology Special Publication 800-38A 2001 ED
8 
9 ECB-AES128
10 ----------
11 
12  plain-text:
13  6bc1bee22e409f96e93d7e117393172a
14  ae2d8a571e03ac9c9eb76fac45af8e51
15  30c81c46a35ce411e5fbc1191a0a52ef
16  f69f2445df4f9b17ad2b417be66c3710
17 
18  key:
19  2b7e151628aed2a6abf7158809cf4f3c
20 
21  resulting cipher
22  3ad77bb40d7a3660a89ecaf32466ef97
23  f5d3d58503b9699de785895a96fdbaaf
24  43b1cd7f598ece23881b00e3ed030688
25  7b0c785e27e8ad3f8223207104725dd4
26 
27 
28 NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
29  You should pad the end of the string with zeros if this is not the case.
30  For AES192/256 the key size is proportionally larger.
31 
32 */
33 
34 
35 /*****************************************************************************/
36 /* Includes: */
37 /*****************************************************************************/
38 #include <string.h> // CBC mode, for memset
39 #include "aes.h"
40 
41 /*****************************************************************************/
42 /* Defines: */
43 /*****************************************************************************/
44 // The number of columns comprising a state in AES. This is a constant in AES. Value=4
45 #define Nb 4
46 
47 #if defined(AES256) && (AES256 == 1)
48  #define Nk 8
49  #define Nr 14
50 #elif defined(AES192) && (AES192 == 1)
51  #define Nk 6
52  #define Nr 12
53 #else
54  #define Nk 4 // The number of 32 bit words in a key.
55  #define Nr 10 // The number of rounds in AES Cipher.
56 #endif
57 
58 // jcallan@github points out that declaring Multiply as a function
59 // reduces code size considerably with the Keil ARM compiler.
60 // See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3
61 #ifndef MULTIPLY_AS_A_FUNCTION
62  #define MULTIPLY_AS_A_FUNCTION 0
63 #endif
64 
65 
66 
67 
68 /*****************************************************************************/
69 /* Private variables: */
70 /*****************************************************************************/
71 // state - array holding the intermediate results during decryption.
72 typedef uint8_t state_t[4][4];
73 
74 
75 
76 // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
77 // The numbers below can be computed dynamically trading ROM for RAM -
78 // This can be useful in (embedded) bootloader applications, where ROM is often limited.
79 static const uint8_t sbox[256] =
80 {
81  //0 1 2 3 4 5 6 7 8 9 A B C D E F
82  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
83  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
84  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
85  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
86  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
87  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
88  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
89  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
90  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
91  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
92  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
93  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
94  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
95  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
96  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
97  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
98 };
99 
100 static const uint8_t rsbox[256] =
101 {
102  0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
103  0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
104  0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
105  0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
106  0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
107  0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
108  0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
109  0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
110  0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
111  0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
112  0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
113  0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
114  0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
115  0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
116  0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
117  0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
118 };
119 
120 // The round constant word array, Rcon[i], contains the values given by
121 // x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
122 static const uint8_t Rcon[11] =
123 {
124  0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
125 };
126 
127 /*
128  * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
129  * that you can remove most of the elements in the Rcon array, because they are unused.
130  *
131  * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
132  *
133  * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed),
134  * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
135  */
136 
137 
138 /*****************************************************************************/
139 /* Private functions: */
140 /*****************************************************************************/
141 /*
142 static uint8_t getSBoxValue(uint8_t num)
143 {
144  return sbox[num];
145 }
146 */
147 #define getSBoxValue(num) (sbox[(num)])
148 /*
149 static uint8_t getSBoxInvert(uint8_t num)
150 {
151  return rsbox[num];
152 }
153 */
154 #define getSBoxInvert(num) (rsbox[(num)])
155 
156 // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
157 static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key)
158 {
159  unsigned i, j, k;
160  uint8_t tempa[4]; // Used for the column/row operations
161 
162  // The first round key is the key itself.
163  for (i = 0; i < Nk; ++i)
164  {
165  RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
166  RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
167  RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
168  RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
169  }
170 
171  // All other round keys are found from the previous round keys.
172  for (i = Nk; i < Nb * (Nr + 1); ++i)
173  {
174  {
175  k = (i - 1) * 4;
176  tempa[0] = RoundKey[k + 0];
177  tempa[1] = RoundKey[k + 1];
178  tempa[2] = RoundKey[k + 2];
179  tempa[3] = RoundKey[k + 3];
180 
181  }
182 
183  if (i % Nk == 0)
184  {
185  // This function shifts the 4 bytes in a word to the left once.
186  // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
187 
188  // Function RotWord()
189  {
190  const uint8_t u8tmp = tempa[0];
191  tempa[0] = tempa[1];
192  tempa[1] = tempa[2];
193  tempa[2] = tempa[3];
194  tempa[3] = u8tmp;
195  }
196 
197  // SubWord() is a function that takes a four-byte input word and
198  // applies the S-box to each of the four bytes to produce an output word.
199 
200  // Function Subword()
201  {
202  tempa[0] = getSBoxValue(tempa[0]);
203  tempa[1] = getSBoxValue(tempa[1]);
204  tempa[2] = getSBoxValue(tempa[2]);
205  tempa[3] = getSBoxValue(tempa[3]);
206  }
207 
208  tempa[0] = tempa[0] ^ Rcon[i / Nk];
209  }
210 
211 #if defined(AES256) && (AES256 == 1)
212 
213  if (i % Nk == 4)
214  {
215  // Function Subword()
216  {
217  tempa[0] = getSBoxValue(tempa[0]);
218  tempa[1] = getSBoxValue(tempa[1]);
219  tempa[2] = getSBoxValue(tempa[2]);
220  tempa[3] = getSBoxValue(tempa[3]);
221  }
222  }
223 
224 #endif
225  j = i * 4;
226  k = (i - Nk) * 4;
227  RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
228  RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
229  RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
230  RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
231  }
232 }
233 
234 void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key)
235 {
236  KeyExpansion(ctx->RoundKey, key);
237 }
238 #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
239 void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv)
240 {
241  KeyExpansion(ctx->RoundKey, key);
242  memcpy (ctx->Iv, iv, AES_BLOCKLEN);
243 }
244 void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv)
245 {
246  memcpy (ctx->Iv, iv, AES_BLOCKLEN);
247 }
248 #endif
249 
250 // This function adds the round key to state.
251 // The round key is added to the state by an XOR function.
252 static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey)
253 {
254  uint8_t i, j;
255 
256  for (i = 0; i < 4; ++i)
257  {
258  for (j = 0; j < 4; ++j)
259  {
260  (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
261  }
262  }
263 }
264 
265 // The SubBytes Function Substitutes the values in the
266 // state matrix with values in an S-box.
267 static void SubBytes(state_t* state)
268 {
269  uint8_t i, j;
270 
271  for (i = 0; i < 4; ++i)
272  {
273  for (j = 0; j < 4; ++j)
274  {
275  (*state)[j][i] = getSBoxValue((*state)[j][i]);
276  }
277  }
278 }
279 
280 // The ShiftRows() function shifts the rows in the state to the left.
281 // Each row is shifted with different offset.
282 // Offset = Row number. So the first row is not shifted.
283 static void ShiftRows(state_t* state)
284 {
285  uint8_t temp;
286 
287  // Rotate first row 1 columns to left
288  temp = (*state)[0][1];
289  (*state)[0][1] = (*state)[1][1];
290  (*state)[1][1] = (*state)[2][1];
291  (*state)[2][1] = (*state)[3][1];
292  (*state)[3][1] = temp;
293 
294  // Rotate second row 2 columns to left
295  temp = (*state)[0][2];
296  (*state)[0][2] = (*state)[2][2];
297  (*state)[2][2] = temp;
298 
299  temp = (*state)[1][2];
300  (*state)[1][2] = (*state)[3][2];
301  (*state)[3][2] = temp;
302 
303  // Rotate third row 3 columns to left
304  temp = (*state)[0][3];
305  (*state)[0][3] = (*state)[3][3];
306  (*state)[3][3] = (*state)[2][3];
307  (*state)[2][3] = (*state)[1][3];
308  (*state)[1][3] = temp;
309 }
310 
311 static uint8_t xtime(uint8_t x)
312 {
313  return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
314 }
315 
316 // MixColumns function mixes the columns of the state matrix
317 static void MixColumns(state_t* state)
318 {
319  uint8_t i;
320  uint8_t Tmp, Tm, t;
321 
322  for (i = 0; i < 4; ++i)
323  {
324  t = (*state)[i][0];
325  Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
326  Tm = (*state)[i][0] ^ (*state)[i][1] ;
327  Tm = xtime(Tm);
328  (*state)[i][0] ^= Tm ^ Tmp ;
329  Tm = (*state)[i][1] ^ (*state)[i][2] ;
330  Tm = xtime(Tm);
331  (*state)[i][1] ^= Tm ^ Tmp ;
332  Tm = (*state)[i][2] ^ (*state)[i][3] ;
333  Tm = xtime(Tm);
334  (*state)[i][2] ^= Tm ^ Tmp ;
335  Tm = (*state)[i][3] ^ t ;
336  Tm = xtime(Tm);
337  (*state)[i][3] ^= Tm ^ Tmp ;
338  }
339 }
340 
341 // Multiply is used to multiply numbers in the field GF(2^8)
342 // Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
343 // The compiler seems to be able to vectorize the operation better this way.
344 // See https://github.com/kokke/tiny-AES-c/pull/34
345 #if MULTIPLY_AS_A_FUNCTION
346 static uint8_t Multiply(uint8_t x, uint8_t y)
347 {
348  return (((y & 1) * x) ^
349  ((y >> 1 & 1) * xtime(x)) ^
350  ((y >> 2 & 1) * xtime(xtime(x))) ^
351  ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^
352  ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */
353 }
354 #else
355 #define Multiply(x, y) \
356  ( ((y & 1) * x) ^ \
357  ((y>>1 & 1) * xtime(x)) ^ \
358  ((y>>2 & 1) * xtime(xtime(x))) ^ \
359  ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
360  ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
361 
362 #endif
363 
364 #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
365 // MixColumns function mixes the columns of the state matrix.
366 // The method used to multiply may be difficult to understand for the inexperienced.
367 // Please use the references to gain more information.
368 static void InvMixColumns(state_t* state)
369 {
370  int i;
371  uint8_t a, b, c, d;
372 
373  for (i = 0; i < 4; ++i)
374  {
375  a = (*state)[i][0];
376  b = (*state)[i][1];
377  c = (*state)[i][2];
378  d = (*state)[i][3];
379 
380  (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
381  (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
382  (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
383  (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
384  }
385 }
386 
387 
388 // The SubBytes Function Substitutes the values in the
389 // state matrix with values in an S-box.
390 static void InvSubBytes(state_t* state)
391 {
392  uint8_t i, j;
393 
394  for (i = 0; i < 4; ++i)
395  {
396  for (j = 0; j < 4; ++j)
397  {
398  (*state)[j][i] = getSBoxInvert((*state)[j][i]);
399  }
400  }
401 }
402 
403 static void InvShiftRows(state_t* state)
404 {
405  uint8_t temp;
406 
407  // Rotate first row 1 columns to right
408  temp = (*state)[3][1];
409  (*state)[3][1] = (*state)[2][1];
410  (*state)[2][1] = (*state)[1][1];
411  (*state)[1][1] = (*state)[0][1];
412  (*state)[0][1] = temp;
413 
414  // Rotate second row 2 columns to right
415  temp = (*state)[0][2];
416  (*state)[0][2] = (*state)[2][2];
417  (*state)[2][2] = temp;
418 
419  temp = (*state)[1][2];
420  (*state)[1][2] = (*state)[3][2];
421  (*state)[3][2] = temp;
422 
423  // Rotate third row 3 columns to right
424  temp = (*state)[0][3];
425  (*state)[0][3] = (*state)[1][3];
426  (*state)[1][3] = (*state)[2][3];
427  (*state)[2][3] = (*state)[3][3];
428  (*state)[3][3] = temp;
429 }
430 #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
431 
432 // Cipher is the main function that encrypts the PlainText.
433 static void Cipher(state_t* state, const uint8_t* RoundKey)
434 {
435  uint8_t round = 0;
436 
437  // Add the First round key to the state before starting the rounds.
438  AddRoundKey(0, state, RoundKey);
439 
440  // There will be Nr rounds.
441  // The first Nr-1 rounds are identical.
442  // These Nr rounds are executed in the loop below.
443  // Last one without MixColumns()
444  for (round = 1; ; ++round)
445  {
446  SubBytes(state);
447  ShiftRows(state);
448 
449  if (round == Nr)
450  {
451  break;
452  }
453 
454  MixColumns(state);
455  AddRoundKey(round, state, RoundKey);
456  }
457 
458  // Add round key to last round
459  AddRoundKey(Nr, state, RoundKey);
460 }
461 
462 #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
463 static void InvCipher(state_t* state, const uint8_t* RoundKey)
464 {
465  uint8_t round = 0;
466 
467  // Add the First round key to the state before starting the rounds.
468  AddRoundKey(Nr, state, RoundKey);
469 
470  // There will be Nr rounds.
471  // The first Nr-1 rounds are identical.
472  // These Nr rounds are executed in the loop below.
473  // Last one without InvMixColumn()
474  for (round = (Nr - 1); ; --round)
475  {
476  InvShiftRows(state);
477  InvSubBytes(state);
478  AddRoundKey(round, state, RoundKey);
479 
480  if (round == 0)
481  {
482  break;
483  }
484 
485  InvMixColumns(state);
486  }
487 
488 }
489 #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
490 
491 /*****************************************************************************/
492 /* Public functions: */
493 /*****************************************************************************/
494 #if defined(ECB) && (ECB == 1)
495 
496 
497 void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf)
498 {
499  // The next function call encrypts the PlainText with the Key using AES algorithm.
500  Cipher((state_t*)buf, ctx->RoundKey);
501 }
502 
503 void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf)
504 {
505  // The next function call decrypts the PlainText with the Key using AES algorithm.
506  InvCipher((state_t*)buf, ctx->RoundKey);
507 }
508 
509 
510 #endif // #if defined(ECB) && (ECB == 1)
511 
512 
513 
514 
515 
516 #if defined(CBC) && (CBC == 1)
517 
518 
519 static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
520 {
521  uint8_t i;
522 
523  for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
524  {
525  buf[i] ^= Iv[i];
526  }
527 }
528 
529 void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
530 {
531  uintptr_t i;
532  uint8_t* Iv = ctx->Iv;
533 
534  for (i = 0; i < length; i += AES_BLOCKLEN)
535  {
536  XorWithIv(buf, Iv);
537  Cipher((state_t*)buf, ctx->RoundKey);
538  Iv = buf;
539  buf += AES_BLOCKLEN;
540  }
541 
542  /* store Iv in ctx for next call */
543  memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
544 }
545 
546 void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
547 {
548  uintptr_t i;
549  uint8_t storeNextIv[AES_BLOCKLEN];
550 
551  for (i = 0; i < length; i += AES_BLOCKLEN)
552  {
553  memcpy(storeNextIv, buf, AES_BLOCKLEN);
554  InvCipher((state_t*)buf, ctx->RoundKey);
555  XorWithIv(buf, ctx->Iv);
556  memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
557  buf += AES_BLOCKLEN;
558  }
559 
560 }
561 
562 #endif // #if defined(CBC) && (CBC == 1)
563 
564 
565 
566 #if defined(CTR) && (CTR == 1)
567 
568 /* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
569 void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
570 {
571  uint8_t buffer[AES_BLOCKLEN];
572 
573  unsigned i;
574  int bi;
575 
576  for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
577  {
578  if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
579  {
580 
581  memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
582  Cipher((state_t*)buffer, ctx->RoundKey);
583 
584  /* Increment Iv and handle overflow */
585  for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
586  {
587  /* inc will overflow */
588  if (ctx->Iv[bi] == 255)
589  {
590  ctx->Iv[bi] = 0;
591  continue;
592  }
593 
594  ctx->Iv[bi] += 1;
595  break;
596  }
597 
598  bi = 0;
599  }
600 
601  buf[i] = (buf[i] ^ buffer[bi]);
602  }
603 }
604 
605 #endif // #if defined(CTR) && (CTR == 1)
606 
void AES_CBC_decrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, uint32_t length)
Definition: aes.c:546
void AES_ECB_encrypt(const struct AES_ctx *ctx, uint8_t *buf)
Definition: aes.c:497
uint8_t state_t[4][4]
Definition: aes.c:72
void AES_CTR_xcrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, uint32_t length)
Definition: aes.c:569
void AES_init_ctx_iv(struct AES_ctx *ctx, const uint8_t *key, const uint8_t *iv)
Definition: aes.c:239
void AES_ECB_decrypt(const struct AES_ctx *ctx, uint8_t *buf)
Definition: aes.c:503
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, uint32_t length)
Definition: aes.c:529
void AES_init_ctx(struct AES_ctx *ctx, const uint8_t *key)
Definition: aes.c:234
void AES_ctx_set_iv(struct AES_ctx *ctx, const uint8_t *iv)
Definition: aes.c:244
Definition: aes.h:44
uint8_t Iv[AES_BLOCKLEN]
Definition: aes.h:47
uint8_t RoundKey[AES_keyExpSize]
Definition: aes.h:45