]> git.saurik.com Git - apple/xnu.git/blob - bsd/crypto/aes/i386/MakeData.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / bsd / crypto / aes / i386 / MakeData.c
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #define MaxRcon 11
7
8 typedef uint8_t Byte;
9 typedef uint32_t Word;
10
11
12 /* In comments below, {n} designates the Galois field element represented by
13 the byte n. See notes about Galois field multiplication in ReadMe.txt.
14
15 So 3+5 is addition of ordinary integers, and 3+5 == 8, while {3}+{5} is
16 addition in the field, and {3} + {5} = {3 XOR 5} = {6}.)
17 */
18
19
20 // Define constants for languages.
21 typedef enum { C, IntelAssembly } Language;
22
23
24 /* LogBase3[i] will contain the base-three logarithm of i in the 256-element
25 Galois field defined by AES. That is, {3}**LogBase3[i] == {3}**i.
26 */
27 static Byte LogBase3[256];
28
29 /* AntilogBase3[i] will contain {3}**i in the 256-element Galois field defined
30 by AES. It contains extra elements so that the antilog of a+b can be found
31 by looking up a+b directly, without having to reduce modulo the period, for
32 0 <= a, b < 255.
33
34 (254 is the greatest value we encounter. Each a or b we use is the
35 base-three logarithm of some element. As a primitive root, the powers of
36 three cycle through all non-zero elements of the field, of which there are
37 255, so the exponents cover 0 to 254 before the powers repeat.)
38 */
39 static Byte AntilogBase3[254+254+1];
40
41
42 static void InitializeLogTables(void)
43 {
44 // log({1}) is zero, so start {p} (power) at {1} and l (logarithm) at 0.
45 Byte p = 1;
46 int l = 0;
47 do
48 {
49 // Record table entries.
50 LogBase3[p] = l;
51 AntilogBase3[l] = p;
52
53 /* Observe that {2}*{p} is {p << 1 ^ (a & 0x80 ? 0x1b : 0)}, per notes
54 in ReadMe.txt. We produce {3}*{p}:
55
56 {3}*{p}
57 = {1}*{p} + {2}*{p}
58 = {1}*{p} + {p << 1 ^ (a & 0x80 ? 0x1b : 0)}
59 = {p ^ p << 1 ^ (p & 0x80 ? 0x1b : 0)}.
60 */
61 p ^= p << 1 ^ (p & 0x80 ? 0x1b : 0);
62 ++l;
63
64 } while (p != 1); // Stop when we have gone around completely.
65
66 /* The antilogarithms are periodic with a period of 255, and we want to
67 look up elements as high as 254+254 (the largest that a sum of two
68 logarithms could be), so we replicate the table beyond the first
69 period.
70 */
71 for (l = 255; l < 254+254; ++l)
72 AntilogBase3[l] = AntilogBase3[l-255];
73 }
74
75
76 /* MultiplyByte(Byte b, Byte c) returns {b}*{c}. It requires tables that must
77 be initialized before this routine is used.
78 */
79 static Byte MultiplyByte(Byte b, Byte c)
80 {
81 // Calculate product by adding logarithms, but avoid logarithms of zero.
82 return b == 0 || c == 0 ? 0 : AntilogBase3[LogBase3[b] + LogBase3[c]];
83 }
84
85
86 // Return {0} if {b} is {0} and the multiplicative inverse of {b} otherwise.
87 static Byte InverseByte(Byte b)
88 {
89 return b == 0 ? 0 : AntilogBase3[255 - LogBase3[b]];
90 }
91
92
93 // Perform AES' SubBytes operation on a single byte.
94 static Byte SubByte(Byte b)
95 {
96 unsigned int r = InverseByte(b);
97
98 // Duplicate r as a proxy for a rotate operation.
99 r = r | r<<8;
100
101 // Apply the standard's affine transformation.
102 return r ^ r>>4 ^ r>>5 ^ r>>6 ^ r>>7 ^ 0x63;
103 }
104
105
106 // Define and populate tables for the SubBytes and InvSubBytes operations.
107 static Byte SubBytesTable[256];
108 static Byte InvSubBytesTable[256];
109
110
111 static void InitializeSubBytesTable(void)
112 {
113 for (int i = 0; i < 256; ++i)
114 SubBytesTable[i] = SubByte((Byte) i);
115 }
116
117
118 static void InitializeInvSubBytesTable(void)
119 {
120 for (int i = 0; i < 256; ++i)
121 InvSubBytesTable[SubByte((Byte) i)] = i;
122 }
123
124
125 /* Print tables for SubBytes function providing the output byte embedded in
126 various places in a word, so that the table entries can be used with
127 fewer byte manipulations.
128 */
129 static void PrintSubBytesWordTable(Language language)
130 {
131 switch (language)
132 {
133 case C:
134 printf("\n\n"
135 "// SubBytes embedded in words tables.\n"
136 "const Word AESSubBytesWordTable[4][256] =\n"
137 "{\n");
138 for (int j = 0; j < 4; ++j)
139 {
140 printf("\t{\n");
141 for (int i = 0; i < 256; ++i)
142 printf("\t\t0x%08x,\n", SubBytesTable[i] << j*8);
143 printf("\t},\n");
144 }
145 printf("};\n");
146 break;
147
148 case IntelAssembly:
149 printf("\n\n"
150 "// SubBytes embedded in words tables.\n"
151 "\t.globl\t_AESSubBytesWordTable\n"
152 "\t.private_extern\t_AESSubBytesWordTable\n"
153 "\t.align\t2\n"
154 "_AESSubBytesWordTable:\n");
155 for (int j = 0; j < 4; ++j)
156 {
157 printf("\t// Table %d.\n", j);
158 for (int i = 0; i < 256; ++i)
159 printf("\t.long\t0x%08x\n", SubBytesTable[i] << j*8);
160 }
161 break;
162 }
163 }
164
165
166 /* Print tables for InvSubBytes function providing the output byte embedded in
167 various places in a word, so that the table entries can be used with
168 fewer byte manipulations.
169 */
170 static void PrintInvSubBytesWordTable(Language language)
171 {
172 switch (language)
173 {
174 case C:
175 printf("\n\n"
176 "// InvSubBytes embedded in words tables.\n"
177 "const Word AESInvSubBytesWordTable[4][256] =\n"
178 "{\n");
179 for (int j = 0; j < 4; ++j)
180 {
181 printf("\t{\n");
182 for (int i = 0; i < 256; ++i)
183 printf("\t\t0x%08x,\n", InvSubBytesTable[i] << j*8);
184 printf("\t},\n");
185 }
186 printf("};\n");
187 break;
188
189 case IntelAssembly:
190 printf("\n\n"
191 "// InvSubBytes embedded in words tables.\n"
192 "\t.globl\t_AESInvSubBytesWordTable\n"
193 "\t.private_extern\t_AESInvSubBytesWordTable\n"
194 "\t.align\t2\n"
195 "_AESInvSubBytesWordTable:\n");
196 for (int j = 0; j < 4; ++j)
197 {
198 printf("\t// Table %d.\n", j);
199 for (int i = 0; i < 256; ++i)
200 printf("\t.long\t0x%08x\n", InvSubBytesTable[i] << j*8);
201 }
202 break;
203 }
204 }
205
206
207 // Print the round constants.
208 static void PrintRcon(Language language)
209 {
210 union { Byte c[4]; Word w; } t = { { 1, 0, 0, 0 } };
211
212 switch (language)
213 {
214 case C:
215 printf("\n\n"
216 "// Round constants.\n"
217 "const Byte AESRcon[] =\n"
218 "{\n"
219 "\t0,\t// Not used, included for indexing simplicity.\n");
220 for (int i = 1; i < MaxRcon; ++i)
221 {
222 printf("\t0x%02x,\n", t.w);
223 t.c[0] = MultiplyByte(0x2, t.c[0]);
224 }
225 printf("};\n");
226 break;
227
228 case IntelAssembly:
229 printf("\n\n"
230 "// Round constants.\n"
231 "\t.globl\t_AESRcon\n"
232 "\t.private_extern\t_AESRcon\n"
233 "_AESRcon:\n"
234 "\t.byte\t0\t// Not used, included for indexing simplicity.\n");
235 for (int i = 1; i < MaxRcon; ++i)
236 {
237 printf("\t.byte\t0x%02x\n", t.w);
238 t.c[0] = MultiplyByte(0x2, t.c[0]);
239 }
240 break;
241 }
242 }
243
244
245 // Print tables for the InvMixColumn operation.
246 static void PrintInvMixColumnTable(Language language)
247 {
248 Word T[4][256];
249
250 for (int i = 0; i < 256; ++i)
251 {
252 union { Byte b[4]; Word w; } c;
253
254 Byte s9 = MultiplyByte(0x9, i);
255 Byte sb = MultiplyByte(0xb, i);
256 Byte sd = MultiplyByte(0xd, i);
257 Byte se = MultiplyByte(0xe, i);
258
259 c.b[0] = se;
260 c.b[1] = s9;
261 c.b[2] = sd;
262 c.b[3] = sb;
263 T[0][i] = c.w;
264
265 c.b[0] = sb;
266 c.b[1] = se;
267 c.b[2] = s9;
268 c.b[3] = sd;
269 T[1][i] = c.w;
270
271 c.b[0] = sd;
272 c.b[1] = sb;
273 c.b[2] = se;
274 c.b[3] = s9;
275 T[2][i] = c.w;
276
277 c.b[0] = s9;
278 c.b[1] = sd;
279 c.b[2] = sb;
280 c.b[3] = se;
281 T[3][i] = c.w;
282 }
283
284 switch (language)
285 {
286 case C:
287 printf("\n\n"
288 "// Tables for InvMixColumn.\n"
289 "const Word AESInvMixColumnTable[4][256] =\n"
290 "{\n");
291 for (int i = 0; i < 4; ++i)
292 {
293 printf("\t{\n");
294 for (int j = 0; j < 256; ++j)
295 printf("\t\t0x%08x,\n", T[i][j]);
296 printf("\t},\n");
297 }
298 printf("};\n");
299 break;
300
301 case IntelAssembly:
302 printf("\n\n"
303 "// Tables for InvMixColumn.\n"
304 "\t.globl\t_AESInvMixColumnTable\n"
305 "\t.private_extern\t_AESInvMixColumnTable\n"
306 "\t.align\t2\n"
307 "_AESInvMixColumnTable:\n");
308 for (int i = 0; i < 4; ++i)
309 {
310 printf("\t// Table %d.\n", i);
311 for (int j = 0; j < 256; ++j)
312 printf("\t.long\t0x%08x\n", T[i][j]);
313 }
314 break;
315 }
316 }
317
318
319 /* Print the tables defined AES Proposal: Rijndael, amended, 9/04/2003,
320 section 5.2.1. These combine the MixColumn and SubBytes operations.
321 */
322 static void PrintEncryptTable(Language language)
323 {
324 Word T[4][256];
325
326 for (int i = 0; i < 256; ++i)
327 {
328 union { Byte b[4]; Word w; } c;
329
330 Byte s1 = SubBytesTable[i];
331 Byte s2 = MultiplyByte(0x2, s1);
332 Byte s3 = s1 ^ s2;
333
334 c.b[0] = s2;
335 c.b[1] = s1;
336 c.b[2] = s1;
337 c.b[3] = s3;
338 T[0][i] = c.w;
339
340 c.b[0] = s3;
341 c.b[1] = s2;
342 //c.b[2] = s1;
343 c.b[3] = s1;
344 T[1][i] = c.w;
345
346 c.b[0] = s1;
347 c.b[1] = s3;
348 c.b[2] = s2;
349 //c.b[3] = s1;
350 T[2][i] = c.w;
351
352 //c.b[0] = s1;
353 c.b[1] = s1;
354 c.b[2] = s3;
355 c.b[3] = s2;
356 T[3][i] = c.w;
357 }
358
359 switch (language)
360 {
361 case C:
362 printf("\n\n"
363 "// Tables for main encryption iterations.\n"
364 "const Word AESEncryptTable[4][256] =\n"
365 "{\n");
366 for (int i = 0; i < 4; ++i)
367 {
368 printf("\t{\n");
369 for (int j = 0; j < 256; ++j)
370 printf("\t\t0x%08x,\n", T[i][j]);
371 printf("\t},\n");
372 }
373 printf("};\n");
374 break;
375
376 case IntelAssembly:
377 printf("\n\n"
378 "// Tables for main encryption iterations.\n"
379 "\t.globl\t_AESEncryptTable\n"
380 "\t.private_extern\t_AESEncryptTable\n"
381 "\t.align\t2\n"
382 "_AESEncryptTable:\n");
383 for (int i = 0; i < 4; ++i)
384 {
385 printf("\t// Table %d.\n", i);
386 for (int j = 0; j < 256; ++j)
387 printf("\t.long\t0x%08x\n", T[i][j]);
388 }
389 break;
390 }
391 }
392
393
394 /* Print the inverse tables. These correspond to the tables above, but for
395 decyrption. These combine the InvSubBytes and InvMixColumn operations.
396 */
397 static void PrintDecryptTable(Language language)
398 {
399 Word T[4][256];
400
401 for (int i = 0; i < 256; ++i)
402 {
403 union { Byte b[4]; Word w; } c;
404
405 Byte si = InvSubBytesTable[i];
406
407 Byte s9 = MultiplyByte(0x9, si);
408 Byte sb = MultiplyByte(0xb, si);
409 Byte sd = MultiplyByte(0xd, si);
410 Byte se = MultiplyByte(0xe, si);
411
412 c.b[0] = se;
413 c.b[1] = s9;
414 c.b[2] = sd;
415 c.b[3] = sb;
416 T[0][i] = c.w;
417
418 c.b[0] = sb;
419 c.b[1] = se;
420 c.b[2] = s9;
421 c.b[3] = sd;
422 T[1][i] = c.w;
423
424 c.b[0] = sd;
425 c.b[1] = sb;
426 c.b[2] = se;
427 c.b[3] = s9;
428 T[2][i] = c.w;
429
430 c.b[0] = s9;
431 c.b[1] = sd;
432 c.b[2] = sb;
433 c.b[3] = se;
434 T[3][i] = c.w;
435 }
436
437 switch (language)
438 {
439 case C:
440 printf("\n\n"
441 "// Tables for main decryption iterations.\n"
442 "const Word AESDecryptTable[4][256] =\n"
443 "{\n");
444 for (int i = 0; i < 4; ++i)
445 {
446 printf("\t{\n");
447 for (int j = 0; j < 256; ++j)
448 printf("\t\t0x%08x,\n", T[i][j]);
449 printf("\t},\n");
450 }
451 printf("};\n");
452 break;
453
454 case IntelAssembly:
455 printf("\n\n"
456 "// Tables for main decryption iterations.\n"
457 "\t.globl\t_AESDecryptTable\n"
458 "\t.private_extern\t_AESDecryptTable\n"
459 "\t.align\t2\n"
460 "_AESDecryptTable:\n");
461 for (int i = 0; i < 4; ++i)
462 {
463 printf("\t// Table %d.\n", i);
464 for (int j = 0; j < 256; ++j)
465 printf("\t.long\t0x%08x\n", T[i][j]);
466 }
467 break;
468 }
469 }
470
471
472 static void Usage(const char *ProgramName)
473 {
474 fprintf(stderr,
475 "%s: This program must have exactly one argument, \"C\" to generate\n"
476 "C or \"Intel\" to generate GCC i386/x86_64 assembly.\n", ProgramName);
477 exit(EXIT_FAILURE);
478 }
479
480
481 int main(int argc, char *argv[])
482 {
483 if (argc != 2)
484 Usage(argv[0]);
485
486 Language language;
487
488 // Figure out which language to generate, C or Intel assembly.
489 if (0 == strcmp(argv[1], "C"))
490 language = C;
491 else if (0 == strcmp(argv[1], "Intel"))
492 language = IntelAssembly;
493 else
494 Usage(argv[0]);
495
496 printf("// This file was generated by " __FILE__ ".\n");
497
498 if (language == C)
499 printf("\n\n#include \"AES.h\"\n");
500
501 if (language == IntelAssembly)
502 printf("\n\n\t.const\n");
503
504 InitializeLogTables();
505 InitializeSubBytesTable();
506 InitializeInvSubBytesTable();
507
508 PrintRcon(language);
509 PrintInvMixColumnTable(language);
510 PrintEncryptTable(language);
511 PrintDecryptTable(language);
512 PrintSubBytesWordTable(language);
513 PrintInvSubBytesWordTable(language);
514
515 return 0;
516 }