source: trunk/tools/FileEncrypt/src/aes.c@ 9

Last change on this file since 9 was 1, checked in by f.jahn, 3 years ago
File size: 18.6 KB
Line 
1/*
2
3This is an implementation of the AES128 algorithm, specifically ECB and CBC mode.
4
5The implementation is verified against the test vectors in:
6 National Institute of Standards and Technology Special Publication 800-38A 2001 ED
7
8ECB-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
27NOTE: 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 <stdint.h>
37#include <string.h> // CBC mode, for memset
38#include "aes.h"
39#include<stdio.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.
66typedef uint8_t state_t[4][4];
67static state_t* state;
68
69// The array that stores the round keys.
70static uint8_t RoundKey[176];
71
72// The Key input to the AES Program
73static 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.
83static 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
102static 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).
124static 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/*****************************************************************************/
146static uint8_t getSBoxValue(uint8_t num)
147{
148 return sbox[num];
149}
150
151static uint8_t getSBoxInvert(uint8_t num)
152{
153 return rsbox[num];
154}
155
156// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
157static void KeyExpansion(void)
158{
159 uint32_t 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 < (Nb * (Nr + 1))); ++i)
173 {
174 for(j = 0; j < 4; ++j)
175 {
176 tempa[j]=RoundKey[(i-1) * 4 + j];
177 }
178 if (i % Nk == 0)
179 {
180 // This function rotates 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 k = tempa[0];
186 tempa[0] = tempa[1];
187 tempa[1] = tempa[2];
188 tempa[2] = tempa[3];
189 tempa[3] = k;
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 tempa[0] = getSBoxValue(tempa[0]);
198 tempa[1] = getSBoxValue(tempa[1]);
199 tempa[2] = getSBoxValue(tempa[2]);
200 tempa[3] = getSBoxValue(tempa[3]);
201 }
202
203 tempa[0] = tempa[0] ^ Rcon[i/Nk];
204 }
205 else if (Nk > 6 && i % Nk == 4)
206 {
207 // Function Subword()
208 {
209 tempa[0] = getSBoxValue(tempa[0]);
210 tempa[1] = getSBoxValue(tempa[1]);
211 tempa[2] = getSBoxValue(tempa[2]);
212 tempa[3] = getSBoxValue(tempa[3]);
213 }
214 }
215 RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0];
216 RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1];
217 RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2];
218 RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3];
219 }
220}
221
222// This function adds the round key to state.
223// The round key is added to the state by an XOR function.
224static void AddRoundKey(uint8_t round)
225{
226 uint8_t i,j;
227 for(i=0;i<4;++i)
228 {
229 for(j = 0; j < 4; ++j)
230 {
231 (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j];
232 }
233 }
234}
235
236// The SubBytes Function Substitutes the values in the
237// state matrix with values in an S-box.
238static void SubBytes(void)
239{
240 uint8_t i, j;
241 for(i = 0; i < 4; ++i)
242 {
243 for(j = 0; j < 4; ++j)
244 {
245 (*state)[j][i] = getSBoxValue((*state)[j][i]);
246 }
247 }
248}
249
250// The ShiftRows() function shifts the rows in the state to the left.
251// Each row is shifted with different offset.
252// Offset = Row number. So the first row is not shifted.
253static void ShiftRows(void)
254{
255 uint8_t temp;
256
257 // Rotate first row 1 columns to left
258 temp = (*state)[0][1];
259 (*state)[0][1] = (*state)[1][1];
260 (*state)[1][1] = (*state)[2][1];
261 (*state)[2][1] = (*state)[3][1];
262 (*state)[3][1] = temp;
263
264 // Rotate second row 2 columns to left
265 temp = (*state)[0][2];
266 (*state)[0][2] = (*state)[2][2];
267 (*state)[2][2] = temp;
268
269 temp = (*state)[1][2];
270 (*state)[1][2] = (*state)[3][2];
271 (*state)[3][2] = temp;
272
273 // Rotate third row 3 columns to left
274 temp = (*state)[0][3];
275 (*state)[0][3] = (*state)[3][3];
276 (*state)[3][3] = (*state)[2][3];
277 (*state)[2][3] = (*state)[1][3];
278 (*state)[1][3] = temp;
279}
280
281static uint8_t xtime(uint8_t x)
282{
283 return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
284}
285
286// MixColumns function mixes the columns of the state matrix
287static void MixColumns(void)
288{
289 uint8_t i;
290 uint8_t Tmp,Tm,t;
291 for(i = 0; i < 4; ++i)
292 {
293 t = (*state)[i][0];
294 Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
295 Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
296 Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
297 Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
298 Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
299 }
300}
301
302// Multiply is used to multiply numbers in the field GF(2^8)
303#if MULTIPLY_AS_A_FUNCTION
304static uint8_t Multiply(uint8_t x, uint8_t y)
305{
306 return (((y & 1) * x) ^
307 ((y>>1 & 1) * xtime(x)) ^
308 ((y>>2 & 1) * xtime(xtime(x))) ^
309 ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
310 ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))));
311 }
312#else
313#define Multiply(x, y) \
314 ( ((y & 1) * x) ^ \
315 ((y>>1 & 1) * xtime(x)) ^ \
316 ((y>>2 & 1) * xtime(xtime(x))) ^ \
317 ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
318 ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
319
320#endif
321
322// MixColumns function mixes the columns of the state matrix.
323// The method used to multiply may be difficult to understand for the inexperienced.
324// Please use the references to gain more information.
325static void InvMixColumns(void)
326{
327 int i;
328 uint8_t a,b,c,d;
329 for(i=0;i<4;++i)
330 {
331 a = (*state)[i][0];
332 b = (*state)[i][1];
333 c = (*state)[i][2];
334 d = (*state)[i][3];
335
336 (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
337 (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
338 (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
339 (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
340 }
341}
342
343
344// The SubBytes Function Substitutes the values in the
345// state matrix with values in an S-box.
346static void InvSubBytes(void)
347{
348 uint8_t i,j;
349 for(i=0;i<4;++i)
350 {
351 for(j=0;j<4;++j)
352 {
353 (*state)[j][i] = getSBoxInvert((*state)[j][i]);
354 }
355 }
356}
357
358static void InvShiftRows(void)
359{
360 uint8_t temp;
361
362 // Rotate first row 1 columns to right
363 temp=(*state)[3][1];
364 (*state)[3][1]=(*state)[2][1];
365 (*state)[2][1]=(*state)[1][1];
366 (*state)[1][1]=(*state)[0][1];
367 (*state)[0][1]=temp;
368
369 // Rotate second row 2 columns to right
370 temp=(*state)[0][2];
371 (*state)[0][2]=(*state)[2][2];
372 (*state)[2][2]=temp;
373
374 temp=(*state)[1][2];
375 (*state)[1][2]=(*state)[3][2];
376 (*state)[3][2]=temp;
377
378 // Rotate third row 3 columns to right
379 temp=(*state)[0][3];
380 (*state)[0][3]=(*state)[1][3];
381 (*state)[1][3]=(*state)[2][3];
382 (*state)[2][3]=(*state)[3][3];
383 (*state)[3][3]=temp;
384}
385
386
387// Cipher is the main function that encrypts the PlainText.
388static void Cipher(void)
389{
390 uint8_t round = 0;
391
392 // Add the First round key to the state before starting the rounds.
393 AddRoundKey(0);
394
395 // There will be Nr rounds.
396 // The first Nr-1 rounds are identical.
397 // These Nr-1 rounds are executed in the loop below.
398 for(round = 1; round < Nr; ++round)
399 {
400 SubBytes();
401 ShiftRows();
402 MixColumns();
403 AddRoundKey(round);
404 }
405
406 // The last round is given below.
407 // The MixColumns function is not here in the last round.
408 SubBytes();
409 ShiftRows();
410 AddRoundKey(Nr);
411}
412
413static void InvCipher(void)
414{
415 uint8_t round=0;
416
417 // Add the First round key to the state before starting the rounds.
418 AddRoundKey(Nr);
419
420 // There will be Nr rounds.
421 // The first Nr-1 rounds are identical.
422 // These Nr-1 rounds are executed in the loop below.
423 for(round=Nr-1;round>0;round--)
424 {
425 InvShiftRows();
426 InvSubBytes();
427 AddRoundKey(round);
428 InvMixColumns();
429 }
430
431 // The last round is given below.
432 // The MixColumns function is not here in the last round.
433 InvShiftRows();
434 InvSubBytes();
435 AddRoundKey(0);
436}
437
438static void BlockCopy(uint8_t* output, uint8_t* input)
439{
440 uint8_t i;
441 for (i=0;i<KEYLEN;++i)
442 {
443 output[i] = input[i];
444 }
445}
446
447
448
449/*****************************************************************************/
450/* Public functions: */
451/*****************************************************************************/
452#if defined(ECB) && ECB
453
454
455void AES128_ECB_encrypt(uint8_t* input, const uint8_t* key, uint8_t* output)
456{
457 // Copy input to output, and work in-memory on output
458 BlockCopy(output, input);
459 state = (state_t*)output;
460
461 Key = key;
462 KeyExpansion();
463
464 // The next function call encrypts the PlainText with the Key using AES algorithm.
465 Cipher();
466}
467
468void AES128_ECB_decrypt(uint8_t* input, const uint8_t* key, uint8_t *output)
469{
470 // Copy input to output, and work in-memory on output
471 BlockCopy(output, input);
472 state = (state_t*)output;
473
474 // The KeyExpansion routine must be called before encryption.
475 Key = key;
476 KeyExpansion();
477
478 InvCipher();
479}
480
481
482#endif // #if defined(ECB) && ECB
483
484
485
486
487
488#if defined(CBC) && CBC
489
490
491static void XorWithIv(uint8_t* buf)
492{
493 uint8_t i;
494 for(i = 0; i < KEYLEN; ++i)
495 {
496 buf[i] ^= Iv[i];
497 }
498}
499
500void AES128_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
501{
502 uintptr_t i;
503 uint8_t remainders = length % KEYLEN; /* Remaining bytes in the last non-full block */
504
505 BlockCopy(output, input);
506 state = (state_t*)output;
507
508 // Skip the key expansion if key is passed as 0
509 if(0 != key)
510 {
511 Key = key;
512 KeyExpansion();
513 }
514
515 if(iv != 0)
516 {
517 Iv = (uint8_t*)iv;
518 }
519
520 for(i = 0; i < length; i += KEYLEN)
521 {
522 XorWithIv(input);
523 BlockCopy(output, input);
524 state = (state_t*)output;
525 Cipher();
526 Iv = output;
527 input += KEYLEN;
528 output += KEYLEN;
529 }
530
531 if(remainders)
532 {
533 BlockCopy(output, input);
534 memset(output + remainders, 0, KEYLEN - remainders); /* add 0-padding */
535 state = (state_t*)output;
536 Cipher();
537 }
538}
539
540void AES128_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
541{
542 uintptr_t i;
543 uint8_t remainders = length % KEYLEN; /* Remaining bytes in the last non-full block */
544
545 BlockCopy(output, input);
546 state = (state_t*)output;
547
548 // Skip the key expansion if key is passed as 0
549 if(0 != key)
550 {
551 Key = key;
552 KeyExpansion();
553 }
554
555 // If iv is passed as 0, we continue to encrypt without re-setting the Iv
556 if(iv != 0)
557 {
558 Iv = (uint8_t*)iv;
559 }
560
561 for(i = 0; i < length; i += KEYLEN)
562 {
563 BlockCopy(output, input);
564 state = (state_t*)output;
565 InvCipher();
566 XorWithIv(output);
567 Iv = input;
568 input += KEYLEN;
569 output += KEYLEN;
570 }
571
572 if(remainders)
573 {
574 BlockCopy(output, input);
575 memset(output+remainders, 0, KEYLEN - remainders); /* add 0-padding */
576 state = (state_t*)output;
577 InvCipher();
578 }
579}
580
581
582#endif // #if defined(CBC) && CBC
583
584
585// prints string as hex
586void phex(uint8_t* str, int num)
587{
588 unsigned char i;
589 for(i = 0; i < num ; ++i)
590 if (i < (num - 1)) printf("%.2x-", str[i]);
591 else printf("%.2x", str[i]);
592 printf("\n");
593}
Note: See TracBrowser for help on using the repository browser.