File Coverage

tiny-AES-c/aes.c
Criterion Covered Total %
statement 0 177 0.0
branch 0 40 0.0
condition n/a
subroutine n/a
pod n/a
total 0 217 0.0


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