initial commit
[rofl0r-KOL.git] / units / twofish / kol_Twofish.pas
blobaa8a644170e92280147ccc32c4b4cfa4721d2ca5
1 {Kol modifications done by neuron, note that this only includes the twofish
2 implementation, not the (loads) of other free encryption types.
4 Great library :)
6 neuron, neuron@hollowtube.mine.nu, problems with the modification can be sent
7 to my email address.
10 Example usage:
11 var TFData:TTwofishData;
12 const key=array[0..7] of char = 'qm3igmfk'
13 // inblock and outblock can be pretty much anything
14 // if you use it on strings, remember, string[0] is the length
15 // so use twofishencrypt___(data,string[1],x,length(string));
16 begin
17 TwofishInit(tfdata,key,8,nil);
18 twofishencryptcbc(tfdata,inblock,outblock,length(inblock));
19 TwofishReset(tfdata);
20 twofishdecryptcbc(tfdata,outblock,inblock,length(outblock));
21 TwoFishBurn(tfdata);
22 end;}
23 {******************************************************************************}
24 {** A binary compatible implementation of Twofish *****************************}
25 {******************************************************************************}
26 {** Written by David Barton (davebarton@bigfoot.com) **************************}
27 {** http://www.scramdisk.clara.net/ *******************************************}
28 {******************************************************************************}
29 unit kol_Twofish;
31 interface
33 {** DCPcrypt include file **}
35 {$Q-} { over flow checking off }
36 {$R-} { range checking off }
38 uses kol;
40 {** DCPCrypt **}
41 type
42 PWord= ^Word;
43 PDWord= ^our_DWord;
44 {$IFDEF VER120}
45 our_DWord= longword;
46 {$ELSE}
47 our_DWord= longint;
48 {$ENDIF}
49 PDWordArray= ^TDWordArray;
50 TDWordArray= array[0..1023] of our_DWord;
51 PByteArray= ^TByteArray;
52 TByteArray= array[0..4095] of byte;
53 {** DCPCrypt End**}
55 const
56 BLU: array[0..3] of our_DWord= (0, 8, 16, 24);
57 TWOFISH_BLOCKSIZE= 16;
58 INPUTWHITEN= 0;
59 OUTPUTWHITEN= (TWOFISH_BLOCKSIZE div 4);
60 NUMROUNDS= 16;
61 ROUNDSUBKEYS= (OUTPUTWHITEN + TWOFISH_BLOCKSIZE div 4);
62 TOTALSUBKEYS= (ROUNDSUBKEYS + NUMROUNDS * 2);
63 RS_GF_FDBK= $14d;
64 SK_STEP= $02020202;
65 SK_BUMP= $01010101;
66 SK_ROTL= 9;
67 P_00= 1;
68 P_01= 0;
69 P_02= 0;
70 P_03= (P_01 xor 1);
71 P_04= 1;
72 P_10= 0;
73 P_11= 0;
74 P_12= 1;
75 P_13= (P_11 xor 1);
76 P_14= 0;
77 P_20= 1;
78 P_21= 1;
79 P_22= 0;
80 P_23= (P_21 xor 1);
81 P_24= 0;
82 P_30= 0;
83 P_31= 1;
84 P_32= 1;
85 P_33= (P_31 xor 1);
86 P_34= 1;
87 MDS_GF_FDBK= $169;
89 type
90 TTwofishData= record
91 IV, LB: array[0..15] of byte;
92 KeyLen: our_DWord;
93 SubKeys: array[0..TOTALSUBKEYS-1] of our_DWord;
94 sboxKeys: array[0..3] of our_DWord;
95 sbox: array[0..3,0..255] of our_DWord;
96 end;
98 procedure TwofishInit(var Data: TTwofishData; var Key; Size: longint; IVector: pointer);
99 procedure TwofishReset(var Data: TTwofishData);
100 procedure TwofishBurn(var Data: TTwofishData);
101 procedure TwofishEncryptECB(var Data: TTwofishData; const InBlock; var OutBlock);
102 procedure TwofishDecryptECB(var Data: TTwofishData; const InBlock; var OutBlock);
103 procedure TwofishEncryptCBC(var Data: TTwofishData; const InData; var OutData; Size: longint);
104 procedure TwofishDecryptCBC(var Data: TTwofishData; const InData; var OutData; Size: longint);
105 procedure TwofishEncryptCFB(var Data: TTwofishData; const InData; var OutData; Size: longint);
106 procedure TwofishDecryptCFB(var Data: TTwofishData; const InData; var OutData; Size: longint);
108 {******************************************************************************}
109 {******************************************************************************}
110 implementation
112 {$I Twofish.Inc}
115 MDS: array[0..3,0..255] of our_DWord;
117 { ** DcpCrypt **}
118 function LRot32(X: our_DWord; c: longint): our_DWord; register; assembler;
120 mov ecx, edx
121 rol eax, cl
122 end;
124 function RRot32(X: our_DWord; c: longint): our_DWord; register; assembler;
126 mov ecx, edx
127 ror eax, cl
128 end;
130 procedure XorBlock(I1, I2, O1: PByteArray; Len: longint);
132 i: longint;
133 begin
134 for i:= 0 to Len-1 do
135 O1^[i]:= I1^[i] xor I2^[i];
136 end;
137 { ** DcpCrypt End**}
144 function LFSR1(x: our_DWord): our_DWord;
145 begin
146 if (x and 1)<> 0 then
147 Result:= (x shr 1) xor (MDS_GF_FDBK div 2)
148 else
149 Result:= (x shr 1);
150 end;
151 function LFSR2(x: our_DWord): our_DWord;
152 begin
153 if (x and 2)<> 0 then
154 if (x and 1)<> 0 then
155 Result:= (x shr 2) xor (MDS_GF_FDBK div 2) xor (MDS_GF_FDBK div 4)
156 else
157 Result:= (x shr 2) xor (MDS_GF_FDBK div 2)
158 else
159 if (x and 1)<> 0 then
160 Result:= (x shr 2) xor (MDS_GF_FDBK div 4)
161 else
162 Result:= (x shr 2);
163 end;
164 function Mul_X(x: our_DWord): our_DWord;
165 begin
166 Result:= x xor LFSR2(x);
167 end;
168 function Mul_Y(x: our_DWord): our_DWord;
169 begin
170 Result:= x xor LFSR1(x) xor LFSR2(x);
171 end;
173 function RS_MDS_Encode(lK0, lK1: our_dword): our_dword;
175 lR, nI, nJ, lG2, lG3: our_dword;
176 bB: byte;
177 begin
178 lR:= 0;
179 for nI:= 0 to 1 do
180 begin
181 if nI<> 0 then
182 lR:= lR xor lK0
183 else
184 lR:= lR xor lK1;
185 for nJ:= 0 to 3 do
186 begin
187 bB:= lR shr 24;
188 if (bB and $80)<> 0 then
189 lG2:= ((bB shl 1) xor RS_GF_FDBK) and $FF
190 else
191 lG2:= (bB shl 1) and $FF;
192 if (bB and 1)<> 0 then
193 lG3:= ((bB shr 1) and $7f) xor (RS_GF_FDBK shr 1) xor lG2
194 else
195 lG3:= ((bB shr 1) and $7f) xor lG2;
196 lR:= (lR shl 8) xor (lG3 shl 24) xor (lG2 shl 16) xor (lG3 shl 8) xor bB;
197 end;
198 end;
199 Result:= lR;
200 end;
202 function f32(x: our_dword; K32: PDWordArray; Len: our_dword): our_dword;
204 t0, t1, t2, t3: our_dword;
205 begin
206 t0:= x and $FF;
207 t1:= (x shr 8) and $FF;
208 t2:= (x shr 16) and $FF;
209 t3:= x shr 24;
210 if Len= 256 then
211 begin
212 t0:= p8x8[p_04,t0] xor ((K32^[3]) and $FF);
213 t1:= p8x8[p_14,t1] xor ((K32^[3] shr 8) and $FF);
214 t2:= p8x8[p_24,t2] xor ((K32^[3] shr 16) and $FF);
215 t3:= p8x8[p_34,t3] xor ((K32^[3] shr 24));
216 end;
217 if Len>= 192 then
218 begin
219 t0:= p8x8[p_03,t0] xor ((K32^[2]) and $FF);
220 t1:= p8x8[p_13,t1] xor ((K32^[2] shr 8) and $FF);
221 t2:= p8x8[p_23,t2] xor ((K32^[2] shr 16) and $FF);
222 t3:= p8x8[p_33,t3] xor ((K32^[2] shr 24));
223 end;
224 Result:= MDS[0,p8x8[p_01,p8x8[p_02,t0] xor ((K32^[1]) and $FF)] xor ((K32^[0]) and $FF)] xor
225 MDS[1,p8x8[p_11,p8x8[p_12,t1] xor ((K32^[1] shr 8) and $FF)] xor ((K32^[0] shr 8) and $FF)] xor
226 MDS[2,p8x8[p_21,p8x8[p_22,t2] xor ((K32^[1] shr 16) and $FF)] xor ((K32^[0] shr 16) and $FF)] xor
227 MDS[3,p8x8[p_31,p8x8[p_32,t3] xor ((K32^[1] shr 24))] xor ((K32^[0] shr 24))];
228 end;
230 procedure TwofishEncryptECB;
232 i: longint;
233 t0, t1: our_dword;
234 X: array[0..3] of our_dword;
235 begin
236 with Data do begin
237 X[0]:= PDWord(@InBlock)^ xor SubKeys[INPUTWHITEN];
238 X[1]:= PDWord(longint(@InBlock)+4)^ xor SubKeys[INPUTWHITEN+1];
239 X[2]:= PDWord(longint(@InBlock)+8)^ xor SubKeys[INPUTWHITEN+2];
240 X[3]:= PDWord(longint(@InBlock)+12)^ xor SubKeys[INPUTWHITEN+3];
241 i:= 0;
242 while i<= NUMROUNDS-2 do
243 begin
244 t0:= sBox[0,2*(x[0] and $ff)] xor sBox[0,2*(((x[0]) shr 8) and $ff)+1]
245 xor sBox[2,2*((x[0] shr 16) and $ff)] xor sBox[2,2*((x[0] shr 24) and $ff)+1];
246 t1:= sBox[0,2*((x[1] shr 24) and $ff)] xor sBox[0,2*(x[1] and $ff)+1]
247 xor sBox[2,2*((x[1] shr 8) and $ff)] xor sBox[2,2*((x[1] shr 16) and $ff)+1];
248 x[3]:= LRot32(x[3],1);
249 x[2]:= x[2] xor (t0 + t1 + SubKeys[ROUNDSUBKEYS+2*i]);
250 x[3]:= x[3] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*i+1]);
251 x[2]:= RRot32(x[2],1);
253 t0:= sBox[0,2*(x[2] and $ff)] xor sBox[0,2*((x[2] shr 8) and $ff)+1]
254 xor sBox[2,2*((x[2] shr 16) and $ff)] xor sBox[2,2*((x[2] shr 24) and $ff)+1];
255 t1:= sBox[0,2*((x[3] shr 24) and $ff)] xor sBox[0,2*(x[3] and $ff)+1]
256 xor sBox[2,2*((x[3] shr 8) and $ff)] xor sBox[2,2*((x[3] shr 16) and $ff)+1];
257 x[1]:= LRot32(x[1],1);
258 x[0]:= x[0] xor (t0 + t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)]);
259 x[1]:= x[1] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)+1]);
260 x[0]:= RRot32(x[0],1);
261 Inc(i,2);
262 end;
263 PDWord(longint(@OutBlock)+ 0)^:= X[2] xor SubKeys[OUTPUTWHITEN];
264 PDWord(longint(@OutBlock)+ 4)^:= X[3] xor SubKeys[OUTPUTWHITEN+1];
265 PDWord(longint(@OutBlock)+ 8)^:= X[0] xor SubKeys[OUTPUTWHITEN+2];
266 PDWord(longint(@OutBlock)+12)^:= X[1] xor SubKeys[OUTPUTWHITEN+3];
267 end;
268 end;
270 procedure TwofishDecryptECB;
272 i: longint;
273 t0, t1: our_dword;
274 X: array[0..3] of our_dword;
275 begin
276 with Data do begin
277 X[2]:= PDWord(@InBlock)^ xor SubKeys[OUTPUTWHITEN];
278 X[3]:= PDWord(longint(@InBlock)+4)^ xor SubKeys[OUTPUTWHITEN+1];
279 X[0]:= PDWord(longint(@InBlock)+8)^ xor SubKeys[OUTPUTWHITEN+2];
280 X[1]:= PDWord(longint(@InBlock)+12)^ xor SubKeys[OUTPUTWHITEN+3];
281 i:= NUMROUNDS-2;
282 while i>= 0 do
283 begin
284 t0:= sBox[0,2*(x[2] and $ff)] xor sBox[0,2*((x[2] shr 8) and $ff)+1]
285 xor sBox[2,2*((x[2] shr 16) and $ff)] xor sBox[2,2*((x[2] shr 24) and $ff)+1];
286 t1:= sBox[0,2*((x[3] shr 24) and $ff)] xor sBox[0,2*(x[3] and $ff)+1]
287 xor sBox[2,2*((x[3] shr 8) and $ff)] xor sBox[2,2*((x[3] shr 16) and $ff)+1];
288 x[0]:= LRot32(x[0],1);
289 x[0]:= x[0] xor (t0 + t1 + Subkeys[ROUNDSUBKEYS+2*(i+1)]);
290 x[1]:= x[1] xor (t0 + 2*t1 + Subkeys[ROUNDSUBKEYS+2*(i+1)+1]);
291 x[1]:= RRot32(x[1],1);
293 t0:= sBox[0,2*(x[0] and $ff)] xor sBox[0,2*((x[0] shr 8) and $ff)+1]
294 xor sBox[2,2*((x[0] shr 16) and $ff)] xor sBox[2,2*((x[0] shr 24) and $ff)+1];
295 t1:= sBox[0,2*((x[1] shr 24) and $ff)] xor sBox[0,2*(x[1] and $ff)+1]
296 xor sBox[2,2*((x[1] shr 8) and $ff)] xor sBox[2,2*((x[1] shr 16) and $ff)+1];
297 x[2]:= LRot32(x[2],1);
298 x[2]:= x[2] xor (t0 + t1 + Subkeys[ROUNDSUBKEYS+2*i]);
299 x[3]:= x[3] xor (t0 + 2*t1 + Subkeys[ROUNDSUBKEYS+2*i+1]);
300 x[3]:= RRot32(x[3],1);
301 Dec(i,2);
302 end;
303 PDWord(longint(@OutBlock)+ 0)^:= X[0] xor SubKeys[INPUTWHITEN];
304 PDWord(longint(@OutBlock)+ 4)^:= X[1] xor SubKeys[INPUTWHITEN+1];
305 PDWord(longint(@OutBlock)+ 8)^:= X[2] xor SubKeys[INPUTWHITEN+2];
306 PDWord(longint(@OutBlock)+12)^:= X[3] xor SubKeys[INPUTWHITEN+3];
307 end;
308 end;
310 procedure TwofishInit;
311 procedure Xor256(Dst, Src: PDWordArray; v: byte);
313 i: our_dword;
314 begin
315 for i:= 0 to 63 do
316 Dst^[i]:= Src^[i] xor (v * $01010101);
317 end;
319 key32: array[0..7] of our_dword;
320 k32e, k32o: array[0..3] of our_dword;
321 k64Cnt, i, j, A, B, q, subkeyCnt: our_dword;
322 L0, L1: array[0..255] of byte;
323 begin
324 if (Size> 256) or (Size<= 0) or ((Size mod 8)<> 0) then
325 Exit;
326 with Data do begin
328 FillChar(Key32,Sizeof(Key32),0);
329 Move(Key,Key32,Size div 8);
330 if Size<= 128 then { pad the key to either 128bit, 192bit or 256bit}
331 Size:= 128
332 else if Size<= 192 then
333 Size:= 192
334 else
335 Size:= 256;
336 subkeyCnt:= ROUNDSUBKEYS + 2*NUMROUNDS;
337 KeyLen:= Size;
338 k64Cnt:= Size div 64;
339 j:= k64Cnt-1;
340 for i:= 0 to j do
341 begin
342 k32e[i]:= key32[2*i];
343 k32o[i]:= key32[2*i+1];
344 sboxKeys[j]:= RS_MDS_Encode(k32e[i],k32o[i]);
345 Dec(j);
346 end;
347 q:= 0;
348 for i:= 0 to ((subkeyCnt div 2)-1) do
349 begin
350 A:= f32(q,@k32e,Size);
351 B:= f32(q+SK_BUMP,@k32o,Size);
352 B:= LRot32(B,8);
353 SubKeys[2*i]:= A+B;
354 B:= A + 2*B;
355 SubKeys[2*i+1]:= LRot32(B,SK_ROTL);
356 Inc(q,SK_STEP);
357 end;
358 case Size of
359 128: begin
360 Xor256(@L0,@p8x8[p_02],(sboxKeys[1] and $FF));
361 A:= (sboxKeys[0] and $FF);
362 i:= 0;
363 while i< 256 do
364 begin
365 sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[p_01,L0[i]] xor A];
366 sBox[0 and 2,2*i+(0 and 1)+2]:= MDS[0,p8x8[p_01,L0[i+1]] xor A];
367 Inc(i,2);
368 end;
369 Xor256(@L0,@p8x8[p_12],(sboxKeys[1] shr 8) and $FF);
370 A:= (sboxKeys[0] shr 8) and $FF;
371 i:= 0;
372 while i< 256 do
373 begin
374 sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[p_11,L0[i]] xor A];
375 sBox[1 and 2,2*i+(1 and 1)+2]:= MDS[1,p8x8[p_11,L0[i+1]] xor A];
376 Inc(i,2);
377 end;
378 Xor256(@L0,@p8x8[p_22],(sboxKeys[1] shr 16) and $FF);
379 A:= (sboxKeys[0] shr 16) and $FF;
380 i:= 0;
381 while i< 256 do
382 begin
383 sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[p_21,L0[i]] xor A];
384 sBox[2 and 2,2*i+(2 and 1)+2]:= MDS[2,p8x8[p_21,L0[i+1]] xor A];
385 Inc(i,2);
386 end;
387 Xor256(@L0,@p8x8[p_32],(sboxKeys[1] shr 24));
388 A:= (sboxKeys[0] shr 24);
389 i:= 0;
390 while i< 256 do
391 begin
392 sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[p_31,L0[i]] xor A];
393 sBox[3 and 2,2*i+(3 and 1)+2]:= MDS[3,p8x8[p_31,L0[i+1]] xor A];
394 Inc(i,2);
395 end;
396 end;
397 192: begin
398 Xor256(@L0,@p8x8[p_03],sboxKeys[2] and $FF);
399 A:= sboxKeys[0] and $FF;
400 B:= sboxKeys[1] and $FF;
401 i:= 0;
402 while i< 256 do
403 begin
404 sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[p_01,p8x8[p_02,L0[i]] xor B] xor A];
405 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];
406 Inc(i,2);
407 end;
408 Xor256(@L0,@p8x8[p_13],(sboxKeys[2] shr 8) and $FF);
409 A:= (sboxKeys[0] shr 8) and $FF;
410 B:= (sboxKeys[1] shr 8) and $FF;
411 i:= 0;
412 while i< 256 do
413 begin
414 sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[p_11,p8x8[p_12,L0[i]] xor B] xor A];
415 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];
416 Inc(i,2);
417 end;
418 Xor256(@L0,@p8x8[p_23],(sboxKeys[2] shr 16) and $FF);
419 A:= (sboxKeys[0] shr 16) and $FF;
420 B:= (sboxKeys[1] shr 16) and $FF;
421 i:= 0;
422 while i< 256 do
423 begin
424 sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[p_21,p8x8[p_22,L0[i]] xor B] xor A];
425 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];
426 Inc(i,2);
427 end;
428 Xor256(@L0,@p8x8[p_33],(sboxKeys[2] shr 24));
429 A:= (sboxKeys[0] shr 24);
430 B:= (sboxKeys[1] shr 24);
431 i:= 0;
432 while i< 256 do
433 begin
434 sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[p_31,p8x8[p_32,L0[i]] xor B] xor A];
435 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];
436 Inc(i,2);
437 end;
438 end;
439 256: begin
440 Xor256(@L1,@p8x8[p_04],(sboxKeys[3]) and $FF);
441 i:= 0;
442 while i< 256 do
443 begin
444 L0[i ]:= p8x8[p_03,L1[i]];
445 L0[i+1]:= p8x8[p_03,L1[i+1]];
446 Inc(i,2);
447 end;
448 Xor256(@L0,@L0,(sboxKeys[2]) and $FF);
449 A:= (sboxKeys[0]) and $FF;
450 B:= (sboxKeys[1]) and $FF;
451 i:= 0;
452 while i< 256 do
453 begin
454 sBox[0 and 2,2*i+(0 and 1)]:= MDS[0,p8x8[p_01,p8x8[p_02,L0[i]] xor B] xor A];
455 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];
456 Inc(i,2);
457 end;
458 Xor256(@L1,@p8x8[p_14],(sboxKeys[3] shr 8) and $FF);
459 i:= 0;
460 while i< 256 do
461 begin
462 L0[i ]:= p8x8[p_13,L1[i]];
463 L0[i+1]:= p8x8[p_13,L1[i+1]];
464 Inc(i,2);
465 end;
466 Xor256(@L0,@L0,(sboxKeys[2] shr 8) and $FF);
467 A:= (sboxKeys[0] shr 8) and $FF;
468 B:= (sboxKeys[1] shr 8) and $FF;
469 i:= 0;
470 while i< 256 do
471 begin
472 sBox[1 and 2,2*i+(1 and 1)]:= MDS[1,p8x8[p_11,p8x8[p_12,L0[i]] xor B] xor A];
473 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];
474 Inc(i,2);
475 end;
477 Xor256(@L1,@p8x8[p_24],(sboxKeys[3] shr 16) and $FF);
478 i:= 0;
479 while i< 256 do
480 begin
481 L0[i ]:= p8x8[p_23,L1[i]];
482 L0[i+1]:= p8x8[p_23,L1[i+1]];
483 Inc(i,2);
484 end;
485 Xor256(@L0,@L0,(sboxKeys[2] shr 16) and $FF);
486 A:= (sboxKeys[0] shr 16) and $FF;
487 B:= (sboxKeys[1] shr 16) and $FF;
488 i:= 0;
489 while i< 256 do
490 begin
491 sBox[2 and 2,2*i+(2 and 1)]:= MDS[2,p8x8[p_21,p8x8[p_22,L0[i]] xor B] xor A];
492 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];
493 Inc(i,2);
494 end;
495 Xor256(@L1,@p8x8[p_34],(sboxKeys[3] shr 24));
496 i:= 0;
497 while i< 256 do
498 begin
499 L0[i ]:= p8x8[p_33,L1[i]];
500 L0[i+1]:= p8x8[p_33,L1[i+1]];
501 Inc(i,2);
502 end;
503 Xor256(@L0,@L0,(sboxKeys[2] shr 24));
504 A:= (sboxKeys[0] shr 24);
505 B:= (sboxKeys[1] shr 24);
506 i:= 0;
507 while i< 256 do
508 begin
509 sBox[3 and 2,2*i+(3 and 1)]:= MDS[3,p8x8[p_31,p8x8[p_32,L0[i]] xor B] xor A];
510 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];
511 Inc(i,2);
512 end;
513 end;
514 end;
516 if IVector= nil then
517 begin
518 FillChar(IV,Sizeof(IV),$FF);
519 TwofishEncryptECB(Data,IV,IV);
520 Move(IV,LB,Sizeof(LB));
522 else
523 begin
524 Move(IVector^,IV,Sizeof(IV));
525 Move(IV,LB,Sizeof(IV));
526 end;
527 end;
528 end;
530 procedure TwofishBurn;
531 begin
532 with Data do begin
533 FillChar(sBox,Sizeof(sBox),$FF);
534 FillChar(sBoxKeys,Sizeof(sBoxKeys),$FF);
535 FillChar(SubKeys,Sizeof(SubKeys),$FF);
536 FillChar(IV,Sizeof(IV),$FF);
537 FillChar(LB,Sizeof(LB),$FF);
538 end;
539 end;
541 procedure TwofishReset;
542 begin
543 with Data do
544 Move(IV,LB,Sizeof(LB));
545 end;
547 procedure TwofishEncryptCBC;
549 TB: array[0..15] of byte;
550 i: longint;
551 begin
552 with Data do begin
553 for i:= 1 to (Size div 16) do
554 begin
555 XorBlock(pointer(longint(@InData)+((i-1)*16)),@LB,@TB,Sizeof(TB));
556 TwofishEncryptECB(Data,TB,TB);
557 Move(TB,pointer(longint(@OutData)+((i-1)*16))^,Sizeof(TB));
558 Move(TB,LB,Sizeof(TB));
559 end;
560 if (Size mod 16)<> 0 then
561 begin
562 TwofishEncryptECB(Data,LB,TB);
563 XorBlock(@TB,@pointer(longint(@InData)+Size-(Size mod 16))^,@pointer(longint(@OutData)+Size-(Size mod 16))^,Size mod 16);
564 end;
565 FillChar(TB,Sizeof(TB),$FF);
566 end;
567 end;
569 procedure TwofishDecryptCBC;
571 TB: array[0..15] of byte;
572 i: longint;
573 begin
574 with Data do begin
575 for i:= 1 to (Size div 16) do
576 begin
577 Move(pointer(longint(@InData)+((i-1)*16))^,TB,Sizeof(TB));
578 TwofishDecryptECB(Data,pointer(longint(@InData)+((i-1)*16))^,pointer(longint(@OutData)+((i-1)*16))^);
579 XorBlock(@LB,pointer(longint(@OutData)+((i-1)*16)),pointer(longint(@OutData)+((i-1)*16)),Sizeof(TB));
580 Move(TB,LB,Sizeof(TB));
581 end;
582 if (Size mod 16)<> 0 then
583 begin
584 TwofishEncryptECB(Data,LB,TB);
585 XorBlock(@TB,@pointer(longint(@InData)+Size-(Size mod 16))^,@pointer(longint(@OutData)+Size-(Size mod 16))^,Size mod 16);
586 end;
587 FillChar(TB,Sizeof(TB),$FF);
588 end;
589 end;
591 procedure TwofishEncryptCFB;
593 i: longint;
594 TB: array[0..15] of byte;
595 begin
596 with Data do begin
597 for i:= 0 to Size-1 do
598 begin
599 TwofishEncryptECB(Data,LB,TB);
600 PByteArray(@OutData)^[i]:= PByteArray(@InData)^[i] xor TB[0];
601 Move(LB[1],LB[0],15);
602 LB[15]:= PByteArray(@OutData)^[i];
603 end;
604 end;
605 end;
607 procedure TwofishDecryptCFB;
609 i: longint;
610 TB: array[0..15] of byte;
611 b: byte;
612 begin
613 with Data do begin
614 for i:= 0 to Size-1 do
615 begin
616 b:= PByteArray(@InData)^[i];
617 TwofishEncryptECB(Data,LB,TB);
618 PByteArray(@OutData)^[i]:= PByteArray(@InData)^[i] xor TB[0];
619 Move(LB[1],LB[0],15);
620 LB[15]:= b;
621 end;
622 end;
623 end;
625 procedure PreCompMDS;
627 m1, mx, my: array[0..1] of our_dword;
628 nI: longint;
629 begin
630 for nI:= 0 to 255 do
631 begin
632 m1[0]:= p8x8[0,nI];
633 mx[0]:= Mul_X(m1[0]);
634 my[0]:= Mul_Y(m1[0]);
635 m1[1]:= p8x8[1,nI];
636 mx[1]:= Mul_X(m1[1]);
637 my[1]:= Mul_Y(m1[1]);
638 mds[0,nI]:= (m1[P_00] shl 0) or
639 (mx[p_00] shl 8) or
640 (my[p_00] shl 16) or
641 (my[p_00] shl 24);
642 mds[1,nI]:= (my[p_10] shl 0) or
643 (my[p_10] shl 8) or
644 (mx[p_10] shl 16) or
645 (m1[p_10] shl 24);
646 mds[2,nI]:= (mx[p_20] shl 0) or
647 (my[p_20] shl 8) or
648 (m1[p_20] shl 16) or
649 (my[p_20] shl 24);
650 mds[3,nI]:= (mx[p_30] shl 0) or
651 (m1[p_30] shl 8) or
652 (my[p_30] shl 16) or
653 (mx[p_30] shl 24);
654 end;
655 end;
657 initialization
658 PreCompMDS;
660 end.