#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define UseAESedp // Tell AES.h to define things for AESedp.
#include "AES.h"
typedef enum { C, IntelAssembly } Language;
static Byte LogBase3[256];
static Byte AntilogBase3[254+254+1];
static void InitializeLogTables(void)
{
Byte p = 1;
int l = 0;
do
{
LogBase3[p] = l;
AntilogBase3[l] = p;
p ^= p << 1 ^ (p & 0x80 ? 0x1b : 0);
++l;
} while (p != 1);
for (l = 255; l < 254+254; ++l)
AntilogBase3[l] = AntilogBase3[l-255];
}
static Byte MultiplyByte(Byte b, Byte c)
{
return b == 0 || c == 0 ? 0 : AntilogBase3[LogBase3[b] + LogBase3[c]];
}
static Byte InverseByte(Byte b)
{
return b == 0 ? 0 : AntilogBase3[255 - LogBase3[b]];
}
static Byte SubByte(Byte b)
{
unsigned int r = InverseByte(b);
r = r | r<<8;
return r ^ r>>4 ^ r>>5 ^ r>>6 ^ r>>7 ^ 0x63;
}
static Byte SubBytesTable[256];
static Byte InvSubBytesTable[256];
static void InitializeSubBytesTable(void)
{
for (int i = 0; i < 256; ++i)
SubBytesTable[i] = SubByte((Byte) i);
}
static void InitializeInvSubBytesTable(void)
{
for (int i = 0; i < 256; ++i)
InvSubBytesTable[SubByte((Byte) i)] = i;
}
static void PrintSubBytesWordTable(Language language)
{
switch (language)
{
case C:
printf("\n\n"
"// SubBytes embedded in words tables.\n"
"const Word AESSubBytesWordTable[4][256] =\n"
"{\n");
for (int j = 0; j < 4; ++j)
{
printf("\t{\n");
for (int i = 0; i < 256; ++i)
printf("\t\t0x%08x,\n", SubBytesTable[i] << j*8);
printf("\t},\n");
}
printf("};\n");
break;
case IntelAssembly:
printf("\n\n"
"// SubBytes embedded in words tables.\n"
"\t.globl\t_AESSubBytesWordTable\n"
"\t.private_extern\t_AESSubBytesWordTable\n"
"\t.align\t2\n"
"_AESSubBytesWordTable:\n");
for (int j = 0; j < 4; ++j)
{
printf("\t// Table %d.\n", j);
for (int i = 0; i < 256; ++i)
printf("\t.long\t0x%08x\n", SubBytesTable[i] << j*8);
}
break;
}
}
static void PrintInvSubBytesWordTable(Language language)
{
switch (language)
{
case C:
printf("\n\n"
"// InvSubBytes embedded in words tables.\n"
"const Word AESInvSubBytesWordTable[4][256] =\n"
"{\n");
for (int j = 0; j < 4; ++j)
{
printf("\t{\n");
for (int i = 0; i < 256; ++i)
printf("\t\t0x%08x,\n", InvSubBytesTable[i] << j*8);
printf("\t},\n");
}
printf("};\n");
break;
case IntelAssembly:
printf("\n\n"
"// InvSubBytes embedded in words tables.\n"
"\t.globl\t_AESInvSubBytesWordTable\n"
"\t.private_extern\t_AESInvSubBytesWordTable\n"
"\t.align\t2\n"
"_AESInvSubBytesWordTable:\n");
for (int j = 0; j < 4; ++j)
{
printf("\t// Table %d.\n", j);
for (int i = 0; i < 256; ++i)
printf("\t.long\t0x%08x\n", InvSubBytesTable[i] << j*8);
}
break;
}
}
static void PrintRcon(Language language)
{
union { Byte c[4]; Word w; } t = { { 1, 0, 0, 0 } };
switch (language)
{
case C:
printf("\n\n"
"// Round constants.\n"
"const Byte AESRcon[] =\n"
"{\n"
"\t0,\t// Not used, included for indexing simplicity.\n");
for (int i = 1; i < MaxRcon; ++i)
{
printf("\t0x%02x,\n", t.w);
t.c[0] = MultiplyByte(0x2, t.c[0]);
}
printf("};\n");
break;
case IntelAssembly:
printf("\n\n"
"// Round constants.\n"
"\t.globl\t_AESRcon\n"
"\t.private_extern\t_AESRcon\n"
"_AESRcon:\n"
"\t.byte\t0\t// Not used, included for indexing simplicity.\n");
for (int i = 1; i < MaxRcon; ++i)
{
printf("\t.byte\t0x%02x\n", t.w);
t.c[0] = MultiplyByte(0x2, t.c[0]);
}
break;
}
}
static void PrintInvMixColumnTable(Language language)
{
Word T[4][256];
for (int i = 0; i < 256; ++i)
{
union { Byte b[4]; Word w; } c;
Byte s9 = MultiplyByte(0x9, i);
Byte sb = MultiplyByte(0xb, i);
Byte sd = MultiplyByte(0xd, i);
Byte se = MultiplyByte(0xe, i);
c.b[0] = se;
c.b[1] = s9;
c.b[2] = sd;
c.b[3] = sb;
T[0][i] = c.w;
c.b[0] = sb;
c.b[1] = se;
c.b[2] = s9;
c.b[3] = sd;
T[1][i] = c.w;
c.b[0] = sd;
c.b[1] = sb;
c.b[2] = se;
c.b[3] = s9;
T[2][i] = c.w;
c.b[0] = s9;
c.b[1] = sd;
c.b[2] = sb;
c.b[3] = se;
T[3][i] = c.w;
}
switch (language)
{
case C:
printf("\n\n"
"// Tables for InvMixColumn.\n"
"const Word AESInvMixColumnTable[4][256] =\n"
"{\n");
for (int i = 0; i < 4; ++i)
{
printf("\t{\n");
for (int j = 0; j < 256; ++j)
printf("\t\t0x%08x,\n", T[i][j]);
printf("\t},\n");
}
printf("};\n");
break;
case IntelAssembly:
printf("\n\n"
"// Tables for InvMixColumn.\n"
"\t.globl\t_AESInvMixColumnTable\n"
"\t.private_extern\t_AESInvMixColumnTable\n"
"\t.align\t2\n"
"_AESInvMixColumnTable:\n");
for (int i = 0; i < 4; ++i)
{
printf("\t// Table %d.\n", i);
for (int j = 0; j < 256; ++j)
printf("\t.long\t0x%08x\n", T[i][j]);
}
break;
}
}
static void PrintEncryptTable(Language language)
{
Word T[4][256];
for (int i = 0; i < 256; ++i)
{
union { Byte b[4]; Word w; } c;
Byte s1 = SubBytesTable[i];
Byte s2 = MultiplyByte(0x2, s1);
Byte s3 = s1 ^ s2;
c.b[0] = s2;
c.b[1] = s1;
c.b[2] = s1;
c.b[3] = s3;
T[0][i] = c.w;
c.b[0] = s3;
c.b[1] = s2;
c.b[3] = s1;
T[1][i] = c.w;
c.b[0] = s1;
c.b[1] = s3;
c.b[2] = s2;
T[2][i] = c.w;
c.b[1] = s1;
c.b[2] = s3;
c.b[3] = s2;
T[3][i] = c.w;
}
switch (language)
{
case C:
printf("\n\n"
"// Tables for main encryption iterations.\n"
"const Word AESEncryptTable[4][256] =\n"
"{\n");
for (int i = 0; i < 4; ++i)
{
printf("\t{\n");
for (int j = 0; j < 256; ++j)
printf("\t\t0x%08x,\n", T[i][j]);
printf("\t},\n");
}
printf("};\n");
break;
case IntelAssembly:
printf("\n\n"
"// Tables for main encryption iterations.\n"
"\t.globl\t_AESEncryptTable\n"
"\t.private_extern\t_AESEncryptTable\n"
"\t.align\t2\n"
"_AESEncryptTable:\n");
for (int i = 0; i < 4; ++i)
{
printf("\t// Table %d.\n", i);
for (int j = 0; j < 256; ++j)
printf("\t.long\t0x%08x\n", T[i][j]);
}
break;
}
}
static void PrintDecryptTable(Language language)
{
Word T[4][256];
for (int i = 0; i < 256; ++i)
{
union { Byte b[4]; Word w; } c;
Byte si = InvSubBytesTable[i];
Byte s9 = MultiplyByte(0x9, si);
Byte sb = MultiplyByte(0xb, si);
Byte sd = MultiplyByte(0xd, si);
Byte se = MultiplyByte(0xe, si);
c.b[0] = se;
c.b[1] = s9;
c.b[2] = sd;
c.b[3] = sb;
T[0][i] = c.w;
c.b[0] = sb;
c.b[1] = se;
c.b[2] = s9;
c.b[3] = sd;
T[1][i] = c.w;
c.b[0] = sd;
c.b[1] = sb;
c.b[2] = se;
c.b[3] = s9;
T[2][i] = c.w;
c.b[0] = s9;
c.b[1] = sd;
c.b[2] = sb;
c.b[3] = se;
T[3][i] = c.w;
}
switch (language)
{
case C:
printf("\n\n"
"// Tables for main decryption iterations.\n"
"const Word AESDecryptTable[4][256] =\n"
"{\n");
for (int i = 0; i < 4; ++i)
{
printf("\t{\n");
for (int j = 0; j < 256; ++j)
printf("\t\t0x%08x,\n", T[i][j]);
printf("\t},\n");
}
printf("};\n");
break;
case IntelAssembly:
printf("\n\n"
"// Tables for main decryption iterations.\n"
"\t.globl\t_AESDecryptTable\n"
"\t.private_extern\t_AESDecryptTable\n"
"\t.align\t2\n"
"_AESDecryptTable:\n");
for (int i = 0; i < 4; ++i)
{
printf("\t// Table %d.\n", i);
for (int j = 0; j < 256; ++j)
printf("\t.long\t0x%08x\n", T[i][j]);
}
break;
}
}
static void Usage(const char *ProgramName)
{
fprintf(stderr,
"%s: This program must have exactly one argument, \"C\" to generate\n"
"C or \"Intel\" to generate GCC i386/x86_64 assembly.\n", ProgramName);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
if (argc != 2)
Usage(argv[0]);
Language language;
if (0 == strcmp(argv[1], "C"))
language = C;
else if (0 == strcmp(argv[1], "Intel"))
language = IntelAssembly;
else
Usage(argv[0]);
printf("// This file was generated by " __FILE__ ".\n");
if (language == C)
printf("\n\n#include \"AES.h\"\n");
if (language == IntelAssembly)
printf("\n\n\t.const\n");
InitializeLogTables();
InitializeSubBytesTable();
InitializeInvSubBytesTable();
PrintRcon(language);
PrintInvMixColumnTable(language);
PrintEncryptTable(language);
PrintDecryptTable(language);
PrintSubBytesWordTable(language);
PrintInvSubBytesWordTable(language);
return 0;
}