program t_mkctab;

(*************************************************************************

 DESCRIPTION     :  Calculate compressed AES tables

 REQUIREMENTS    :  TP5-7, D1-D7/D9-D10, FPC, VP, WDOSX

 EXTERNAL DATA   :  ---

 MEMORY USAGE    :  ---

 DISPLAY MODE    :  ---

 REFERENCES      :  [1] http://csrc.nist.gov/fips/fips-197.pdf


 Version  Date      Author      Modification
 -------  --------  -------     ------------------------------------------
 0.10     08.07.06  we          Initial version using existing static tables
 0.11     12.07.06  we          Use (Inv)SBox bytes instead of zero fill bytes
 0.12     13.07.06  we          Without static tables
**************************************************************************)

{$i STD.INC}

{$ifdef APPCONS}
  {$apptype console}
{$endif}

uses
  {$ifdef WINCRT}
    wincrt,
  {$endif}
  mem_util;



{---------------------------------------------------------------------------}
{Encrypt}
{  3  2  1  0}
{ a5 63 63 c6}
{ xx xx xx c6 63 63 a5 xx
  xx xx a5 c6 63 63 xx xx
  xx 63 a5 c6 63 xx xx xx
  63 63 a5 c6 xx xx xx xx}

{If (b0,b1,b2,b3) are the bytes of an Te0 longint the}
{TCe entry has the 8 bytes (b1,b2,b3,b0,b1,b2,b3,SBox)  }

{---------------------------------------------------------------------------}
{Decrypt}
{  3  2  1  0}
{ 50 a7 f4 51}

{ xx xx xx 51 f4 a7 50 xx
  xx xx 50 51 f4 a7 xx xx
  xx a7 50 51 f4 xx xx xx
  f4 a7 50 51 xx xx xx xx}

{If (b0,b1,b2,b3) are the bytes of an Td0 longint the}
{TCd entry has the 8 bytes (b1,b2,b3,b0,b1,b2,b3,InvSBox)  }


{---------------------------------------------------------------------------}
{types to access table: Tex[i] = TCe[i].Ex.L, Tdx[i] = TCd[i].Ex.L}
(*
type
  TH0 = packed record             TH1 = packed record
          b0,b1,b2: byte;                 b0,b1: byte;
          L: longint;                     L: longint;
          box: byte;                      b2,box: byte;
        end;                            end;

  TH2 = packed record             TH3 = packed record
          b0: byte;                       L: longint;
          L: longint;                     b0,b1,b2,box: byte;
          b1,b2,box: byte;              end;
        end;

  THU = record                    TDU = record
          case integer of                 case integer of
            0: (E0: TH0);                   0: (D0: TH0);
            1: (E1: TH1);                   1: (D1: TH1);
            2: (E2: TH2);                   2: (D2: TH2);
            3: (E3: TH3);                   3: (D3: TH3);
        end;                            end;
*)


var
  GLog, GPow: array[byte] of byte;


{---------------------------------------------------------------------------}
procedure CalcBaseTables;
  {-Calculate dynamic tables: power, log}
var
  i, p: byte;
begin
  {Power/Log tables}
  p := 1;
  for i:=0 to 254 do begin
    GPow[i] := p;
    GLog[p] := i;
    if p and $80 = 0 then p := (p shl 1) xor p
    else p := (p shl 1) xor p xor $1B;
  end;
  GPow[255] := 1;
end;


{---------------------------------------------------------------------------}
function GMul(x,y: byte): byte;
  {-calculate x*y in GF(2^8)}
var
  i: word;
begin
  if (x=0) or (y=0) then GMul := 0
  else begin
    i := word(GLog[x])+word(GLog[y]);
    if i>=255 then dec(i,255);
    GMul := GPow[i];
  end;
end;


{---------------------------------------------------------------------------}
function rot(b,n: byte): byte;
  {-rotate byte right n bits}
begin
  rot := (b shr n) xor (b shl (8-n));
end;


{---------------------------------------------------------------------------}
procedure MakeCompressedTables;
  {-Calculate and dump compressed AES tables}
var
  i,j: integer;
  p: byte;
  b: array[0..3] of byte;
  s: array[0..4] of string[4];
  InvSBox: array[byte] of byte;
begin
  CalcBaseTables;
  writeln('const');
  writeln('  TCe: packed array[0..2047] of byte = (');
  for i:=0 to 255 do begin
    {SBox calculation, cf. [1] 5.1.1}
    if i=0 then p:=0 else p:=GPow[255-GLog[i]];  {p*i = 1}
    p := p xor rot(p,4) xor rot(p,5) xor rot(p,6) xor rot(p,7) xor $63;
    InvSBox[p] := i;
    b[0] := GMul(2,p);
    b[1] := p;
    b[2] := p;
    b[3] := GMul(3,p);
    for j:=0 to 3 do s[j] := '$'+HexByte(b[j])+',';
    s[4] := '$'+HexByte(p);
    if odd(i) then begin
      write(s[1],s[2],s[3],s[0],s[1],s[2],s[3],s[4]);
      if i=255 then writeln(');') else writeln(',');
    end
    else write('':9,s[1],s[2],s[3],s[0],s[1],s[2],s[3],s[4],',');
  end;
  writeln;
  writeln('const');
  writeln('  TCd: packed array[0..2047] of byte = (');
  for i:=0 to 255 do begin
    p    := InvSbox[i];
    b[0] := GMul(14,p);
    b[1] := GMul( 9,p);
    b[2] := GMul(13,p);
    b[3] := GMul(11,p);
    for j:=0 to 3 do s[j] := '$'+HexByte(b[j])+',';
    s[4] := '$'+HexByte(p);
    if odd(i) then begin
      write(s[1],s[2],s[3],s[0],s[1],s[2],s[3],s[4]);
      if i=255 then writeln(');') else writeln(',');
    end
    else write('':9,s[1],s[2],s[3],s[0],s[1],s[2],s[3],s[4],',');
  end;
end;

begin
  MakeCompressedTables;
end.
