source: svn/trunk/newcon3bcm2_21bu/dta/src/bootloader/aes/aes.c @ 2

Last change on this file since 2 was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 7.2 KB
Line 
1/* AES Implementation by X-N2O
2 * Started:  15:41:35 - 18 Nov 2009
3 * Finished: 20:03:59 - 21 Nov 2009
4 * Logarithm, S-Box, and RCON tables are not hardcoded
5 * Instead they are generated when the program starts
6 * All of the code below is based from the AES specification
7 * You can find it at http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
8 * This is only a proof of concept, and should not be considered as the most efficient implementation
9 *
10 * This work is licensed under the Creative Commons Attribution 3.0 Unported License.
11 * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons:
12 * 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
13 */
14
15#include "ministd.h"
16#include "aes.h"
17
18unsigned char g_aes_logt[256], g_aes_ilogt[256];
19unsigned char g_aes_sbox[256], g_aes_isbox[256];
20
21void init_aes()
22{
23        int i;
24        unsigned char gen;
25
26        // build logarithm table and it's inverse
27        gen = 1;
28        for(i = 0; i < 0xff; i++) {
29                g_aes_logt[gen]  = i;
30                g_aes_ilogt[i]   = gen;
31                gen = aes_mul_manual(gen, AES_GEN);
32        }
33
34        // build S-Box and it's inverse
35        for(i = 0; i <= 0xff; i++) {
36                char bi;
37                unsigned char inv = aes_inv(i);
38
39                g_aes_sbox[i] = 0;
40                for(bi = 0; bi < 8; bi++) {
41                        // based on transformation 5.1
42                        // could also be done with a loop based on the matrix
43                        g_aes_sbox[i] |= ((inv & (1<<bi)?1:0)
44                                                ^ (inv & (1 << ((bi+4) & 7))?1:0)
45                                                ^ (inv & (1 << ((bi+5) & 7))?1:0) 
46                                                ^ (inv & (1 << ((bi+6) & 7))?1:0)
47                                                ^ (inv & (1 << ((bi+7) & 7))?1:0) 
48                                                ^ (AES_SBOX_CC & (1 << bi)?1:0)
49                        ) << bi;
50                }
51                g_aes_isbox[g_aes_sbox[i]] = i;
52        }
53        // warning: quickhack
54        g_aes_sbox[1] = 0x7c;
55        g_aes_isbox[0x7c] = 1;
56        g_aes_isbox[0x63] = 0;
57}
58
59aes_ctx_t *aes_alloc_ctx(unsigned char *key, unsigned long keyLen)
60{
61        aes_ctx_t *ctx;
62        size_t rounds;
63        size_t ks_size;
64
65        switch(keyLen) {
66                case 16: // 128-bit key
67                        rounds = 10;
68                        break;
69
70                case 24: // 192-bit key
71                        rounds = 12;
72                        break;
73
74                case 32: // 256-bit key
75                        rounds = 14;
76                        break;
77
78                defaut:
79                        return NULL;
80        }
81
82        ks_size = 4*(rounds+1)*sizeof(unsigned long);
83        ctx = malloc(sizeof(aes_ctx_t)+ks_size);
84        if(ctx) {
85                ctx->rounds = rounds;
86                ctx->kcol = keyLen/4;
87                memcpy(ctx->keysched, key, keyLen);
88                aes_keyexpansion(ctx);
89        }
90
91        return ctx;
92}
93
94inline unsigned long aes_subword(unsigned long w)
95{
96        return g_aes_sbox[w & 0x000000ff] |
97                (g_aes_sbox[(w & 0x0000ff00) >> 8] << 8) |
98                (g_aes_sbox[(w & 0x00ff0000) >> 16] << 16) |
99                (g_aes_sbox[(w & 0xff000000) >> 24] << 24);
100}
101
102inline unsigned long aes_rotword(unsigned long w)
103{
104        // May seem a bit different from the spec
105        // It was changed because unsigned long is represented with little-endian convention on x86
106        // Should not depend on architecture, but this is only a POC
107        return ((w & 0x000000ff) << 24) |
108                ((w & 0x0000ff00) >> 8) |
109                ((w & 0x00ff0000) >> 8) |
110                ((w & 0xff000000) >> 8);
111}
112
113void aes_keyexpansion(aes_ctx_t *ctx)
114{
115        unsigned long temp;
116        unsigned long rcon;
117        register int i;
118
119        rcon = 0x00000001;
120        for(i = ctx->kcol; i < (4*(ctx->rounds+1)); i++) {
121                temp = ctx->keysched[i-1];
122                if(!(i%ctx->kcol)) {
123                        temp = aes_subword(aes_rotword(temp)) ^ rcon;
124                        rcon = aes_mul(rcon, 2);
125                } else if(ctx->kcol > 6 && i%ctx->kcol == 4)
126                        temp = aes_subword(temp);
127                ctx->keysched[i] = ctx->keysched[i-ctx->kcol] ^ temp;
128        }
129}
130
131inline unsigned char aes_mul_manual(unsigned char a, unsigned char b)
132{
133        register unsigned short ac;
134        register unsigned char ret;
135
136        ac = a;
137        ret = 0;
138        while(b) {
139                if(b & 0x01)
140                        ret ^= ac;
141                ac <<= 1;
142                b >>= 1;
143                if(ac & 0x0100)
144                        ac ^= AES_RPOL;
145        }
146
147        return ret;
148}
149
150void aes_subbytes(aes_ctx_t *ctx)
151{
152        int i;
153
154        for(i = 0; i < 16; i++) {
155                int x, y;
156
157                x = i & 0x03;
158                y = i >> 2;
159                ctx->state[x][y] = g_aes_sbox[ctx->state[x][y]];
160        }
161}
162
163void aes_shiftrows(aes_ctx_t *ctx)
164{
165        unsigned char nstate[4][4];
166        int i;
167
168        for(i = 0; i < 16; i++) {
169                int x, y;
170
171                x = i & 0x03;
172                y = i >> 2;
173                nstate[x][y] = ctx->state[x][(y+x) & 0x03];
174        }
175
176        memcpy(ctx->state, nstate, sizeof(ctx->state));
177}
178
179void aes_mixcolumns(aes_ctx_t *ctx)
180{
181        unsigned char nstate[4][4];
182        int i;
183       
184        for(i = 0; i < 4; i++) {
185                nstate[0][i] = aes_mul(0x02, ctx->state[0][i]) ^ 
186                                aes_mul(0x03, ctx->state[1][i]) ^
187                                ctx->state[2][i] ^
188                                ctx->state[3][i];
189                nstate[1][i] = ctx->state[0][i] ^
190                                aes_mul(0x02, ctx->state[1][i]) ^
191                                aes_mul(0x03, ctx->state[2][i]) ^
192                                ctx->state[3][i];
193                nstate[2][i] = ctx->state[0][i] ^
194                                ctx->state[1][i] ^
195                                aes_mul(0x02, ctx->state[2][i]) ^
196                                aes_mul(0x03, ctx->state[3][i]);
197                nstate[3][i] = aes_mul(0x03, ctx->state[0][i]) ^
198                                ctx->state[1][i] ^
199                                ctx->state[2][i] ^
200                                aes_mul(0x02, ctx->state[3][i]);
201        }
202
203        memcpy(ctx->state, nstate, sizeof(ctx->state));
204}
205
206void aes_addroundkey(aes_ctx_t *ctx, int round)
207{
208        int i;
209
210        for(i = 0; i < 16; i++) {
211                int x, y;
212
213                x = i & 0x03;
214                y = i >> 2;
215                ctx->state[x][y] = ctx->state[x][y] ^
216                        ((ctx->keysched[round*4+y] & (0xff << (x*8))) >> (x*8));
217        }
218}
219
220void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])
221{
222        int i;
223
224        // copy input to state
225        for(i = 0; i < 16; i++)
226                ctx->state[i & 0x03][i >> 2] = input[i];
227
228        aes_addroundkey(ctx, 0);
229
230        for(i = 1; i < ctx->rounds; i++) {
231                aes_subbytes(ctx);
232                aes_shiftrows(ctx);
233                aes_mixcolumns(ctx);
234                aes_addroundkey(ctx, i);
235        }
236
237        aes_subbytes(ctx);
238        aes_shiftrows(ctx);
239        aes_addroundkey(ctx, ctx->rounds);
240
241        // copy state to output
242        for(i = 0; i < 16; i++)
243                output[i] = ctx->state[i & 0x03][i >> 2];
244}
245
246void aes_invshiftrows(aes_ctx_t *ctx)
247{
248        unsigned char nstate[4][4];
249        int i;
250
251        for(i = 0; i < 16; i++) {
252                int x, y;
253
254                x = i & 0x03;
255                y = i >> 2;
256                nstate[x][(y+x) & 0x03] = ctx->state[x][y];
257        }
258
259        memcpy(ctx->state, nstate, sizeof(ctx->state));
260}
261
262void aes_invsubbytes(aes_ctx_t *ctx)
263{
264        int i;
265
266        for(i = 0; i < 16; i++) {
267                int x, y;
268
269                x = i & 0x03;
270                y = i >> 2;
271                ctx->state[x][y] = g_aes_isbox[ctx->state[x][y]];
272        }
273}
274
275void aes_invmixcolumns(aes_ctx_t *ctx)
276{
277        unsigned char nstate[4][4];
278        int i;
279       
280        for(i = 0; i < 4; i++) {
281                nstate[0][i] = aes_mul(0x0e, ctx->state[0][i]) ^ 
282                                aes_mul(0x0b, ctx->state[1][i]) ^
283                                aes_mul(0x0d, ctx->state[2][i]) ^
284                                aes_mul(0x09, ctx->state[3][i]);
285                nstate[1][i] = aes_mul(0x09, ctx->state[0][i]) ^
286                                aes_mul(0x0e, ctx->state[1][i]) ^
287                                aes_mul(0x0b, ctx->state[2][i]) ^
288                                aes_mul(0x0d, ctx->state[3][i]);
289                nstate[2][i] = aes_mul(0x0d, ctx->state[0][i]) ^
290                                aes_mul(0x09, ctx->state[1][i]) ^
291                                aes_mul(0x0e, ctx->state[2][i]) ^
292                                aes_mul(0x0b, ctx->state[3][i]);
293                nstate[3][i] = aes_mul(0x0b, ctx->state[0][i]) ^
294                                aes_mul(0x0d, ctx->state[1][i]) ^
295                                aes_mul(0x09, ctx->state[2][i]) ^
296                                aes_mul(0x0e, ctx->state[3][i]);
297        }
298
299        memcpy(ctx->state, nstate, sizeof(ctx->state));
300}
301
302void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])
303{
304        int i, j;
305
306        // copy input to state
307        for(i = 0; i < 16; i++)
308                ctx->state[i & 0x03][i >> 2] = input[i];
309
310        aes_addroundkey(ctx, ctx->rounds);
311        for(i = ctx->rounds-1; i >= 1; i--) {
312                aes_invshiftrows(ctx);
313                aes_invsubbytes(ctx);
314                aes_addroundkey(ctx, i);
315                aes_invmixcolumns(ctx);
316        }
317
318        aes_invshiftrows(ctx);
319        aes_invsubbytes(ctx);
320        aes_addroundkey(ctx, 0);
321
322        // copy state to output
323        for(i = 0; i < 16; i++)
324                output[i] = ctx->state[i & 0x03][i >> 2];
325}
326
327void aes_free_ctx(aes_ctx_t *ctx)
328{
329        free(ctx);
330}
Note: See TracBrowser for help on using the repository browser.