home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / nastroje / WP.ZIP / twofish.pas < prev    next >
Pascal/Delphi Source File  |  1999-05-15  |  23KB  |  645 lines

  1. {
  2. ***************************************************
  3. * A binary compatible Twofish implementation      *
  4. * written by Dave Barton (davebarton@bigfoot.com) *
  5. * partially based on C source by                  *
  6. * Markus Hahn (hahn@flix.de)                      *
  7. ***************************************************
  8. * 128bit block encryption                         *
  9. * Variable size key - up to 256bit                *
  10. ***************************************************
  11. }
  12. unit Twofish;
  13.  
  14. interface
  15. uses
  16.   Sysutils, Tools;
  17.  
  18. const
  19.   BLU: array[0..3] of DWord= (0, 8, 16, 24);
  20.   TWOFISH_BLOCKSIZE= 16;
  21.   INPUTWHITEN= 0;
  22.   OUTPUTWHITEN= (TWOFISH_BLOCKSIZE div 4);
  23.   NUMROUNDS= 16;
  24.   ROUNDSUBKEYS= (OUTPUTWHITEN + TWOFISH_BLOCKSIZE div 4);
  25.   TOTALSUBKEYS= (ROUNDSUBKEYS + NUMROUNDS * 2);
  26.   RS_GF_FDBK= $14d;
  27.   SK_STEP= $02020202;
  28.   SK_BUMP= $01010101;
  29.   SK_ROTL= 9;
  30.   P_00=           1;
  31.   P_01=           0;
  32.   P_02=           0;
  33.   P_03=           (P_01 xor 1);
  34.   P_04=           1;
  35.   P_10=           0;
  36.   P_11=           0;
  37.   P_12=           1;
  38.   P_13=           (P_11 xor 1);
  39.   P_14=           0;
  40.   P_20=           1;
  41.   P_21=           1;
  42.   P_22=           0;
  43.   P_23=           (P_21 xor 1);
  44.   P_24=           0;
  45.   P_30=           0;
  46.   P_31=           1;
  47.   P_32=           1;
  48.   P_33=           (P_31 xor 1);
  49.   P_34=           1;
  50.   MDS_GF_FDBK= $169;
  51.  
  52. type
  53.   TTwofishData= record
  54.     KeyLen: DWord;
  55.     SubKeys: array[0..TOTALSUBKEYS-1] of DWord;
  56.     sboxKeys: array[0..3] of DWord;
  57.     sbox: array[0..3,0..255] of DWord;
  58.     InitBlock: array[0..15] of byte;    { initial IV }
  59.     LastBlock: array[0..15] of byte;    { current IV }
  60.   end;
  61.  
  62. function TwofishSelfTest: boolean;
  63.   { performs a self test on this implementation }
  64. procedure TwofishInit(var Data: TTwofishData; Key: pointer; Len: integer; IV: pointer);
  65.   { initializes the TTwofishData structure with the key information and IV if applicable }
  66. procedure TwofishBurn(var Data: TTwofishData);
  67.   { erases all information about the key }
  68.  
  69. procedure TwofishEncryptECB(var Data: TTwofishData; InData, OutData: pointer);
  70.   { encrypts the data in a 128bit block using the ECB mode }
  71. procedure TwofishEncryptCBC(var Data: TTwofishData; InData, OutData: pointer);
  72.   { encrypts the data in a 128bit block using the CBC chaining mode }
  73. procedure TwofishEncryptOFB(var Data: TTwofishData; InData, OutData: pointer);
  74.   { encrypts the data in a 128bit block using the OFB chaining mode }
  75. procedure TwofishEncryptCFB(var Data: TTwofishData; InData, OutData: pointer; Len: integer);
  76.   { encrypts Len bytes of data using the CFB chaining mode }
  77. procedure TwofishEncryptOFBC(var Data: TTwofishData; InData, OutData: pointer; Len: integer);
  78.   { encrypts Len bytes of data using the OFB counter chaining mode }
  79.  
  80. procedure TwofishDecryptECB(var Data: TTwofishData; InData, OutData: pointer);
  81.   { decrypts the data in a 128bit block using the ECB mode }
  82. procedure TwofishDecryptCBC(var Data: TTwofishData; InData, OutData: pointer);
  83.   { decrypts the data in a 128bit block using the CBC chaining mode }
  84. procedure TwofishDecryptOFB(var Data: TTwofishData; InData, OutData: pointer);
  85.   { decrypts the data in a 128bit block using the OFB chaining mode }
  86. procedure TwofishDecryptCFB(var Data: TTwofishData; InData, OutData: pointer; Len: integer);
  87.   { decrypts Len bytes of data using the CFB chaining mode }
  88. procedure TwofishDecryptOFBC(var Data: TTwofishData; InData, OutData: pointer; Len: integer);
  89.   { decrypts Len bytes of data using the OFB counter chaining mode }
  90.  
  91. procedure TwofishReset(var Data: TTwofishData);
  92.   { resets the chaining mode information }
  93.  
  94. {******************************************************************************}
  95. implementation
  96. {$R-}
  97.  
  98. {$I Twofish.inc}
  99.  
  100. type
  101.   PDWord= ^DWord;
  102.   PDWordArray= ^TDWordArray;
  103.   TDWordArray= array[0..1023] of DWord;
  104.  
  105. var
  106.   MDS: array[0..3,0..255] of DWord;
  107.  
  108. function LFSR1(x: DWord): DWord;
  109. begin
  110.   if (x and 1)<> 0 then
  111.     Result:= (x shr 1) xor (MDS_GF_FDBK div 2)
  112.   else
  113.     Result:= (x shr 1);
  114. end;
  115. function LFSR2(x: DWord): DWord;
  116. begin
  117.   if (x and 2)<> 0 then
  118.     if (x and 1)<> 0 then
  119.       Result:= (x shr 2) xor (MDS_GF_FDBK div 2) xor (MDS_GF_FDBK div 4)
  120.     else
  121.       Result:= (x shr 2) xor (MDS_GF_FDBK div 2)
  122.   else
  123.     if (x and 1)<> 0 then
  124.       Result:= (x shr 2) xor (MDS_GF_FDBK div 4)
  125.     else
  126.       Result:= (x shr 2);
  127. end;
  128. function Mx_1(x: DWord): DWord;
  129. begin
  130.   Result:= x;
  131. end;
  132. function Mx_X(x: DWord): DWord;
  133. begin
  134.   Result:= x xor LFSR2(x);
  135. end;
  136. function Mx_Y(x: DWord): DWord;
  137. begin
  138.   Result:= x xor LFSR1(x) xor LFSR2(x);
  139. end;
  140.  
  141. const
  142.   Mul_1: function(x: DWord): DWord = Mx_1;
  143.   Mul_X: function(x: DWord): DWord = Mx_X;
  144.   Mul_Y: function(x: DWord): DWord = Mx_Y;
  145.  
  146. procedure PreCompMDS;
  147. var
  148.   m1, mx, my: array[0..1] of byte;
  149.   nI: integer;
  150. begin
  151.   for nI:= 0 to 255 do
  152.   begin
  153.     m1[0]:= p8x8[0,nI];
  154.     mx[0]:= Mul_X(m1[0]);
  155.     my[0]:= Mul_Y(m1[0]);
  156.     m1[1]:= p8x8[1,nI];
  157.     mx[1]:= Mul_X(m1[1]);
  158.     my[1]:= Mul_Y(m1[1]);
  159.     mds[0,nI]:= (m1[P_00] shl 0) or
  160.                 (mx[p_00] shl 8) or
  161.                 (my[p_00] shl 16) or
  162.                 (my[p_00] shl 24);
  163.     mds[1,nI]:= (my[p_10] shl 0) or
  164.                 (my[p_10] shl 8) or
  165.                 (mx[p_10] shl 16) or
  166.                 (m1[p_10] shl 24);
  167.     mds[2,nI]:= (mx[p_20] shl 0) or
  168.                 (my[p_20] shl 8) or
  169.                 (m1[p_20] shl 16) or
  170.                 (my[p_20] shl 24);
  171.     mds[3,nI]:= (mx[p_30] shl 0) or
  172.                 (m1[p_30] shl 8) or
  173.                 (my[p_30] shl 16) or
  174.                 (mx[p_30] shl 24);
  175.   end;
  176. end;
  177.  
  178. function RS_MDS_Encode(lK0, lK1: DWord): DWord;
  179. var
  180.   lR, nI, nJ, lG2, lG3: DWord;
  181.   bB: byte;
  182. begin
  183.   lR:= 0;
  184.   for nI:= 0 to 1 do
  185.   begin
  186.     if nI<> 0  then
  187.       lR:= lR xor lK0
  188.     else
  189.       lR:= lR xor lK1;
  190.     for nJ:= 0 to 3 do
  191.     begin
  192.       bB:= lR shr 24;
  193.       if (bB and $80)<> 0 then
  194.         lG2:= ((bB shl 1) xor RS_GF_FDBK) and $FF
  195.       else
  196.         lG2:= (bB shl 1) and $FF;
  197.       if (bB and 1)<> 0 then
  198.         lG3:= ((bB shr 1) and $7f) xor (RS_GF_FDBK shr 1) xor lG2
  199.       else
  200.         lG3:= ((bB shr 1) and $7f) xor lG2;
  201.       lR:= (lR shl 8) xor (lG3 shl 24) xor (lG2 shl 16) xor (lG3 shl 8) xor bB;
  202.     end;
  203.   end;
  204.   Result:= lR;
  205. end;
  206.  
  207. function f32(x: DWord; K32: PDWordArray; Len: DWord): DWord;
  208. var
  209.   t0, t1, t2, t3: DWord;
  210. begin
  211.   t0:= x and $FF;
  212.   t1:= (x shr 8) and $FF;
  213.   t2:= (x shr 16) and $FF;
  214.   t3:= x shr 24;
  215.   if Len= 256 then
  216.   begin
  217.     t0:= p8x8[p_04,t0] xor ((K32[3]) and $FF);
  218.     t1:= p8x8[p_14,t1] xor ((K32[3] shr  8) and $FF);
  219.     t2:= p8x8[p_24,t2] xor ((K32[3] shr 16) and $FF);
  220.     t3:= p8x8[p_34,t3] xor ((K32[3] shr 24));
  221.   end;
  222.   if Len>= 192 then
  223.   begin
  224.     t0:= p8x8[p_03,t0] xor ((K32[2]) and $FF);
  225.     t1:= p8x8[p_13,t1] xor ((K32[2] shr  8) and $FF);
  226.     t2:= p8x8[p_23,t2] xor ((K32[2] shr 16) and $FF);
  227.     t3:= p8x8[p_33,t3] xor ((K32[2] shr 24));
  228.   end;
  229.   Result:= MDS[0,p8x8[p_01,p8x8[p_02,t0] xor ((K32[1]) and $FF)] xor ((K32[0]) and $FF)] xor
  230.            MDS[1,p8x8[p_11,p8x8[p_12,t1] xor ((K32[1] shr  8) and $FF)] xor ((K32[0] shr  8) and $FF)] xor
  231.            MDS[2,p8x8[p_21,p8x8[p_22,t2] xor ((K32[1] shr 16) and $FF)] xor ((K32[0] shr 16) and $FF)] xor
  232.            MDS[3,p8x8[p_31,p8x8[p_32,t3] xor ((K32[1] shr 24))] xor ((K32[0] shr 24))];
  233. end;
  234.  
  235. function TwofishSelfTest;
  236. const
  237.   Key: array[0..31] of byte= ($01,$23,$45,$67,$89,$AB,$CD,$EF,$FE,$DC,$BA,$98,$76,$54,$32,$10,$00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$AA,$BB,$CC,$DD,$EE,$FF);
  238.   InBlock: array[0..15] of byte= ($0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0);
  239.   OutBlock: array[0..15] of byte= ($37,$52,$7B,$E0,$05,$23,$34,$B8,$9F,$0C,$FC,$CA,$E8,$7C,$FA,$20);
  240. var
  241.   Block: array[0..15] of byte;
  242.   Data: TTwofishData;
  243. begin
  244.   TwofishInit(Data,@Key,Sizeof(Key),nil);
  245.   TwofishEncryptECB(Data,@InBlock,@Block);
  246.   Result:= CompareMem(@Block,@OutBlock,Sizeof(Block));
  247.   TwofishDecryptECB(Data,@Block,@Block);
  248.   Result:= Result and CompareMem(@Block,@InBlock,Sizeof(Block));
  249.   TwofishBurn(Data);
  250. end;
  251.  
  252. procedure TwofishInit;
  253.   procedure Xor256(Dst, Src: PDWordArray; v: byte);
  254.   var
  255.     i: DWord;
  256.   begin
  257.     for i:= 0 to 63 do
  258.       Dst[i]:= Src[i] xor (v * $01010101);
  259.   end;
  260. var
  261.   key32: array[0..7] of DWord;
  262.   k32e, k32o: array[0..3] of DWord;
  263.   k64Cnt, i, j, A, B, q, subkeyCnt: DWord;
  264.   L0, L1: array[0..255] of byte;
  265. begin
  266.   if (Len<= 0) or (Len> 32) then
  267.     raise Exception.Create('Key length must be between 1 and 32 bytes');
  268.   with Data do
  269.   begin
  270.     if IV= nil then
  271.     begin
  272.       FillChar(InitBlock,16,0);
  273.       FillChar(LastBlock,16,0);
  274.     end
  275.     else
  276.     begin
  277.       Move(IV^,InitBlock,16);
  278.       Move(IV^,LastBlock,16);
  279.     end;
  280.     FillChar(Key32,Sizeof(Key32),0);
  281.     Move(Key^,Key32,Len);
  282.     if Len<= 16 then           // pad the key to either 128bit, 192bit or 256bit
  283.       Len:= 128
  284.     else if Len<= 24 then
  285.       Len:= 192
  286.     else
  287.       Len:= 256;
  288.     subkeyCnt:= ROUNDSUBKEYS + 2*NUMROUNDS;
  289.     KeyLen:= Len;
  290.     k64Cnt:= Len div 64;
  291.     j:= k64Cnt-1;
  292.     for i:= 0 to j do
  293.     begin
  294.       k32e[i]:= key32[2*i];
  295.       k32o[i]:= key32[2*i+1];
  296.       sboxKeys[j]:= RS_MDS_Encode(k32e[i],k32o[i]);
  297.       Dec(j);
  298.     end;
  299.     q:= 0;
  300.     for i:= 0 to ((subkeyCnt div 2)-1) do
  301.     begin
  302.       A:= f32(q,@k32e,len);
  303.       B:= f32(q+SK_BUMP,@k32o,len);
  304.       B:= LRot32(B,8);
  305.       SubKeys[2*i]:= A+B;
  306.       B:= A + 2*B;
  307.       SubKeys[2*i+1]:= LRot32(B,SK_ROTL);
  308.       Inc(q,SK_STEP);
  309.     end;
  310.     case Len of
  311.       128: begin
  312.              Xor256(@L0,@p8x8[p_02],(sboxKeys[1] and $FF));
  313.              A:= (sboxKeys[0] and $FF);
  314.              i:= 0;
  315.              while i< 256 do
  316.              begin
  317.                sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[p_01,L0[i]] xor A];
  318.                sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[p_01,L0[i+1]] xor A];
  319.                Inc(i,2);
  320.              end;
  321.              Xor256(@L0,@p8x8[p_12],(sboxKeys[1] shr 8) and $FF);
  322.              A:= (sboxKeys[0] shr 8) and $FF;
  323.              i:= 0;
  324.              while i< 256 do
  325.              begin
  326.                sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[p_11,L0[i]] xor A];
  327.                sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[p_11,L0[i+1]] xor A];
  328.                Inc(i,2);
  329.              end;
  330.              Xor256(@L0,@p8x8[p_22],(sboxKeys[1] shr 16) and $FF);
  331.              A:= (sboxKeys[0] shr 16) and $FF;
  332.              i:= 0;
  333.              while i< 256 do
  334.              begin
  335.                sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[p_21,L0[i]] xor A];
  336.                sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[p_21,L0[i+1]] xor A];
  337.                Inc(i,2);
  338.              end;
  339.              Xor256(@L0,@p8x8[p_32],(sboxKeys[1] shr 24));
  340.              A:= (sboxKeys[0] shr 24);
  341.              i:= 0;
  342.              while i< 256 do
  343.              begin
  344.                sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[p_31,L0[i]] xor A];
  345.                sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[p_31,L0[i+1]] xor A];
  346.                Inc(i,2);
  347.              end;
  348.            end;
  349.       192: begin
  350.              Xor256(@L0,@p8x8[p_03],sboxKeys[2] and $FF);
  351.              A:= sboxKeys[0] and $FF;
  352.              B:= sboxKeys[1] and $FF;
  353.              i:= 0;
  354.              while i< 256 do
  355.              begin
  356.                sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[p_01,p8x8[p_02,L0[i]] xor B] xor A];
  357.                sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[p_01,p8x8[p_02,L0[i+1]] xor B] xor A];
  358.                Inc(i,2);
  359.              end;
  360.              Xor256(@L0,@p8x8[p_13],(sboxKeys[2] shr 8) and $FF);
  361.              A:= (sboxKeys[0] shr 8) and $FF;
  362.              B:= (sboxKeys[1] shr 8) and $FF;
  363.              i:= 0;
  364.              while i< 256 do
  365.              begin
  366.                sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[p_11,p8x8[p_12,L0[i]] xor B] xor A];
  367.                sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[p_11,p8x8[p_12,L0[i+1]] xor B] xor A];
  368.                Inc(i,2);
  369.              end;
  370.              Xor256(@L0,@p8x8[p_23],(sboxKeys[2] shr 16) and $FF);
  371.              A:= (sboxKeys[0] shr 16) and $FF;
  372.              B:= (sboxKeys[1] shr 16) and $FF;
  373.              i:= 0;
  374.              while i< 256 do
  375.              begin
  376.                sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[p_21,p8x8[p_22,L0[i]] xor B] xor A];
  377.                sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[p_21,p8x8[p_22,L0[i+1]] xor B] xor A];
  378.                Inc(i,2);
  379.              end;
  380.              Xor256(@L0,@p8x8[p_33],(sboxKeys[2] shr 24));
  381.              A:= (sboxKeys[0] shr 24);
  382.              B:= (sboxKeys[1] shr 24);
  383.              i:= 0;
  384.              while i< 256 do
  385.              begin
  386.                sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[p_31,p8x8[p_32,L0[i]] xor B] xor A];
  387.                sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[p_31,p8x8[p_32,L0[i+1]] xor B] xor A];
  388.                Inc(i,2);
  389.              end;
  390.            end;
  391.       256: begin
  392.              Xor256(@L1,@p8x8[p_04],(sboxKeys[3]) and $FF);
  393.              i:= 0;
  394.              while i< 256 do
  395.              begin
  396.                L0[i  ]:= p8x8[p_03,L1[i]];
  397.                L0[i+1]:= p8x8[p_03,L1[i+1]];
  398.                Inc(i,2);
  399.              end;
  400.              Xor256(@L0,@L0,(sboxKeys[2]) and $FF);
  401.              A:= (sboxKeys[0]) and $FF;
  402.              B:= (sboxKeys[1]) and $FF;
  403.              i:= 0;
  404.              while i< 256 do
  405.              begin
  406.                sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[p_01,p8x8[p_02,L0[i]] xor B] xor A];
  407.                sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[p_01,p8x8[p_02,L0[i+1]] xor B] xor A];
  408.                Inc(i,2);
  409.              end;
  410.              Xor256(@L1,@p8x8[p_14],(sboxKeys[3] shr  8) and $FF);
  411.              i:= 0;
  412.              while i< 256 do
  413.              begin
  414.                L0[i  ]:= p8x8[p_13,L1[i]];
  415.                L0[i+1]:= p8x8[p_13,L1[i+1]];
  416.                Inc(i,2);
  417.              end;
  418.              Xor256(@L0,@L0,(sboxKeys[2] shr  8) and $FF);
  419.              A:= (sboxKeys[0] shr  8) and $FF;
  420.              B:= (sboxKeys[1] shr  8) and $FF;
  421.              i:= 0;
  422.              while i< 256 do
  423.              begin
  424.                sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[p_11,p8x8[p_12,L0[i]] xor B] xor A];
  425.                sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[p_11,p8x8[p_12,L0[i+1]] xor B] xor A];
  426.                Inc(i,2);
  427.              end;
  428.  
  429.              Xor256(@L1,@p8x8[p_24],(sboxKeys[3] shr 16) and $FF);
  430.              i:= 0;
  431.              while i< 256 do
  432.              begin
  433.                L0[i  ]:= p8x8[p_23,L1[i]];
  434.                L0[i+1]:= p8x8[p_23,L1[i+1]];
  435.                Inc(i,2);
  436.              end;
  437.              Xor256(@L0,@L0,(sboxKeys[2] shr 16) and $FF);
  438.              A:= (sboxKeys[0] shr 16) and $FF;
  439.              B:= (sboxKeys[1] shr 16) and $FF;
  440.              i:= 0;
  441.              while i< 256 do
  442.              begin
  443.                sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[p_21,p8x8[p_22,L0[i]] xor B] xor A];
  444.                sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[p_21,p8x8[p_22,L0[i+1]] xor B] xor A];
  445.                Inc(i,2);
  446.              end;
  447.              Xor256(@L1,@p8x8[p_34],(sboxKeys[3] shr 24));
  448.              i:= 0;
  449.              while i< 256 do
  450.              begin
  451.                L0[i  ]:= p8x8[p_33,L1[i]];
  452.                L0[i+1]:= p8x8[p_33,L1[i+1]];
  453.                Inc(i,2);
  454.              end;
  455.              Xor256(@L0,@L0,(sboxKeys[2] shr 24));
  456.              A:= (sboxKeys[0] shr 24);
  457.              B:= (sboxKeys[1] shr 24);
  458.              i:= 0;
  459.              while i< 256 do
  460.              begin
  461.                sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[p_31,p8x8[p_32,L0[i]] xor B] xor A];
  462.                sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[p_31,p8x8[p_32,L0[i+1]] xor B] xor A];
  463.                Inc(i,2);
  464.              end;
  465.            end;
  466.     end;
  467.   end;
  468. end;
  469.  
  470. procedure TwofishBurn;
  471. begin
  472.   FillChar(Data,Sizeof(Data),0);
  473. end;
  474.  
  475. procedure TwofishEncryptECB;
  476. var
  477.   i: integer;
  478.   t0, t1: DWord;
  479.   X: array[0..3] of DWord;
  480. begin
  481.   X[0]:= PDWord(InData)^ xor Data.SubKeys[INPUTWHITEN];
  482.   X[1]:= PDWord(integer(InData)+4)^ xor Data.SubKeys[INPUTWHITEN+1];
  483.   X[2]:= PDWord(integer(InData)+8)^ xor Data.SubKeys[INPUTWHITEN+2];
  484.   X[3]:= PDWord(integer(InData)+12)^ xor Data.SubKeys[INPUTWHITEN+3];
  485.   with Data do
  486.   begin
  487.     i:= 0;
  488.     while i<= NUMROUNDS-2 do
  489.     begin
  490.       t0:= Data.sBox[0,2*(((x[0]) shr (blu[(0) and  3])) and $ff)] xor Data.sBox[0,2*(((x[0]) shr (blu[(1) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[0]) shr (blu[(2) and  3])) and $ff)] xor Data.sBox[2,2*(((x[0]) shr (blu[(3) and  3])) and $ff)+1];
  491.       t1:= Data.sBox[0,2*(((x[1]) shr (blu[(3) and  3])) and $ff)] xor Data.sBox[0,2*(((x[1]) shr (blu[(4) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[1]) shr (blu[(5) and  3])) and $ff)] xor Data.sBox[2,2*(((x[1]) shr (blu[(6) and  3])) and $ff)+1];
  492.       x[3]:= LRot32(x[3],1);
  493.       x[2]:= x[2] xor (t0 +   t1 + Data.Subkeys[ROUNDSUBKEYS+2*i]);
  494.       x[3]:= x[3] xor (t0 + 2*t1 + Data.Subkeys[ROUNDSUBKEYS+2*i+1]);
  495.       x[2]:= RRot32(x[2],1);
  496.  
  497.       t0:= Data.sBox[0,2*(((x[2]) shr (blu[(0) and  3])) and $ff)] xor Data.sBox[0,2*(((x[2]) shr (blu[(1) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[2]) shr (blu[(2) and  3])) and $ff)] xor Data.sBox[2,2*(((x[2]) shr (blu[(3) and  3])) and $ff)+1];
  498.       t1:= Data.sBox[0,2*(((x[3]) shr (blu[(3) and  3])) and $ff)] xor Data.sBox[0,2*(((x[3]) shr (blu[(4) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[3]) shr (blu[(5) and  3])) and $ff)] xor Data.sBox[2,2*(((x[3]) shr (blu[(6) and  3])) and $ff)+1];
  499.       x[1]:= LRot32(x[1],1);
  500.       x[0]:= x[0] xor (t0 +   t1 + Data.Subkeys[ROUNDSUBKEYS+2*(i+1)]);
  501.       x[1]:= x[1] xor (t0 + 2*t1 + Data.Subkeys[ROUNDSUBKEYS+2*(i+1)+1]);
  502.       x[0]:= RRot32(x[0],1);
  503.       Inc(i,2);
  504.     end;
  505.   end;
  506.   PDWord(integer(OutData)+ 0)^:= X[2] xor Data.SubKeys[OUTPUTWHITEN];
  507.   PDWord(integer(OutData)+ 4)^:= X[3] xor Data.SubKeys[OUTPUTWHITEN+1];
  508.   PDWord(integer(OutData)+ 8)^:= X[0] xor Data.SubKeys[OUTPUTWHITEN+2];
  509.   PDWord(integer(OutData)+12)^:= X[1] xor Data.SubKeys[OUTPUTWHITEN+3];
  510. end;
  511.  
  512. procedure TwofishDecryptECB;
  513. var
  514.   i: integer;
  515.   t0, t1: DWord;
  516.   X: array[0..3] of DWord;
  517. begin
  518.   X[2]:= PDWord(InData)^ xor Data.SubKeys[OUTPUTWHITEN];
  519.   X[3]:= PDWord(integer(InData)+4)^ xor Data.SubKeys[OUTPUTWHITEN+1];
  520.   X[0]:= PDWord(integer(InData)+8)^ xor Data.SubKeys[OUTPUTWHITEN+2];
  521.   X[1]:= PDWord(integer(InData)+12)^ xor Data.SubKeys[OUTPUTWHITEN+3];
  522.   with Data do
  523.   begin
  524.     i:= NUMROUNDS-2;
  525.     while i>= 0 do
  526.     begin
  527.       t0:= Data.sBox[0,2*(((x[2]) shr (blu[(0) and  3])) and $ff)] xor Data.sBox[0,2*(((x[2]) shr (blu[(1) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[2]) shr (blu[(2) and  3])) and $ff)] xor Data.sBox[2,2*(((x[2]) shr (blu[(3) and  3])) and $ff)+1];
  528.       t1:= Data.sBox[0,2*(((x[3]) shr (blu[(3) and  3])) and $ff)] xor Data.sBox[0,2*(((x[3]) shr (blu[(4) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[3]) shr (blu[(5) and  3])) and $ff)] xor Data.sBox[2,2*(((x[3]) shr (blu[(6) and  3])) and $ff)+1];
  529.       x[0]:= LRot32(x[0],1);
  530.       x[0]:= x[0] xor (t0 +   t1 + Data.Subkeys[ROUNDSUBKEYS+2*(i+1)]);
  531.       x[1]:= x[1] xor (t0 + 2*t1 + Data.Subkeys[ROUNDSUBKEYS+2*(i+1)+1]);
  532.       x[1]:= RRot32(x[1],1);
  533.  
  534.       t0:= Data.sBox[0,2*(((x[0]) shr (blu[(0) and  3])) and $ff)] xor Data.sBox[0,2*(((x[0]) shr (blu[(1) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[0]) shr (blu[(2) and  3])) and $ff)] xor Data.sBox[2,2*(((x[0]) shr (blu[(3) and  3])) and $ff)+1];
  535.       t1:= Data.sBox[0,2*(((x[1]) shr (blu[(3) and  3])) and $ff)] xor Data.sBox[0,2*(((x[1]) shr (blu[(4) and  3])) and $ff)+1] xor Data.sBox[2,2*(((x[1]) shr (blu[(5) and  3])) and $ff)] xor Data.sBox[2,2*(((x[1]) shr (blu[(6) and  3])) and $ff)+1];
  536.       x[2]:= LRot32(x[2],1);
  537.       x[2]:= x[2] xor (t0 +   t1 + Data.Subkeys[ROUNDSUBKEYS+2*i]);
  538.       x[3]:= x[3] xor (t0 + 2*t1 + Data.Subkeys[ROUNDSUBKEYS+2*i+1]);
  539.       x[3]:= RRot32(x[3],1);
  540.       Dec(i,2);
  541.     end;
  542.   end;
  543.   PDWord(integer(OutData)+ 0)^:= X[0] xor Data.SubKeys[INPUTWHITEN];
  544.   PDWord(integer(OutData)+ 4)^:= X[1] xor Data.SubKeys[INPUTWHITEN+1];
  545.   PDWord(integer(OutData)+ 8)^:= X[2] xor Data.SubKeys[INPUTWHITEN+2];
  546.   PDWord(integer(OutData)+12)^:= X[3] xor Data.SubKeys[INPUTWHITEN+3];
  547. end;
  548.  
  549. procedure TwofishEncryptCBC;
  550. begin
  551.   XorBlock(InData,@Data.LastBlock,OutData,16);
  552.   TwofishEncryptECB(Data,OutData,OutData);
  553.   Move(OutData^,Data.LastBlock,16);
  554. end;
  555.  
  556. procedure TwofishDecryptCBC;
  557. var
  558.   TempBlock: array[0..15] of byte;
  559. begin
  560.   Move(InData^,TempBlock,16);
  561.   TwofishDecryptECB(Data,InData,OutData);
  562.   XorBlock(OutData,@Data.LastBlock,OutData,16);
  563.   Move(TempBlock,Data.LastBlock,16);
  564. end;
  565.  
  566. procedure TwofishEncryptCFB;
  567. var
  568.   i: integer;
  569.   TempBlock: array[0..15] of byte;
  570. begin
  571.   for i:= 0 to Len-1 do
  572.   begin
  573.     TwofishEncryptECB(Data,@Data.LastBlock,@TempBlock);
  574.     PByteArray(OutData)[i]:= PByteArray(InData)[i] xor TempBlock[0];
  575.     Move(Data.LastBlock[1],Data.LastBlock[0],15);
  576.     Data.LastBlock[15]:= PByteArray(OutData)[i];
  577.   end;
  578. end;
  579.  
  580. procedure TwofishDecryptCFB;
  581. var
  582.   i: integer;
  583.   TempBlock: array[0..15] of byte;
  584.   b: byte;
  585. begin
  586.   for i:= 0 to Len-1 do
  587.   begin
  588.     b:= PByteArray(InData)[i];
  589.     TwofishEncryptECB(Data,@Data.LastBlock,@TempBlock);
  590.     PByteArray(OutData)[i]:= PByteArray(InData)[i] xor TempBlock[0];
  591.     Move(Data.LastBlock[1],Data.LastBlock[0],15);
  592.     Data.LastBlock[15]:= b;
  593.   end;
  594. end;
  595.  
  596. procedure TwofishEncryptOFB;
  597. begin
  598.   TwofishEncryptECB(Data,@Data.LastBlock,@Data.LastBlock);
  599.   XorBlock(@Data.LastBlock,InData,OutData,16);
  600. end;
  601.  
  602. procedure TwofishDecryptOFB;
  603. begin
  604.   TwofishEncryptECB(Data,@Data.LastBlock,@Data.LastBlock);
  605.   XorBlock(@Data.LastBlock,InData,OutData,16);
  606. end;
  607.  
  608. procedure TwofishEncryptOFBC;
  609. var
  610.   i: integer;
  611.   TempBlock: array[0..15] of byte;
  612. begin
  613.   for i:= 0 to Len-1 do
  614.   begin
  615.     TwofishEncryptECB(Data,@Data.LastBlock,@TempBlock);
  616.     PByteArray(OutData)[i]:= PByteArray(InData)[i] xor TempBlock[0];
  617.     IncBlock(@Data.LastBlock,16);
  618.   end;
  619. end;
  620.  
  621. procedure TwofishDecryptOFBC;
  622. var
  623.   i: integer;
  624.   TempBlock: array[0..15] of byte;
  625. begin
  626.   for i:= 0 to Len-1 do
  627.   begin
  628.     TwofishEncryptECB(Data,@Data.LastBlock,@TempBlock);
  629.     PByteArray(OutData)[i]:= PByteArray(InData)[i] xor TempBlock[0];
  630.     IncBlock(@Data.LastBlock,16);
  631.   end;
  632. end;
  633.  
  634. procedure TwofishReset;
  635. begin
  636.   Move(Data.InitBlock,Data.LastBlock,16);
  637. end;
  638.  
  639.  
  640. initialization
  641.   PreCompMDS;
  642.  
  643. end.
  644.  
  645.