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