Subversion Repositories decoder

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
{Copyright:      Hagen Reddmann HaReddmann at T-Online dot de
2
 Author:         Hagen Reddmann
3
 Remarks:        freeware, but this Copyright must be included
4
 known Problems: none
5
 Version:        5.1,  Part I from Delphi Encryption Compendium  ( DEC Part I)
6
                 Delphi 5
7
 
8
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
9
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
12
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
15
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
16
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
17
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
18
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
}
20
 
21
unit DECCipher;
22
 
23
interface
24
 
25
uses SysUtils, Classes, DECUtil, DECFmt;
26
 
27
{$I VER.INC}
28
 
29
type
30
  TCipher_Null         = class;  // Null cipher, does'nt encrypt, copying only
31
  TCipher_Blowfish     = class;
32
  TCipher_Twofish      = class;  {AES Round 2 Final Candidate}
33
  TCipher_IDEA         = class;
34
  TCipher_Cast256      = class;
35
  TCipher_Mars         = class;  {AES Round 2 Final Candidate}
36
  TCipher_RC4          = class;  {Streamcipher in as Block Cipher}
37
  TCipher_RC6          = class;  {AES Round 2 Final Candidate}
38
  TCipher_Rijndael     = class;  {AES Round 2 Final Candidate}
39
  TCipher_Square       = class;
40
  TCipher_SCOP         = class;  {Streamcipher on Longword, very fast}
41
  TCipher_Sapphire     = class;  {Stream Cipher, eq. Design from german ENIGMA Machine}
42
  TCipher_1DES         = class;  {Single DES  8 byte Blocksize,  8 byte Keysize  56 bits relevant}
43
  TCipher_2DES         = class;  {Triple DES  8 byte Blocksize, 16 byte Keysize 112 bits relevant}
44
  TCipher_3DES         = class;  {Triple DES  8 byte Blocksize, 24 byte Keysize 168 bits relevant}
45
  TCipher_2DDES        = class;  {Triple DES 16 byte Blocksize, 16 byte Keysize 112 bits relevant}
46
  TCipher_3DDES        = class;  {Triple DES 16 byte Blocksize, 24 byte Keysize 168 bits relevant}
47
  TCipher_3TDES        = class;  {Triple DES 24 byte Blocksize, 24 byte Keysize 168 bits relevant}
48
  TCipher_3Way         = class;
49
  TCipher_Cast128      = class;
50
  TCipher_Gost         = class;
51
  TCipher_Misty        = class;
52
  TCipher_NewDES       = class;
53
  TCipher_Q128         = class;
54
  TCipher_RC2          = class;
55
  TCipher_RC5          = class;
56
  TCipher_SAFER        = class;
57
  TCipher_Shark        = class;
58
  TCipher_Skipjack     = class;
59
  TCipher_TEA          = class;
60
  TCipher_TEAN         = class;
61
 
62
  TCipherContext = packed record
63
    KeySize: Integer;            // maximal key size in bytes
64
    BlockSize: Integer;          // mininmal block size in bytes, eg. 1 = Streamcipher
65
    BufferSize: Integer;         // internal buffersize in bytes
66
    UserSize: Integer;           // internal size in bytes of cipher dependend structures
67
    UserSave: Boolean;          
68
  end;
69
 
70
  TCipherState = (csNew, csInitialized, csEncode, csDecode, csPadded, csDone);
71
  TCipherStates = set of TCipherState;
72
{ TCipher.State represents the internal state of processing
73
  csNew         = cipher isn't initialized, .Init() must be called before en/decode
74
  csInitialized = cipher is initialized by .Init(), eg. Keysetup was processed
75
  csEncode      = Encodeing was started, and more chunks can be encoded, but not decoded
76
  csDecode      = Decodeing was started, and more chunks can be decoded, but not encoded
77
  csPadded      = trough En/Decodeing the messagechunks are padded, no more chunks can
78
                  be processed, the cipher is blocked.
79
  csDone        = Processing is finished and Cipher.Done was called. Now new En/Decoding
80
                  can be started without calling .Init() before. csDone is basicaly
81
                  identical to csInitialized, except Cipher.Buffer holds the encrypted
82
                  last state of Cipher.Feedback, thus Cipher.Buffer can be used as C-MAC.}
83
 
84
  TCipherMode = (cmCTSx, cmCBCx, cmCFB8, cmCFBx, cmOFB8, cmOFBx, cmCFS8, cmCFSx, cmECBx);
85
{ cmCTSx = double CBC, with CFS8 padding of truncated final block
86
  cmCBCx = Cipher Block Chainung, with CFB8 padding of truncated final block
87
  cmCFB8 = 8bit Cipher Feedback mode
88
  cmCFBx = CFB on Blocksize of Cipher
89
  cmOFB8 = 8bit Output Feedback mode
90
  cmOFBx = OFB on Blocksize bytes
91
  cmCFS8 = 8Bit CFS, double CFB
92
  cmCFSx = CFS on Blocksize bytes
93
  cmECBx = Electronic Code Book
94
 
95
  Modes cmCBCx, cmCTSx, cmCFBx, cmOFBx, cmCFSx, cmECBx working on Blocks of
96
  Cipher.BufferSize bytes, on Blockcipher that's equal to Cipher.BlockSize.
97
 
98
  Modes cmCFB8, cmOFB8, cmCFS8 work on 8 bit Feedback Shift Registers.
99
 
100
  Modes cmCTSx, cmCFSx, cmCFS8 are prohibitary modes developed by me. These modes
101
  works such as cmCBCx, cmCFBx, cmCFB8 but with double XOR'ing of the inputstream
102
  into Feedback register.
103
 
104
  Mode cmECBx need message padding to a multiple of Cipher.BlockSize and should
105
  be only used in 1byte Streamciphers.
106
 
107
  Modes cmCTSx, cmCBCx need no external padding, because internal the last truncated
108
  block is padded by cmCFS8 or cmCFB8. After padding these Mode can't be used to
109
  process more data. If it needed to process chunks of data then each chunk must
110
  be algined to Cipher.BufferSize bytes.
111
 
112
  Modes cmCFBx,cmCFB8,cmOFBx,cmOFB8,cmCFSx,cmCFS8 need no padding.
113
 
114
}
115
  TDECCipherCodeEvent = procedure(const Source; var Dest; DataSize: Integer) of object;
116
 
117
  TDECCipherClass = class of TDECCipher;
118
 
119
  TDECCipher = class(TDECObject)
120
  private
121
    FState: TCipherState;
122
    FMode: TCipherMode;
123
    FData: PByteArray;
124
    FDataSize: Integer;
125
    procedure SetMode(Value: TCipherMode);
126
  protected
127
    FBufferSize: Integer;
128
    FBufferIndex: Integer;
129
    FUserSize: Integer;
130
    FBuffer: PByteArray;
131
    FVector: PByteArray;
132
    FFeedback: PByteArray;
133
    FUser: Pointer;
134
    FUserSave: Pointer;
135
    procedure CheckState(States: TCipherStates);
136
    procedure DoInit(const Key; Size: Integer); virtual; abstract;
137
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); virtual; abstract;
138
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); virtual; abstract;
139
  public
140
    constructor Create; override;
141
    destructor Destroy; override;
142
 
143
    class function Context: TCipherContext; virtual; abstract;
144
 
145
    procedure Init(const Key; Size: Integer; const IVector; IVectorSize: Integer; IFiller: Byte = $FF); overload;
146
    procedure Init(const Key: Binary; const IVector: Binary = ''; IFiller: Byte = $FF); overload;
147
    procedure Done;
148
    procedure Protect; virtual;
149
 
150
    procedure Encode(const Source; var Dest; DataSize: Integer);
151
    procedure Decode(const Source; var Dest; DataSize: Integer);
152
 
153
    function  EncodeBinary(const Source: Binary; Format: TDECFormatClass = nil): Binary;
154
    function  DecodeBinary(const Source: Binary; Format: TDECFormatClass = nil): Binary;
155
    procedure EncodeFile(const Source, Dest: String; const Progress: IDECProgress = nil);
156
    procedure DecodeFile(const Source, Dest: String; const Progress: IDECProgress = nil);
157
    procedure EncodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress = nil);
158
    procedure DecodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress = nil);
159
 
160
    function  CalcMAC(Format: TDECFormatClass = nil): Binary;
161
 
162
    property InitVectorSize: Integer read FBufferSize;
163
    property InitVector: PByteArray read FVector; // buffer size bytes
164
    property Feedback: PByteArray read FFeedback; // buffer size bytes
165
 
166
    property State: TCipherState read FState;
167
  published
168
    property Mode: TCipherMode read FMode write SetMode;
169
  end;
170
 
171
  TCipher_Null = class(TDECCipher)
172
  protected
173
    procedure DoInit(const Key; Size: Integer); override;
174
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
175
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
176
  public
177
    class function Context: TCipherContext; override;
178
  end;
179
 
180
  TCipher_Blowfish = class(TDECCipher)
181
  protected
182
    procedure DoInit(const Key; Size: Integer); override;
183
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
184
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
185
  public
186
    class function Context: TCipherContext; override;
187
  end;
188
 
189
  TCipher_Twofish = class(TDECCipher)
190
  protected
191
    procedure DoInit(const Key; Size: Integer); override;
192
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
193
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
194
  public
195
    class function Context: TCipherContext; override;
196
  end;
197
 
198
  TCipher_IDEA = class(TDECCipher) {International Data Encryption Algorithm }
199
  protected
200
    procedure DoInit(const Key; Size: Integer); override;
201
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
202
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
203
  public
204
    class function Context: TCipherContext; override;
205
  end;
206
 
207
  TCipher_Cast256 = class(TDECCipher)
208
  protected
209
    procedure DoInit(const Key; Size: Integer); override;
210
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
211
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
212
  public
213
    class function Context: TCipherContext; override;
214
  end;
215
 
216
  TCipher_Mars = class(TDECCipher)
217
  protected
218
    procedure DoInit(const Key; Size: Integer); override;
219
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
220
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
221
  public
222
    class function Context: TCipherContext; override;
223
  end;
224
 
225
  TCipher_RC4 = class(TDECCipher)
226
  protected
227
    procedure DoInit(const Key; Size: Integer); override;
228
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
229
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
230
  public
231
    class function Context: TCipherContext; override;
232
  end;
233
 
234
  TCipher_RC6 = class(TDECCipher)
235
  private
236
    FRounds: Integer; {16-24, default 20}
237
    procedure SetRounds(Value: Integer);
238
  protected
239
    procedure DoInit(const Key; Size: Integer); override;
240
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
241
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
242
  public
243
    class function Context: TCipherContext; override;
244
  published
245
    property Rounds: Integer read FRounds write SetRounds;
246
  end;
247
 
248
  TCipher_Rijndael = class(TDECCipher)
249
  private
250
    FRounds: Integer;
251
  protected
252
    procedure DoInit(const Key; Size: Integer); override;
253
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
254
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
255
  public
256
    class function Context: TCipherContext; override;
257
  published
258
    property Rounds: Integer read FRounds;
259
  end;
260
 
261
  TCipher_Square = class(TDECCipher)
262
  protected
263
    procedure DoInit(const Key; Size: Integer); override;
264
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
265
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
266
  public
267
    class function Context: TCipherContext; override;
268
  end;
269
 
270
  TCipher_SCOP = class(TDECCipher) {Stream Cipher in Blockmode}
271
  protected
272
    procedure DoInit(const Key; Size: Integer); override;
273
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
274
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
275
  public
276
    class function Context: TCipherContext; override;
277
  end;
278
 
279
  TCipher_Sapphire = class(TDECCipher)
280
  protected
281
    procedure DoInit(const Key; Size: Integer); override;
282
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
283
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
284
  public
285
    class function Context: TCipherContext; override;
286
  end;
287
 
288
  TCipher_1DES = class(TDECCipher)
289
  protected
290
    procedure DoInitKey(const Data: array of Byte; Key: PLongArray; Reverse: Boolean);
291
    procedure DoInit(const Key; Size: Integer); override;
292
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
293
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
294
  public
295
    class function Context: TCipherContext; override;
296
  end;
297
 
298
  TCipher_2DES = class(TCipher_1DES)
299
  protected
300
    procedure DoInit(const Key; Size: Integer); override;
301
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
302
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
303
  public
304
    class function Context: TCipherContext; override;
305
  end;
306
 
307
  TCipher_3DES = class(TCipher_1DES)
308
  protected
309
    procedure DoInit(const Key; Size: Integer); override;
310
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
311
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
312
  public
313
    class function Context: TCipherContext; override;
314
  end;
315
 
316
  TCipher_2DDES = class(TCipher_2DES)
317
  protected
318
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
319
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
320
  public
321
    class function Context: TCipherContext; override;
322
  end;
323
 
324
  TCipher_3DDES = class(TCipher_3DES)
325
  protected
326
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
327
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
328
  public
329
    class function Context: TCipherContext; override;
330
  end;
331
 
332
  TCipher_3TDES = class(TCipher_3DES)
333
  protected
334
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
335
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
336
  public
337
    class function Context: TCipherContext; override;
338
  end;
339
 
340
  TCipher_3Way = class(TDECCipher)
341
  protected
342
    procedure DoInit(const Key; Size: Integer); override;
343
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
344
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
345
  public
346
    class function Context: TCipherContext; override;
347
  end;
348
 
349
  TCipher_Cast128 = class(TDECCipher) {Carlisle Adams and Stafford Tavares }
350
  private
351
    FRounds: Integer;
352
    procedure SetRounds(Value: Integer);
353
  protected
354
    procedure DoInit(const Key; Size: Integer); override;
355
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
356
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
357
  public
358
    class function Context: TCipherContext; override;
359
  published
360
    property Rounds: Integer read FRounds write SetRounds;
361
  end;
362
 
363
  TCipher_Gost = class(TDECCipher) {russian Cipher}
364
  protected
365
    procedure DoInit(const Key; Size: Integer); override;
366
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
367
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
368
  public
369
    class function Context: TCipherContext; override;
370
  end;
371
 
372
  TCipher_Misty = class(TDECCipher)
373
  protected
374
    procedure DoInit(const Key; Size: Integer); override;
375
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
376
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
377
  public
378
    class function Context: TCipherContext; override;
379
  end;
380
 
381
{ This algorithm resembles the Data Encryption Standard (DES), but is easier
382
  to implement in software and is supposed to be more secure.
383
  It is not to be confused with another algorithm--known by the
384
  same name--which is simply DES without the initial and final
385
  permutations.  The NewDES here is a completely different algorithm.}
386
 
387
  TCipher_NewDES = class(TDECCipher)
388
  protected
389
    procedure DoInit(const Key; Size: Integer); override;
390
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
391
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
392
  public
393
    class function Context: TCipherContext; override;
394
  end;
395
 
396
  TCipher_Q128 = class(TDECCipher)
397
  protected
398
    procedure DoInit(const Key; Size: Integer); override;
399
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
400
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
401
  public
402
    class function Context: TCipherContext; override;
403
  end;
404
 
405
  TCipher_RC2 = class(TDECCipher)
406
  protected
407
    procedure DoInit(const Key; Size: Integer); override;
408
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
409
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
410
  public
411
    class function Context: TCipherContext; override;
412
  end;
413
 
414
  TCipher_RC5 = class(TDECCipher)
415
  private
416
    FRounds: Integer; {8-16, default 12}
417
    procedure SetRounds(Value: Integer);
418
  protected
419
    procedure DoInit(const Key; Size: Integer); override;
420
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
421
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
422
  public
423
    class function Context: TCipherContext; override;
424
  published
425
    property Rounds: Integer read FRounds write SetRounds;
426
  end;
427
 
428
  TSAFERVersion = (svSK128, svSK64, svSK40, svK128, svK64, svK40);
429
{svK40       SAFER K-40    Keysize is 40bit  ->  5 Byte
430
 svK64       SAFER K-64    Keysize is 64bit  ->  8 Byte
431
 svK128      SAFER K-128   KeySize is 128bit -> 16 Byte
432
 svSK40      SAFER SK-40   stronger Version from K-40 with better Keyscheduling
433
 svSK64      SAFER SK-64   stronger Version from K-64 with better Keyscheduling
434
 svSK128     SAFER SK-128  stronger Version from K-128 with better Keyscheduling}
435
 
436
  TCipher_SAFER = class(TDECCipher) {SAFER = Secure And Fast Encryption Routine}
437
  private
438
    FRounds: Integer;
439
    FVersion: TSAFERVersion;
440
    procedure SetRounds(Value: Integer);
441
    procedure SetVersion(Value: TSAFERVersion);
442
  protected
443
    procedure DoInit(const Key; Size: Integer); override;
444
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
445
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
446
  public
447
    class function Context: TCipherContext; override;
448
  published
449
    property Rounds: Integer read FRounds write SetRounds;
450
    property Version: TSAFERVersion read FVersion write SetVersion;
451
  end;
452
 
453
  TCipher_Shark = class(TDECCipher)
454
  protected
455
    procedure DoInit(const Key; Size: Integer); override;
456
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
457
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
458
  public
459
    class function Context: TCipherContext; override;
460
  end;
461
 
462
  TCipher_Skipjack = class(TDECCipher)
463
  protected
464
    procedure DoInit(const Key; Size: Integer); override;
465
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
466
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
467
  public
468
    class function Context: TCipherContext; override;
469
  end;
470
 
471
  TCipher_TEA = class(TDECCipher) {Tiny Encryption Algorithm}
472
  private
473
    FRounds: Integer; {16 - 32, default 16 is sufficient, 32 is ample}
474
    procedure SetRounds(Value: Integer);
475
  protected
476
    procedure DoInit(const Key; Size: Integer); override;
477
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
478
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
479
  public
480
    class function Context: TCipherContext; override;
481
  published
482
    property Rounds: Integer read FRounds write SetRounds;
483
  end;
484
 
485
  TCipher_TEAN = class(TCipher_TEA) {Tiny Encryption Algorithm, extended Version}
486
  protected
487
    procedure DoEncode(Source, Dest: Pointer; Size: Integer); override;
488
    procedure DoDecode(Source, Dest: Pointer; Size: Integer); override;
489
  end;
490
 
491
function  ValidCipher(CipherClass: TDECCipherClass = nil): TDECCipherClass;
492
function  CipherByName(const Name: String): TDECCipherClass;
493
function  CipherByIdentity(Identity: LongWord): TDECCipherClass;
494
procedure SetDefaultCipherClass(CipherClass: TDECCipherClass = nil);
495
 
496
var
497
  StreamBufferSize: Integer = 8192;
498
 
499
implementation
500
 
501
uses TypInfo, DECData;
502
 
503
resourcestring
504
  sAlreadyPadded        = 'Cipher have already padded, can not process message';
505
  sInvalidState         = 'Cipher is not in valid state for this action';
506
  sInvalidMessageLength = 'Messagelength for %s must be a multiple of %d bytes';
507
  sKeyMaterialToLarge   = 'Keymaterial is to large as can be used, security issue';
508
  sIVMaterialToLarge    = 'Initvector is to large as can be used, security issue';
509
  sInvalidMACMode       = 'Invalid Cipher mode to compute MAC';
510
  sCipherNoDefault      = 'No default cipher are registered';
511
 
512
var
513
  FDefaultCipherClass: TDECCipherClass = nil;
514
 
515
function ValidCipher(CipherClass: TDECCipherClass): TDECCipherClass;
516
begin
517
  if CipherClass <> nil then Result := CipherClass
518
    else Result := FDefaultCipherClass;
519
  if Result = nil then raise EDECException.Create(sCipherNoDefault);
520
end;
521
 
522
function CipherByName(const Name: String): TDECCipherClass;
523
begin
524
  Result := TDECCipherClass(DECClassByName(Name, TDECCipher));
525
end;
526
 
527
function CipherByIdentity(Identity: LongWord): TDECCipherClass;
528
begin
529
  Result := TDECCipherClass(DECClassByIdentity(Identity, TDECCipher));
530
end;
531
 
532
procedure SetDefaultCipherClass(CipherClass: TDECCipherClass);
533
begin
534
  if CipherClass <> nil then CipherClass.Register;
535
  FDefaultCipherClass := CipherClass;
536
end;
537
 
538
procedure TDECCipher.SetMode(Value: TCipherMode);
539
begin
540
  if Value <> FMode then
541
  begin
542
    if not (FState in [csNew, csInitialized, csDone]) then Done;
543
    FMode := Value;
544
  end;
545
end;
546
 
547
procedure TDECCipher.CheckState(States: TCipherStates);
548
var
549
  S: String;
550
begin
551
  if not (FState in States) then
552
  begin
553
    if FState = csPadded then S := sAlreadyPadded
554
      else S := sInvalidState;
555
    raise EDECException.Create(S);
556
  end;
557
end;
558
 
559
constructor TDECCipher.Create;
560
var
561
  MustUserSaved: Boolean;
562
begin
563
  inherited Create;
564
  with Context do
565
  begin
566
    FBufferSize := BufferSize;
567
    FUserSize := UserSize;
568
    MustUserSaved := UserSave;
569
  end;
570
  FDataSize := FBufferSize * 3 + FUserSize;
571
  if MustUserSaved then Inc(FDataSize, FUserSize);
572
  ReallocMem(FData, FDataSize);
573
  FVector := @FData[0];
574
  FFeedback := @FVector[FBufferSize];
575
  FBuffer := @FFeedback[FBufferSize];
576
  FUser := @FBuffer[FBufferSize];
577
  if MustUserSaved then FUserSave := @PByteArray(FUser)[FUserSize]
578
    else FUserSave := nil;
579
  Protect;
580
end;
581
 
582
destructor TDECCipher.Destroy;
583
begin
584
  Protect;
585
  ReallocMem(FData, 0);
586
  FVector := nil;
587
  FFeedback := nil;
588
  FBuffer := nil;
589
  FUser := nil;
590
  FUserSave := nil;
591
  inherited Destroy;
592
end;
593
 
594
procedure TDECCipher.Init(const Key; Size: Integer; const IVector; IVectorSize: Integer; IFiller: Byte);
595
begin
596
  Protect;
597
 
598
  if Size > Context.KeySize then
599
    raise EDECException.Create(sKeyMaterialToLarge);
600
  if IVectorSize > FBufferSize then
601
    raise EDECException.Create(sIVMaterialToLarge);
602
 
603
  DoInit(Key, Size);
604
  if FUserSave <> nil then
605
    Move(FUser^, FUserSave^, FUserSize);
606
 
607
  FillChar(FVector^, FBufferSize, IFiller);
608
  if IVectorSize = 0 then
609
  begin
610
    DoEncode(FVector, FVector, FBufferSize);
611
    if FUserSave <> nil then Move(FUserSave^, FUser^, FUserSize);
612
  end else Move(IVector, FVector^, IVectorSize);
613
  Move(FVector^, FFeedback^, FBufferSize);
614
  FState := csInitialized;
615
end;
616
 
617
procedure TDECCipher.Init(const Key: Binary; const IVector: Binary; IFiller: Byte);
618
begin
619
  Init(Key[1], Length(Key), IVector[1], Length(IVector), IFiller);
620
end;
621
 
622
procedure TDECCipher.Done;
623
begin
624
  if FState <> csDone then
625
  begin
626
    FState := csDone;
627
    FBufferIndex := 0;
628
    DoEncode(FFeedback, FBuffer, FBufferSize);
629
    Move(FVector^, FFeedback^, FBufferSize);
630
    if FUserSave <> nil then
631
      Move(FUserSave^, FUser^, FUserSize);
632
  end;
633
end;
634
 
635
procedure TDECCipher.Protect;
636
begin
637
  FState := csNew;
638
  ProtectBuffer(FData[0], FDataSize);
639
end;
640
 
641
procedure InvalidMessageLength(Cipher: TDECCipher);
642
begin
643
  with Cipher do
644
    raise EDECException.CreateFmt(sInvalidMessageLength,
645
      [TypInfo.GetEnumName(TypeInfo(TCipherMode), Integer(FMode)), Context.BlockSize]);
646
end;
647
 
648
procedure TDECCipher.Encode(const Source; var Dest; DataSize: Integer);
649
 
650
  procedure EncodeECBx(S,D: PByteArray; Size: Integer);
651
  var
652
    I: Integer;
653
  begin
654
    if Context.BlockSize = 1 then
655
    begin
656
      DoEncode(S, D, Size);
657
      FState := csEncode;
658
    end else
659
    begin
660
      Dec(Size, FBufferSize);
661
      I := 0;
662
      while I <= Size do
663
      begin
664
        DoEncode(@S[I], @D[I], FBufferSize);
665
        Inc(I, FBufferSize);
666
      end;
667
      Dec(Size, I - FBufferSize);
668
      if Size > 0 then
669
        if Size mod Context.BlockSize = 0 then
670
        begin
671
          DoEncode(@S[I], @D[I], Size);
672
          FState := csEncode;
673
        end else
674
        begin
675
          FState := csPadded;
676
          InvalidMessageLength(Self);
677
        end;
678
    end;
679
  end;
680
 
681
  procedure EncodeCFB8(S,D: PByteArray; Size: Integer);
682
  // CFB-8
683
  var
684
    I: Integer;
685
  begin
686
    I := 0;
687
    while I < Size do
688
    begin
689
      DoEncode(FFeedback, FBuffer, FBufferSize);
690
      Move(FFeedback[1], FFeedback[0], FBufferSize -1);
691
      D[I] := S[I] xor FBuffer[0];
692
      FFeedback[FBufferSize -1] := D[I];
693
      Inc(I);
694
    end;
695
    FState := csEncode;
696
  end;
697
 
698
  procedure EncodeOFB8(S,D: PByteArray; Size: Integer);
699
  var
700
    I: Integer;
701
  begin
702
    I := 0;
703
    while I < Size do
704
    begin
705
      DoEncode(FFeedback, FBuffer, FBufferSize);
706
      Move(FFeedback[1], FFeedback[0], FBufferSize -1);
707
      FFeedback[FBufferSize -1] := FBuffer[0];
708
      D[I] := S[I] xor FBuffer[0];
709
      Inc(I);
710
    end;
711
    FState := csEncode;
712
  end;
713
 
714
  procedure EncodeCFS8(S,D: PByteArray; Size: Integer);
715
  // CFS-8, CTS as CFB
716
  var
717
    I: Integer;
718
  begin
719
    I := 0;
720
    while I < Size do
721
    begin
722
      DoEncode(FFeedback, FBuffer, FBufferSize);
723
      D[I] := S[I] xor FBuffer[0];
724
      Move(FFeedback[1], FFeedback[0], FBufferSize -1);
725
      FFeedback[FBufferSize -1] := FFeedback[FBufferSize -1] xor D[I];
726
      Inc(I);
727
    end;
728
    FState := csEncode;
729
  end;
730
 
731
  procedure EncodeCFBx(S,D: PByteArray; Size: Integer);
732
  // CFB-BlockSize
733
  var
734
    I: Integer;
735
    F: PByteArray;
736
  begin
737
    FState := csEncode;
738
    if FBufferIndex > 0 then
739
    begin
740
      I := FBufferSize - FBufferIndex;
741
      if I > Size then I := Size;
742
      XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
743
      Move(D[0], FFeedback[FBufferIndex], I);
744
      Inc(FBufferIndex, I);
745
      if FBufferIndex < FBufferSize then Exit;
746
      Dec(Size, I);
747
      S := @S[I];
748
      D := @D[I];
749
      FBufferIndex := 0
750
    end;
751
    Dec(Size, FBufferSize);
752
    F := FFeedback;
753
    I := 0;
754
    while I < Size do
755
    begin
756
      DoEncode(F, FBuffer, FBufferSize);
757
      XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
758
      F := @D[I];
759
      Inc(I, FBufferSize);
760
    end;
761
    if F <> FFeedback then
762
      Move(F^, FFeedback^, FBufferSize);
763
    Dec(Size, I - FBufferSize);
764
    if Size > 0 then
765
    begin
766
      DoEncode(FFeedback, FBuffer, FBufferSize);
767
      XORBuffers(S[I], FBuffer[0], Size, D[I]);
768
      Move(D[I], FFeedback[0], Size);
769
      FBufferIndex := Size;
770
    end;
771
  end;
772
 
773
  procedure EncodeOFBx(S,D: PByteArray; Size: Integer);
774
  // OFB-BlockSize
775
  var
776
    I: Integer;
777
  begin
778
    FState := csEncode;
779
    if FBufferIndex > 0 then
780
    begin
781
      I := FBufferSize - FBufferIndex;
782
      if I > Size then I := Size;
783
      XORBuffers(S[0], FFeedback[FBufferIndex], I, D[0]);
784
      Inc(FBufferIndex, I);
785
      if FBufferIndex < FBufferSize then Exit;
786
      Dec(Size, I);
787
      S := @S[I];
788
      D := @D[I];
789
      FBufferIndex := 0
790
    end;
791
    Dec(Size, FBufferSize);
792
    I := 0;
793
    while I < Size do
794
    begin
795
      DoEncode(FFeedback, FFeedback, FBufferSize);
796
      XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]);
797
      Inc(I, FBufferSize);
798
    end;
799
    Dec(Size, I - FBufferSize);
800
    if Size > 0 then
801
    begin
802
      DoEncode(FFeedback, FFeedback, FBufferSize);
803
      XORBuffers(S[I], FFeedback[0], Size, D[I]);
804
      FBufferIndex := Size;
805
    end;
806
  end;
807
 
808
  procedure EncodeCFSx(S,D: PByteArray; Size: Integer);
809
  // CFS-BlockSize
810
  var
811
    I: Integer;
812
  begin
813
    FState := csEncode;
814
    if FBufferIndex > 0 then
815
    begin
816
      I := FBufferSize - FBufferIndex;
817
      if I > Size then I := Size;
818
      XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
819
      XORBuffers(D[0], FFeedback[FBufferIndex], I, FFeedback[FBufferIndex]);
820
      Inc(FBufferIndex, I);
821
      if FBufferIndex < FBufferSize then Exit;
822
      Dec(Size, I);
823
      S := @S[I];
824
      D := @D[I];
825
      FBufferIndex := 0
826
    end;
827
    Dec(Size, FBufferSize);
828
    I := 0;
829
    while I < Size do
830
    begin
831
      DoEncode(FFeedback, FBuffer, FBufferSize);
832
      XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
833
      XORBuffers(D[I], FFeedback[0], FBufferSize, FFeedback[0]);
834
      Inc(I, FBufferSize);
835
    end;
836
    Dec(Size, I - FBufferSize);
837
    if Size > 0 then
838
    begin
839
      DoEncode(FFeedback, FBuffer, FBufferSize);
840
      XORBuffers(S[I], FBuffer[0], Size, D[I]);
841
      XORBuffers(D[I], FFeedback[0], Size, FFeedback[0]);
842
      FBufferIndex := Size;
843
    end;
844
  end;
845
 
846
  procedure EncodeCBCx(S,D: PByteArray; Size: Integer);
847
  var
848
    F: PByteArray;
849
    I: Integer;
850
  begin
851
    Dec(Size, FBufferSize);
852
    F := FFeedback;
853
    I := 0;
854
    while I <= Size do
855
    begin
856
      XORBuffers(S[I], F[0], FBufferSize, D[I]);
857
      F := @D[I];
858
      DoEncode(F, F, FBufferSize);
859
      Inc(I, FBufferSize);
860
    end;
861
    if F <> FFeedback then
862
      Move(F[0], FFeedback[0], FBufferSize);
863
    Dec(Size, I - FBufferSize);
864
    if Size > 0 then
865
    begin  // padding
866
      EncodeCFB8(@S[I], @D[I], Size);
867
      FState := csPadded;
868
    end else FState := csEncode;
869
  end;
870
 
871
  procedure EncodeCTSx(S,D: PByteArray; Size: Integer);
872
  var
873
    I: Integer;
874
  begin
875
    Dec(Size, FBufferSize);
876
    I := 0;
877
    while I <= Size do
878
    begin
879
      XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]);
880
      DoEncode(@D[I], @D[I], FBufferSize);
881
      XORBuffers(D[I], FFeedback[0], FBufferSize, FFeedback[0]);
882
      Inc(I, FBufferSize);
883
     end;
884
     Dec(Size, I - FBufferSize);
885
     if Size > 0 then
886
     begin // padding
887
       EncodeCFS8(@S[I], @D[I], Size);
888
       FState := csPadded;
889
     end else FState := csEncode;
890
  end;
891
 
892
begin
893
  CheckState([csInitialized, csEncode, csDone]);
894
  case FMode of
895
    cmECBx: EncodeECBx(@Source, @Dest, DataSize);
896
    cmCBCx: EncodeCBCx(@Source, @Dest, DataSize);
897
    cmCTSx: EncodeCTSx(@Source, @Dest, DataSize);
898
    cmCFB8: EncodeCFB8(@Source, @Dest, DataSize);
899
    cmCFBx: EncodeCFBx(@Source, @Dest, DataSize);
900
    cmOFB8: EncodeOFB8(@Source, @Dest, DataSize);
901
    cmOFBx: EncodeOFBx(@Source, @Dest, DataSize);
902
    cmCFS8: EncodeCFS8(@Source, @Dest, DataSize);
903
    cmCFSx: EncodeCFSx(@Source, @Dest, DataSize);
904
  end;
905
end;
906
 
907
procedure TDECCipher.Decode(const Source; var Dest; DataSize: Integer);
908
 
909
  procedure DecodeECBx(S,D: PByteArray; Size: Integer);
910
  var
911
    I: Integer;
912
  begin
913
    if Context.BlockSize = 1 then
914
    begin
915
      DoDecode(S, D, Size);
916
      FState := csDecode;
917
    end else
918
    begin
919
      Dec(Size, FBufferSize);
920
      I := 0;
921
      while I <= Size do
922
      begin
923
        DoDecode(@S[I], @D[I], FBufferSize);
924
        Inc(I, FBufferSize);
925
      end;
926
      Dec(Size, I - FBufferSize);
927
      if Size > 0 then
928
        if Size mod Context.BlockSize = 0 then
929
        begin
930
          DoDecode(@S[I], @D[I], Size);
931
          FState := csDecode;
932
        end else
933
        begin
934
          FState := csPadded;
935
          InvalidMessageLength(Self);
936
        end;
937
    end;
938
  end;
939
 
940
  procedure DecodeCFB8(S,D: PByteArray; Size: Integer);
941
  // CFB-8
942
  var
943
    I: Integer;
944
  begin
945
    I := 0;
946
    while I < Size do
947
    begin
948
      DoEncode(FFeedback, FBuffer, FBufferSize);
949
      Move(FFeedback[1], FFeedback[0], FBufferSize -1);
950
      FFeedback[FBufferSize -1] := S[I];
951
      D[I] := S[I] xor FBuffer[0];
952
      Inc(I);
953
    end;
954
    FState := csDecode;
955
  end;
956
 
957
  procedure DecodeOFB8(S,D: PByteArray; Size: Integer);
958
  // same as EncodeOFB
959
  var
960
    I: Integer;
961
  begin
962
    I := 0;
963
    while I < Size do
964
    begin
965
      DoEncode(FFeedback, FBuffer, FBufferSize);
966
      Move(FFeedback[1], FFeedback[0], FBufferSize -1);
967
      FFeedback[FBufferSize -1] := FBuffer[0];
968
      D[I] := S[I] xor FBuffer[0];
969
      Inc(I);
970
    end;
971
    FState := csDecode;
972
  end;
973
 
974
  procedure DecodeCFS8(S,D: PByteArray; Size: Integer);
975
  var
976
    I: Integer;
977
  begin
978
    I := 0;
979
    while I < Size do
980
    begin
981
      DoEncode(FFeedback, FBuffer, FBufferSize);
982
      Move(FFeedback[1], FFeedback[0], FBufferSize -1);
983
      FFeedback[FBufferSize -1] := FFeedback[FBufferSize -1] xor S[I];
984
      D[I] := S[I] xor FBuffer[0];
985
      Inc(I);
986
    end;
987
    FState := csDecode;
988
  end;
989
 
990
  procedure DecodeCFBx(S,D: PByteArray; Size: Integer);
991
  // CFB-BlockSize
992
  var
993
    I: Integer;
994
    F: PByteArray;
995
  begin
996
    FState := csDecode;
997
    if FBufferIndex > 0 then
998
    begin // remain bytes of last decode
999
      I := FBufferSize - FBufferIndex;
1000
      if I > Size then I := Size;
1001
      Move(S[0], FFeedback[FBufferIndex], I);
1002
      XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
1003
      Inc(FBufferIndex, I);
1004
      if FBufferIndex < FBufferSize then Exit;
1005
      Dec(Size, I);
1006
      S := @S[I];
1007
      D := @D[I];
1008
      FBufferIndex := 0
1009
    end;
1010
  // process chunks of FBufferSize bytes
1011
    Dec(Size, FBufferSize);
1012
    I := 0;
1013
    if S <> D then
1014
    begin
1015
      F := FFeedback;
1016
      while I < Size do
1017
      begin
1018
        DoEncode(F, FBuffer, FBufferSize);
1019
        XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
1020
        F := @S[I];
1021
        Inc(I, FBufferSize);
1022
      end;
1023
      if F <> FFeedback then
1024
        Move(F^, FFeedback^, FBufferSize);
1025
    end else
1026
      while I < Size do
1027
      begin
1028
        DoEncode(FFeedback, FBuffer, FBufferSize);
1029
        Move(S[I], FFeedback[0], FBufferSize);
1030
        XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
1031
        Inc(I, FBufferSize);
1032
      end;
1033
    Dec(Size, I - FBufferSize);
1034
    if Size > 0 then
1035
    begin // remain bytes
1036
      DoEncode(FFeedback, FBuffer, FBufferSize);
1037
      Move(S[I], FFeedback[0], Size);
1038
      XORBuffers(S[I], FBuffer[0], Size, D[I]);
1039
      FBufferIndex := Size;
1040
    end;
1041
  end;
1042
 
1043
  procedure DecodeOFBx(S,D: PByteArray; Size: Integer);
1044
  // OFB-BlockSize, same as EncodeOFBx
1045
  var
1046
    I: Integer;
1047
  begin
1048
    FState := csDecode;
1049
    if FBufferIndex > 0 then
1050
    begin
1051
      I := FBufferSize - FBufferIndex;
1052
      if I > Size then I := Size;
1053
      XORBuffers(S[0], FFeedback[FBufferIndex], I, D[0]);
1054
      Inc(FBufferIndex, I);
1055
      if FBufferIndex < FBufferSize then Exit;
1056
      Dec(Size, I);
1057
      S := @S[I];
1058
      D := @D[I];
1059
      FBufferIndex := 0
1060
    end;
1061
    Dec(Size, FBufferSize);
1062
    I := 0;
1063
    while I < Size do
1064
    begin
1065
      DoEncode(FFeedback, FFeedback, FBufferSize);
1066
      XORBuffers(S[I], FFeedback[0], FBufferSize, D[I]);
1067
      Inc(I, FBufferSize);
1068
    end;
1069
    Dec(Size, I - FBufferSize);
1070
    if Size > 0 then
1071
    begin
1072
      DoEncode(FFeedback, FFeedback, FBufferSize);
1073
      XORBuffers(S[I], FFeedback[0], Size, D[I]);
1074
      FBufferIndex := Size;
1075
    end;
1076
  end;
1077
 
1078
  procedure DecodeCFSx(S,D: PByteArray; Size: Integer);
1079
  // CFS-BlockSize
1080
  var
1081
    I: Integer;
1082
  begin
1083
    FState := csDecode;
1084
    if FBufferIndex > 0 then
1085
    begin // remain bytes of last decode
1086
      I := FBufferSize - FBufferIndex;
1087
      if I > Size then I := Size;
1088
      XORBuffers(S[0], FFeedback[FBufferIndex], I, FFeedback[FBufferIndex]);
1089
      XORBuffers(S[0], FBuffer[FBufferIndex], I, D[0]);
1090
      Inc(FBufferIndex, I);
1091
      if FBufferIndex < FBufferSize then Exit;
1092
      Dec(Size, I);
1093
      S := @S[I];
1094
      D := @D[I];
1095
      FBufferIndex := 0
1096
    end;
1097
  // process chunks of FBufferSize bytes
1098
    Dec(Size, FBufferSize);
1099
    I := 0;
1100
    while I < Size do
1101
    begin
1102
      DoEncode(FFeedback, FBuffer, FBufferSize);
1103
      XORBuffers(S[I], FFeedback[0], FBufferSize, FFeedback[0]);
1104
      XORBuffers(S[I], FBuffer[0], FBufferSize, D[I]);
1105
      Inc(I, FBufferSize);
1106
    end;
1107
    Dec(Size, I - FBufferSize);
1108
    if Size > 0 then
1109
    begin // remain bytes
1110
      DoEncode(FFeedback, FBuffer, FBufferSize);
1111
      XORBuffers(S[I], FFeedback[0], Size, FFeedback[0]);
1112
      XORBuffers(S[I], FBuffer[0], Size, D[I]);
1113
      FBufferIndex := Size;
1114
    end;
1115
  end;
1116
 
1117
  procedure DecodeCBCx(S,D: PByteArray; Size: Integer);
1118
  var
1119
    I: Integer;
1120
    F,B,T: PByteArray;
1121
  begin
1122
    Dec(Size, FBufferSize);
1123
    F := FFeedback;
1124
    I := 0;
1125
    if S = D then
1126
    begin
1127
      B := FBuffer;
1128
      while I <= Size do
1129
      begin
1130
        Move(S[I], B[0], FBufferSize);
1131
        DoDecode(@S[I], @S[I], FBufferSize);
1132
        XORBuffers(S[I], F[0], FBufferSize, S[I]);
1133
        T := F;
1134
        F := B;
1135
        B := T;
1136
        Inc(I, FBufferSize);
1137
      end;
1138
    end else
1139
      while I <= Size do
1140
      begin
1141
        DoDecode(@S[I], @D[I], FBufferSize);
1142
        XORBuffers(F[0], D[I], FBufferSize, D[I]);
1143
        F := @S[I];
1144
        Inc(I, FBufferSize);
1145
      end;
1146
    if F <> FFeedback then
1147
      Move(F[0], FFeedback[0], FBufferSize);
1148
    Dec(Size, I - FBufferSize);
1149
    if Size > 0 then
1150
    begin
1151
      DecodeCFB8(@S[I], @D[I], Size);
1152
      FState := csPadded;
1153
    end else FState := csDecode;
1154
  end;
1155
 
1156
  procedure DecodeCTSx(S,D: PByteArray; Size: Integer);
1157
  var
1158
    I: Integer;
1159
    F,B,T: PByteArray;
1160
  begin
1161
    Dec(Size, FBufferSize);
1162
    F := FFeedback;
1163
    B := FBuffer;
1164
    I := 0;
1165
    while I <= Size do
1166
    begin
1167
      XORBuffers(S[I], F[0], FBufferSize, B[0]);
1168
      DoDecode(@S[I], @D[I], FBufferSize);
1169
      XORBuffers(D[I], F[0], FBufferSize, D[I]);
1170
      T := B;
1171
      B := F;
1172
      F := T;
1173
      Inc(I, FBufferSize);
1174
    end;
1175
    if F <> FFeedback then
1176
      Move(F[0], FFeedback[0], FBufferSize);
1177
    Dec(Size, I - FBufferSize);
1178
    if Size > 0 then
1179
    begin
1180
      DecodeCFS8(@S[I], @D[I], Size);
1181
      FState := csPadded;
1182
    end else FState := csDecode;
1183
  end;
1184
 
1185
begin
1186
  CheckState([csInitialized, csDecode, csDone]);
1187
  case FMode of
1188
    cmECBx: DecodeECBx(@Source, @Dest, DataSize);
1189
    cmCBCx: DecodeCBCx(@Source, @Dest, DataSize);
1190
    cmCTSx: DecodeCTSx(@Source, @Dest, DataSize);
1191
    cmCFB8: DecodeCFB8(@Source, @Dest, DataSize);
1192
    cmCFBx: DecodeCFBx(@Source, @Dest, DataSize);
1193
    cmOFB8: DecodeOFB8(@Source, @Dest, DataSize);
1194
    cmOFBx: DecodeOFBx(@Source, @Dest, DataSize);
1195
    cmCFS8: DecodeCFS8(@Source, @Dest, DataSize);
1196
    cmCFSx: DecodeCFSx(@Source, @Dest, DataSize);
1197
  end;
1198
end;
1199
 
1200
function TDECCipher.EncodeBinary(const Source: Binary; Format: TDECFormatClass): Binary;
1201
begin
1202
  SetLength(Result, Length(Source));
1203
  Encode(Source[1], Result[1], Length(Source));
1204
  Result := ValidFormat(Format).Encode(Result);
1205
end;
1206
 
1207
function TDECCipher.DecodeBinary(const Source: Binary; Format: TDECFormatClass): Binary;
1208
begin
1209
  Result := ValidFormat(Format).Decode(Source);
1210
  Decode(Result[1], Result[1], Length(Result));
1211
end;
1212
 
1213
procedure DoCodeStream(Source,Dest: TStream; Size: Int64; BlockSize: Integer; const Proc: TDECCipherCodeEvent; const Progress: IDECProgress);
1214
var
1215
  Buffer: Binary;
1216
  BufferSize,Bytes: Integer;
1217
  Min,Max,Pos: Int64;
1218
begin
1219
  Pos := Source.Position;
1220
  if Size < 0 then Size := Source.Size - Pos;
1221
  Min := Pos;
1222
  Max := Pos + Size;
1223
  if Size > 0 then
1224
  try
1225
    if StreamBufferSize <= 0 then StreamBufferSize := 8192;
1226
    BufferSize := StreamBufferSize mod BlockSize;
1227
    if BufferSize = 0 then BufferSize := StreamBufferSize
1228
      else BufferSize := StreamBufferSize + BlockSize - BufferSize;
1229
    if Size > BufferSize then SetLength(Buffer, BufferSize)
1230
      else SetLength(Buffer, Size);
1231
    while Size > 0 do
1232
    begin
1233
      if Assigned(Progress) then Progress.Process(Min, Max, Pos);
1234
      Bytes := BufferSize;
1235
      if Bytes > Size then Bytes := Size;
1236
      Source.ReadBuffer(Buffer[1], Bytes);
1237
      Proc(Buffer[1], Buffer[1], Bytes);
1238
      Dest.WriteBuffer(Buffer[1], Bytes);
1239
      Dec(Size, Bytes);
1240
      Inc(Pos, Bytes);
1241
    end;
1242
  finally
1243
    ProtectBinary(Buffer);
1244
    if Assigned(Progress) then Progress.Process(Min, Max, Max);
1245
  end;
1246
end;
1247
 
1248
procedure DoCodeFile(const Source,Dest: String; BlockSize: Integer; const Proc: TDECCipherCodeEvent; const Progress: IDECProgress);
1249
var
1250
  S,D: TStream;
1251
begin
1252
  S := TFileStream.Create(Source, fmOpenRead or fmShareDenyNone);
1253
  try
1254
    D := TFileStream.Create(Dest, fmCreate);
1255
    try
1256
      DoCodeStream(S, D, S.Size, BlockSize, Proc, Progress);
1257
    finally
1258
      D.Free;
1259
    end;
1260
  finally
1261
    S.Free;
1262
  end;
1263
end;
1264
 
1265
procedure TDECCipher.EncodeFile(const Source, Dest: String; const Progress: IDECProgress);
1266
begin
1267
  DoCodeFile(Source, Dest, Context.BlockSize, Encode, Progress);
1268
end;
1269
 
1270
procedure TDECCipher.DecodeFile(const Source, Dest: String; const Progress: IDECProgress);
1271
begin
1272
  DoCodeFile(Source, Dest, Context.BlockSize, Decode, Progress);
1273
end;
1274
 
1275
procedure TDECCipher.EncodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress);
1276
begin
1277
  DoCodeStream(Source, Dest, DataSize, Context.BlockSize, Encode, Progress);
1278
end;
1279
 
1280
procedure TDECCipher.DecodeStream(const Source, Dest: TStream; const DataSize: Int64; const Progress: IDECProgress);
1281
begin
1282
  DoCodeStream(Source, Dest, DataSize, Context.BlockSize, Decode, Progress);
1283
end;
1284
 
1285
function TDECCipher.CalcMAC(Format: TDECFormatClass): Binary;
1286
begin
1287
  Done;
1288
  if FMode in [cmECBx] then raise EDECException.Create(sInvalidMACMode)
1289
    else Result := ValidFormat(Format).Encode(FBuffer^, FBufferSize);
1290
end;
1291
 
1292
// .TCipher_Null
1293
class function TCipher_Null.Context: TCipherContext;
1294
begin
1295
  Result.KeySize := 0;
1296
  Result.BlockSize := 1;
1297
  Result.BufferSize := 32;
1298
  Result.UserSize := 0;
1299
  Result.UserSave := False;
1300
end;
1301
 
1302
procedure TCipher_Null.DoInit(const Key; Size: Integer);
1303
begin
1304
end;
1305
 
1306
procedure TCipher_Null.DoEncode(Source, Dest: Pointer; Size: Integer);
1307
begin
1308
  if Source <> Dest then Move(Source^, Dest^, Size);
1309
end;
1310
 
1311
procedure TCipher_Null.DoDecode(Source, Dest: Pointer; Size: Integer);
1312
begin
1313
  if Source <> Dest then Move(Source^, Dest^, Size);
1314
end;
1315
 
1316
// .TCipher_Blowfish
1317
 
1318
{$IFDEF UseASM}
1319
  {$IFDEF 486GE}
1320
    {$DEFINE Blowfish_asm}
1321
  {$ENDIF}
1322
{$ENDIF}
1323
 
1324
type
1325
  PBlowfish = ^TBlowfish;
1326
  TBlowfish = array[0..3, 0..255] of LongWord;
1327
 
1328
class function TCipher_Blowfish.Context: TCipherContext;
1329
begin
1330
  Result.KeySize := 56;
1331
  Result.BufferSize := 8;
1332
  Result.BlockSize := 8;
1333
  Result.UserSize := SizeOf(Blowfish_Data) + SizeOf(Blowfish_Key);
1334
  Result.UserSave := False;
1335
end;
1336
 
1337
procedure TCipher_Blowfish.DoInit(const Key; Size: Integer);
1338
var
1339
  I,J: Integer;
1340
  B: array[0..1] of LongWord;
1341
  K: PByteArray;
1342
  P: PLongArray;
1343
  S: PBlowfish;
1344
begin
1345
  K := @Key;
1346
  S := FUser;
1347
  P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data));
1348
  Move(Blowfish_Data, S^, SizeOf(Blowfish_Data));
1349
  Move(Blowfish_Key, P^, Sizeof(Blowfish_Key));
1350
  J := 0;
1351
  if Size > 0 then
1352
    for I := 0 to 17 do
1353
    begin
1354
      P[I] := P[I] xor (K[(J + 0) mod Size] shl 24 +
1355
                        K[(J + 1) mod Size] shl 16 +
1356
                        K[(J + 2) mod Size] shl  8 +
1357
                        K[(J + 3) mod Size] shl  0);
1358
      J := (J + 4) mod Size;
1359
    end;
1360
  FillChar(B, SizeOf(B), 0);
1361
  for I := 0 to 8 do
1362
  begin
1363
    DoEncode(@B, @B, SizeOf(B));
1364
    P[I * 2 + 0] := SwapLong(B[0]);
1365
    P[I * 2 + 1] := SwapLong(B[1]);
1366
  end;
1367
  for I := 0 to 3 do
1368
    for J := 0 to 127 do
1369
    begin
1370
      DoEncode(@B, @B, SizeOf(B));
1371
      S[I, J * 2 + 0] := SwapLong(B[0]);
1372
      S[I, J * 2 + 1] := SwapLong(B[1]);
1373
    end;
1374
  FillChar(B, SizeOf(B), 0);
1375
end;
1376
 
1377
procedure TCipher_Blowfish.DoEncode(Source, Dest: Pointer; Size: Integer);
1378
{$IFDEF Blowfish_asm}  // specialy for CPU >= 486
1379
// Source = EDX, Dest=ECX, Size on Stack
1380
asm
1381
        PUSH   EDI
1382
        PUSH   ESI
1383
        PUSH   EBX
1384
        PUSH   EBP
1385
        PUSH   ECX
1386
        MOV    ESI,[EAX].TCipher_Blowfish.FUser
1387
        MOV    EBX,[EDX + 0]     // A
1388
        MOV    EBP,[EDX + 4]     // B
1389
        BSWAP  EBX               // CPU >= 486
1390
        BSWAP  EBP
1391
        XOR    EBX,[ESI + 4 * 256 * 4]
1392
        XOR    EDI,EDI
1393
@@1:    MOV    EAX,EBX
1394
        SHR    EBX,16
1395
        MOVZX  ECX,BH
1396
        AND    EBX,0FFh
1397
        MOV    ECX,[ESI + ECX * 4 + 1024 * 0]
1398
        MOV    EBX,[ESI + EBX * 4 + 1024 * 1]
1399
        MOVZX  EDX,AH
1400
        ADD    EBX,ECX
1401
        MOVZX  ECX,AL
1402
        MOV    EDX,[ESI + EDX * 4 + 1024 * 2]
1403
        MOV    ECX,[ESI + ECX * 4 + 1024 * 3]
1404
        XOR    EBX,EDX
1405
        XOR    EBP,[ESI + 4 * 256 * 4 + 4 + EDI * 4]
1406
        ADD    EBX,ECX
1407
        INC    EDI
1408
        XOR    EBX,EBP
1409
        TEST   EDI,010h
1410
        MOV    EBP,EAX
1411
        JZ     @@1
1412
        POP    EAX
1413
        XOR    EBP,[ESI + 4 * 256 * 4 + 17 * 4]
1414
        BSWAP  EBX
1415
        BSWAP  EBP
1416
        MOV    [EAX + 4],EBX
1417
        MOV    [EAX + 0],EBP
1418
        POP    EBP
1419
        POP    EBX
1420
        POP    ESI
1421
        POP    EDI
1422
end;
1423
{$ELSE}
1424
var
1425
  I,A,B: LongWord;
1426
  P: PLongArray;
1427
  D: PBlowfish;
1428
begin
1429
  Assert(Size = Context.BlockSize);
1430
 
1431
  D := FUser;
1432
  P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data));
1433
  A := SwapLong(PLongArray(Source)[0]) xor P[0]; P := @P[1];
1434
  B := SwapLong(PLongArray(Source)[1]);
1435
  for I := 0 to 7 do
1436
  begin
1437
    B := B xor P[0] xor (D[0, A shr 24        ] +
1438
                         D[1, A shr 16 and $FF] xor
1439
                         D[2, A shr  8 and $FF] +
1440
                         D[3, A        and $FF]);
1441
 
1442
    A := A xor P[1] xor (D[0, B shr 24        ] +
1443
                         D[1, B shr 16 and $FF] xor
1444
                         D[2, B shr  8 and $FF] +
1445
                         D[3, B        and $FF]);
1446
    P := @P[2];
1447
  end;
1448
  PLongArray(Dest)[0] := SwapLong(B xor P[0]);
1449
  PLongArray(Dest)[1] := SwapLong(A);
1450
end;
1451
{$ENDIF}
1452
 
1453
procedure TCipher_Blowfish.DoDecode(Source, Dest: Pointer; Size: Integer);
1454
{$IFDEF Blowfish_asm}
1455
asm
1456
        PUSH   EDI
1457
        PUSH   ESI
1458
        PUSH   EBX
1459
        PUSH   EBP
1460
        PUSH   ECX
1461
        MOV    ESI,[EAX].TCipher_Blowfish.FUser
1462
        MOV    EBX,[EDX + 0]     // A
1463
        MOV    EBP,[EDX + 4]     // B
1464
        BSWAP  EBX
1465
        BSWAP  EBP
1466
        XOR    EBX,[ESI + 4 * 256 * 4 + 17 * 4]
1467
        MOV    EDI,16
1468
@@1:    MOV    EAX,EBX
1469
        SHR    EBX,16
1470
        MOVZX  ECX,BH
1471
        MOVZX  EDX,BL
1472
        MOV    EBX,[ESI + ECX * 4 + 1024 * 0]
1473
        MOV    EDX,[ESI + EDX * 4 + 1024 * 1]
1474
        MOVZX  ECX,AH
1475
        LEA    EBX,[EBX + EDX]
1476
        MOVZX  EDX,AL
1477
        MOV    ECX,[ESI + ECX * 4 + 1024 * 2]
1478
        MOV    EDX,[ESI + EDX * 4 + 1024 * 3]
1479
        XOR    EBX,ECX
1480
        XOR    EBP,[ESI + 4 * 256 * 4 + EDI * 4]
1481
        LEA    EBX,[EBX + EDX]
1482
        XOR    EBX,EBP
1483
        DEC    EDI
1484
        MOV    EBP,EAX
1485
        JNZ    @@1
1486
        POP    EAX
1487
        XOR    EBP,[ESI + 4 * 256 * 4]
1488
        BSWAP  EBX
1489
        BSWAP  EBP
1490
        MOV    [EAX + 0],EBP
1491
        MOV    [EAX + 4],EBX
1492
        POP    EBP
1493
        POP    EBX
1494
        POP    ESI
1495
        POP    EDI
1496
end;
1497
{$ELSE}
1498
var
1499
  I,A,B: LongWord;
1500
  P: PLongArray;
1501
  D: PBlowfish;
1502
begin
1503
  Assert(Size = Context.BlockSize);
1504
 
1505
  D := FUser;
1506
  P := Pointer(PChar(FUser) + SizeOf(Blowfish_Data) + SizeOf(Blowfish_Key) - SizeOf(Integer));
1507
  A := SwapLong(PLongArray(Source)[0]) xor P[0];
1508
  B := SwapLong(PLongArray(Source)[1]);
1509
  for I := 0 to 7 do
1510
  begin
1511
    Dec(PLongWord(P), 2);
1512
    B := B xor P[1] xor (D[0, A shr 24        ] +
1513
                         D[1, A shr 16 and $FF] xor
1514
                         D[2, A shr  8 and $FF] +
1515
                         D[3, A        and $FF]);
1516
    A := A xor P[0] xor (D[0, B shr 24        ] +
1517
                         D[1, B shr 16 and $FF] xor
1518
                         D[2, B shr  8 and $FF] +
1519
                         D[3, B        and $FF]);
1520
  end;
1521
  Dec(PLongWord(P));
1522
  PLongArray(Dest)[0] := SwapLong(B xor P[0]);
1523
  PLongArray(Dest)[1] := SwapLong(A);
1524
end;
1525
{$ENDIF}
1526
 
1527
// .TCipher_Twofish
1528
type
1529
  PTwofishBox = ^TTwofishBox;
1530
  TTwofishBox = array[0..3, 0..255] of Longword;
1531
 
1532
  TLongRec = record
1533
               case Integer of
1534
                 0: (L: Longword);
1535
                 1: (A,B,C,D: Byte);
1536
             end;
1537
 
1538
class function TCipher_Twofish.Context: TCipherContext;
1539
begin
1540
  Result.KeySize := 32;
1541
  Result.BufferSize := 16;
1542
  Result.BlockSize := 16;
1543
  Result.UserSize := 4256;
1544
  Result.UserSave := False;
1545
end;
1546
 
1547
procedure TCipher_Twofish.DoInit(const Key; Size: Integer);
1548
var
1549
  BoxKey: array[0..3] of TLongRec;
1550
  SubKey: PLongArray;
1551
  Box: PTwofishBox;
1552
 
1553
  procedure SetupKey;
1554
 
1555
    function Encode(K0, K1: Integer): Integer;
1556
    var
1557
      R, I, J, G2, G3: Integer;
1558
      B: byte;
1559
    begin
1560
      R := 0;
1561
      for I := 0 to 1 do
1562
      begin
1563
        if I <> 0 then R := R xor K0 else R := R xor K1;
1564
        for J := 0 to 3 do
1565
        begin
1566
          B := R shr 24;
1567
          if B and $80 <> 0 then G2 := (B shl 1 xor $014D) and $FF
1568
            else G2 := B shl 1 and $FF;
1569
          if B and 1 <> 0 then G3 := (B shr 1 and $7F) xor $014D shr 1 xor G2
1570
            else G3 := (B shr 1 and $7F) xor G2;
1571
          R := R shl 8 xor G3 shl 24 xor G2 shl 16 xor G3 shl 8 xor B;
1572
        end;
1573
      end;
1574
      Result := R;
1575
    end;
1576
 
1577
    function F32(X: Integer; K: array of Integer): Integer;
1578
    var
1579
      A, B, C, D: LongWord;
1580
    begin
1581
      A := X        and $FF;
1582
      B := X shr  8 and $FF;
1583
      C := X shr 16 and $FF;
1584
      D := X shr 24;
1585
      if Size = 32 then
1586
      begin
1587
        A := Twofish_8x8[1, A] xor K[3]        and $FF;
1588
        B := Twofish_8x8[0, B] xor K[3] shr  8 and $FF;
1589
        C := Twofish_8x8[0, C] xor K[3] shr 16 and $FF;
1590
        D := Twofish_8x8[1, D] xor K[3] shr 24;
1591
      end;
1592
      if Size >= 24 then
1593
      begin
1594
        A := Twofish_8x8[1, A] xor K[2]        and $FF;
1595
        B := Twofish_8x8[1, B] xor K[2] shr  8 and $FF;
1596
        C := Twofish_8x8[0, C] xor K[2] shr 16 and $FF;
1597
        D := Twofish_8x8[0, D] xor K[2] shr 24;
1598
      end;
1599
      A := Twofish_8x8[0, A] xor K[1]        and $FF;
1600
      B := Twofish_8x8[1, B] xor K[1] shr  8 and $FF;
1601
      C := Twofish_8x8[0, C] xor K[1] shr 16 and $FF;
1602
      D := Twofish_8x8[1, D] xor K[1] shr 24;
1603
 
1604
      A := Twofish_8x8[0, A] xor K[0]        and $FF;
1605
      B := Twofish_8x8[0, B] xor K[0] shr  8 and $FF;
1606
      C := Twofish_8x8[1, C] xor K[0] shr 16 and $FF;
1607
      D := Twofish_8x8[1, D] xor K[0] shr 24;
1608
 
1609
      Result := Twofish_Data[0, A] xor Twofish_Data[1, B] xor
1610
                Twofish_Data[2, C] xor Twofish_Data[3, D];
1611
    end;
1612
 
1613
  var
1614
    I,J,A,B: Integer;
1615
    E,O: array[0..3] of Integer;
1616
    K: array[0..7] of Integer;
1617
  begin
1618
    FillChar(K, SizeOf(K), 0);
1619
    Move(Key, K, Size);
1620
    if Size <= 16 then Size := 16 else
1621
      if Size <= 24 then Size := 24
1622
        else Size := 32;
1623
    J := Size shr 3 - 1;
1624
    for I := 0 to J do
1625
    begin
1626
      E[I] := K[I shl 1];
1627
      O[I] := K[I shl 1 + 1];
1628
      BoxKey[J].L := Encode(E[I], O[I]);
1629
      Dec(J);
1630
    end;
1631
    J := 0;
1632
    for I := 0 to 19 do
1633
    begin
1634
      A := F32(J, E);
1635
      B := F32(J + $01010101, O);
1636
      B := B shl 8 or B shr 24;
1637
      SubKey[I shl 1] := A + B;
1638
      B := A + B shl 1;     // here buggy instead shr 1 it's correct shl 1
1639
      SubKey[I shl 1 + 1] := B shl 9 or B shr 23;
1640
      Inc(J, $02020202);
1641
    end;
1642
  end;
1643
 
1644
  procedure DoXOR(D, S: PLongArray; Value: LongWord);
1645
  var
1646
    I: LongWord;
1647
  begin
1648
    Value := (Value and $FF) * $01010101;
1649
    for I := 0 to 63 do D[I] := S[I] xor Value;
1650
  end;
1651
 
1652
  procedure SetupBox128;
1653
  var
1654
    L: array[0..255] of Byte;
1655
    A,I: Integer;
1656
  begin
1657
    DoXOR(@L, @Twofish_8x8[0], BoxKey[1].L);
1658
    A := BoxKey[0].A;
1659
    for I := 0 to 255 do
1660
      Box[0, I] := Twofish_Data[0, Twofish_8x8[0, L[I]] xor A];
1661
    DoXOR(@L, @Twofish_8x8[1], BoxKey[1].L shr 8);
1662
    A := BoxKey[0].B;
1663
    for I := 0 to 255 do
1664
      Box[1, I] := Twofish_Data[1, Twofish_8x8[0, L[I]] xor A];
1665
    DoXOR(@L, @Twofish_8x8[0], BoxKey[1].L shr 16);
1666
    A := BoxKey[0].C;
1667
    for I := 0 to 255 do
1668
      Box[2, I] := Twofish_Data[2, Twofish_8x8[1, L[I]] xor A];
1669
    DoXOR(@L, @Twofish_8x8[1], BoxKey[1].L shr 24);
1670
    A := BoxKey[0].D;
1671
    for I := 0 to 255 do
1672
      Box[3, I] := Twofish_Data[3, Twofish_8x8[1, L[I]] xor A];
1673
  end;
1674
 
1675
  procedure SetupBox192;
1676
  var
1677
    L: array[0..255] of Byte;
1678
    A,B,I: Integer;
1679
  begin
1680
    DoXOR(@L, @Twofish_8x8[1], BoxKey[2].L);
1681
    A := BoxKey[0].A;
1682
    B := BoxKey[1].A;
1683
    for I := 0 to 255 do
1684
      Box[0, I] := Twofish_Data[0, Twofish_8x8[0, Twofish_8x8[0, L[I]] xor B] xor A];
1685
    DoXOR(@L, @Twofish_8x8[1], BoxKey[2].L shr 8);
1686
    A := BoxKey[0].B;
1687
    B := BoxKey[1].B;
1688
    for I := 0 to 255 do
1689
      Box[1, I] := Twofish_Data[1, Twofish_8x8[0, Twofish_8x8[1, L[I]] xor B] xor A];
1690
    DoXOR(@L, @Twofish_8x8[0], BoxKey[2].L shr 16);
1691
    A := BoxKey[0].C;
1692
    B := BoxKey[1].C;
1693
    for I := 0 to 255 do
1694
      Box[2, I] := Twofish_Data[2, Twofish_8x8[1, Twofish_8x8[0, L[I]] xor B] xor A];
1695
    DoXOR(@L ,@Twofish_8x8[0], BoxKey[2].L shr 24);
1696
    A := BoxKey[0].D;
1697
    B := BoxKey[1].D;
1698
    for I := 0 to 255 do
1699
      Box[3, I] := Twofish_Data[3, Twofish_8x8[1, Twofish_8x8[1, L[I]] xor B] xor A];
1700
  end;
1701
 
1702
  procedure SetupBox256;
1703
  var
1704
    L: array[0..255] of Byte;
1705
    K: array[0..255] of Byte;
1706
    A,B,I: Integer;
1707
  begin
1708
    DoXOR(@K, @Twofish_8x8[1], BoxKey[3].L);
1709
    for I := 0 to 255 do L[I] := Twofish_8x8[1, K[I]];
1710
    DoXOR(@L, @L, BoxKey[2].L);
1711
    A := BoxKey[0].A;
1712
    B := BoxKey[1].A;
1713
    for I := 0 to 255 do
1714
      Box[0, I] := Twofish_Data[0, Twofish_8x8[0, Twofish_8x8[0, L[I]] xor B] xor A];
1715
    DoXOR(@K, @Twofish_8x8[0], BoxKey[3].L shr 8);
1716
    for I := 0 to 255 do L[I] := Twofish_8x8[1, K[I]];
1717
    DoXOR(@L, @L, BoxKey[2].L shr 8);
1718
    A := BoxKey[0].B;
1719
    B := BoxKey[1].B;
1720
    for I := 0 to 255 do
1721
      Box[1, I] := Twofish_Data[1, Twofish_8x8[0, Twofish_8x8[1, L[I]] xor B] xor A];
1722
    DoXOR(@K, @Twofish_8x8[0],BoxKey[3].L shr 16);
1723
    for I := 0 to 255 do L[I] := Twofish_8x8[0, K[I]];
1724
    DoXOR(@L, @L, BoxKey[2].L shr 16);
1725
    A := BoxKey[0].C;
1726
    B := BoxKey[1].C;
1727
    for I := 0 to 255 do
1728
      Box[2, I] := Twofish_Data[2, Twofish_8x8[1, Twofish_8x8[0, L[I]] xor B] xor A];
1729
    DoXOR(@K, @Twofish_8x8[1], BoxKey[3].L shr 24);
1730
    for I := 0 to 255 do L[I] := Twofish_8x8[0, K[I]];
1731
    DoXOR(@L, @L, BoxKey[2].L shr 24);
1732
    A := BoxKey[0].D;
1733
    B := BoxKey[1].D;
1734
    for I := 0 to 255 do
1735
      Box[3, I] := Twofish_Data[3, Twofish_8x8[1, Twofish_8x8[1, L[I]] xor B] xor A];
1736
  end;
1737
 
1738
begin
1739
  SubKey := FUser;
1740
  Box    := @SubKey[40];
1741
  SetupKey;
1742
  if Size = 16 then SetupBox128 else
1743
    if Size = 24 then SetupBox192
1744
      else SetupBox256;
1745
end;
1746
 
1747
procedure TCipher_Twofish.DoEncode(Source, Dest: Pointer; Size: Integer);
1748
var
1749
  S: PLongArray;
1750
  Box: PTwofishBox;
1751
  I,X,Y: LongWord;
1752
  A,B,C,D: TLongRec;
1753
begin
1754
  Assert(Size = Context.BlockSize);
1755
 
1756
  S   := FUser;
1757
  A.L := PLongArray(Source)[0] xor S[0];
1758
  B.L := PLongArray(Source)[1] xor S[1];
1759
  C.L := PLongArray(Source)[2] xor S[2];
1760
  D.L := PLongArray(Source)[3] xor S[3];
1761
 
1762
  Box := @S[40];
1763
  S   := @S[8];
1764
  for I := 0 to 7 do
1765
  begin
1766
    X := Box[0, A.A] xor Box[1, A.B] xor Box[2, A.C] xor Box[3, A.D];
1767
    Y := Box[1, B.A] xor Box[2, B.B] xor Box[3, B.C] xor Box[0, B.D];
1768
    D.L := D.L shl 1 or D.L shr 31;
1769
    C.L := C.L xor (X + Y       + S[0]);
1770
    D.L := D.L xor (X + Y shl 1 + S[1]);
1771
    C.L := C.L shr 1 or C.L shl 31;
1772
 
1773
    X := Box[0, C.A] xor Box[1, C.B] xor Box[2, C.C] xor Box[3, C.D];
1774
    Y := Box[1, D.A] xor Box[2, D.B] xor Box[3, D.C] xor Box[0, D.D];
1775
    B.L := B.L shl 1 or B.L shr 31;
1776
    A.L := A.L xor (X + Y       + S[2]);
1777
    B.L := B.L xor (X + Y shl 1 + S[3]);
1778
    A.L := A.L shr 1 or A.L shl 31;
1779
 
1780
    S := @S[4];
1781
  end;
1782
  S := FUser;
1783
  PLongArray(Dest)[0] := C.L xor S[4];
1784
  PLongArray(Dest)[1] := D.L xor S[5];
1785
  PLongArray(Dest)[2] := A.L xor S[6];
1786
  PLongArray(Dest)[3] := B.L xor S[7];
1787
end;
1788
 
1789
procedure TCipher_Twofish.DoDecode(Source, Dest: Pointer; Size: Integer);
1790
var
1791
  S: PLongArray;
1792
  Box: PTwofishBox;
1793
  I,X,Y: LongWord;
1794
  A,B,C,D: TLongRec;
1795
begin
1796
  Assert(Size = Context.BlockSize);
1797
 
1798
  S := FUser;
1799
  Box := @S[40];
1800
  C.L := PLongArray(Source)[0] xor S[4];
1801
  D.L := PLongArray(Source)[1] xor S[5];
1802
  A.L := PLongArray(Source)[2] xor S[6];
1803
  B.L := PLongArray(Source)[3] xor S[7];
1804
  S := @S[36];
1805
  for I := 0 to 7 do
1806
  begin
1807
    X := Box[0, C.A] xor Box[1, C.B] xor Box[2, C.C] xor Box[3, C.D];
1808
    Y := Box[0, D.D] xor Box[1, D.A] xor Box[2, D.B] xor Box[3, D.C];
1809
    A.L := A.L shl 1 or A.L shr 31;
1810
    B.L := B.L xor (X + Y shl 1 + S[3]);
1811
    A.L := A.L xor (X + Y       + S[2]);
1812
    B.L := B.L shr 1 or B.L shl 31;
1813
 
1814
    X := Box[0, A.A] xor Box[1, A.B] xor Box[2, A.C] xor Box[3, A.D];
1815
    Y := Box[0, B.D] xor Box[1, B.A] xor Box[2, B.B] xor Box[3, B.C];
1816
    C.L := C.L shl 1 or C.L shr 31;
1817
    D.L := D.L xor (X + Y shl 1 + S[1]);
1818
    C.L := C.L xor (X + Y       + S[0]);
1819
    D.L := D.L shr 1 or D.L shl 31;
1820
 
1821
    Dec(PLongWord(S), 4);
1822
  end;
1823
  S := FUser;
1824
  PLongArray(Dest)[0] := A.L xor S[0];
1825
  PLongArray(Dest)[1] := B.L xor S[1];
1826
  PLongArray(Dest)[2] := C.L xor S[2];
1827
  PLongArray(Dest)[3] := D.L xor S[3];
1828
end;
1829
 
1830
// .TCipher_IDEA
1831
class function TCipher_IDEA.Context: TCipherContext;
1832
begin
1833
  Result.KeySize := 16;
1834
  Result.BufferSize := 8;
1835
  Result.BlockSize := 8;
1836
  Result.UserSize := 208;
1837
  Result.UserSave := False;
1838
end;
1839
 
1840
procedure TCipher_IDEA.DoInit(const Key; Size: Integer);
1841
 
1842
  function IDEAInv(X: Word): Word;
1843
  var
1844
    A, B, C, D: Word;
1845
  begin
1846
    if X <= 1 then
1847
    begin
1848
      Result := X;
1849
      Exit;
1850
    end;
1851
    A := 1;
1852
    B := $10001 div X;
1853
    C := $10001 mod X;
1854
    while C <> 1 do
1855
    begin
1856
      D := X div C;
1857
      X := X mod C;
1858
      Inc(A, B * D);
1859
      if X = 1 then
1860
      begin
1861
        Result := A;
1862
        Exit;
1863
      end;
1864
      D := C div X;
1865
      C := C mod X;
1866
      Inc(B, A * D);
1867
    end;
1868
    Result := 1 - B;
1869
  end;
1870
 
1871
var
1872
  I: Integer;
1873
  E: PWordArray;
1874
  A,B,C: Word;
1875
  K,D: PWordArray;
1876
begin
1877
  E := FUser;
1878
  Move(Key, E^, Size);
1879
  for I := 0 to 7 do E[I] := Swap(E[I]);
1880
  for I := 0 to 39 do
1881
    E[I + 8] := E[I and not 7 + (I + 1) and 7] shl 9 or
1882
                E[I and not 7 + (I + 2) and 7] shr 7;
1883
  for I := 41 to 44 do
1884
    E[I + 7] := E[I] shl 9 or E[I + 1] shr 7;
1885
  K  := E;
1886
  D  := @E[100];
1887
  A  := IDEAInv(K[0]);
1888
  B  := 0 - K[1];
1889
  C  := 0 - K[2];
1890
  D[3] := IDEAInv(K[3]);
1891
  D[2] := C;
1892
  D[1] := B;
1893
  D[0] := A;
1894
  Inc(PWord(K), 4);
1895
  for I := 1 to 8 do
1896
  begin
1897
    Dec(PWord(D), 6);
1898
    A    := K[0];
1899
    D[5] := K[1];
1900
    D[4] := A;
1901
    A    := IDEAInv(K[2]);
1902
    B    := 0 - K[3];
1903
    C    := 0 - K[4];
1904
    D[3] := IDEAInv(K[5]);
1905
    D[2] := B;
1906
    D[1] := C;
1907
    D[0] := A;
1908
    Inc(PWord(K), 6);
1909
  end;
1910
  A    := D[2];
1911
  D[2] := D[1];
1912
  D[1] := A;
1913
end;
1914
 
1915
function IDEAMul(X,Y: LongWord): LongWord;
1916
asm
1917
       AND    EAX,0FFFFh
1918
       JZ     @@1
1919
       AND    EDX,0FFFFh
1920
       JZ     @@1
1921
       MUL    EDX
1922
       MOV    EDX,EAX
1923
       MOV    ECX,EAX
1924
       SHR    EDX,16
1925
       SUB    EAX,EDX
1926
       SUB    CX,AX
1927
       ADC    EAX,0
1928
       RET
1929
@@1:   LEA    EAX,[EAX + EDX -1]
1930
       NEG    EAX
1931
end;
1932
 
1933
procedure IDEACipher(Source, Dest: PLongArray; Key: PWordArray);
1934
var
1935
  I: LongWord;
1936
  X,Y,A,B,C,D: LongWord;
1937
begin
1938
  I := SwapLong(Source[0]);
1939
  A := I shr 16;
1940
  B := I and $FFFF;
1941
  I := SwapLong(Source[1]);
1942
  C := I shr 16;
1943
  D := I and $FFFF;
1944
  for I := 0 to 7 do
1945
  begin
1946
    A := IDEAMul(A, Key[0]);
1947
    Inc(B, Key[1]);
1948
    Inc(C, Key[2]);
1949
    D := IDEAMul(D, Key[3]);
1950
    Y := C xor A;
1951
    Y := IDEAMul(Y, Key[4]);
1952
    X := B xor D + Y;
1953
    X := IDEAMul(X, Key[5]);
1954
    Inc(Y, X);
1955
    A := A xor X;
1956
    D := D xor Y;
1957
    Y := B xor Y;
1958
    B := C xor X;
1959
    C := Y;
1960
    Key := @Key[6];
1961
  end;
1962
  Dest[0] := SwapLong(IDEAMul(A, Key[0]) shl 16 or (C + Key[1]) and $FFFF);
1963
  Dest[1] := SwapLong((B + Key[2]) shl 16 or IDEAMul(D, Key[3]) and $FFFF);
1964
end;
1965
 
1966
procedure TCipher_IDEA.DoEncode(Source, Dest: Pointer; Size: Integer);
1967
begin
1968
  Assert(Size = Context.BlockSize);
1969
 
1970
  IDEACipher(Source, Dest, FUser);
1971
end;
1972
 
1973
procedure TCipher_IDEA.DoDecode(Source, Dest: Pointer; Size: Integer);
1974
begin
1975
  Assert(Size = Context.BlockSize);
1976
 
1977
  IDEACipher(Source, Dest, @PLongArray(FUser)[26]);
1978
end;
1979
 
1980
// .TCipher_Cast256
1981
class function TCipher_Cast256.Context: TCipherContext;
1982
begin
1983
  Result.KeySize := 32;
1984
  Result.BlockSize := 16;
1985
  Result.BufferSize := 16;
1986
  Result.UserSize := 384;
1987
  Result.UserSave := False;
1988
end;
1989
 
1990
procedure TCipher_Cast256.DoInit(const Key; Size: Integer);
1991
var
1992
  X: array[0..7] of LongWord;
1993
  M, R, I, J, T: LongWord;
1994
  K: PLongArray;
1995
begin
1996
  FillChar(X, SizeOf(X), 0);
1997
  Move(Key, X, Size);
1998
  SwapLongBuffer(X, X, 8);
1999
  K := FUser;
2000
  M := $5A827999;
2001
  R := 19;
2002
  for I := 0 to 11 do
2003
  begin
2004
    for J := 0 to 1 do
2005
    begin
2006
      T := M + X[7];
2007
      T := T shl R or T shr (32 - R);
2008
      X[6] := X[6] xor (Cast256_Data[0, T shr 24] xor
2009
                        Cast256_Data[1, T shr 16 and $FF] -
2010
                        Cast256_Data[2, T shr  8 and $FF] +
2011
                        Cast256_Data[3, T and $FF]);
2012
      Inc(M, $6ED9EBA1);
2013
      Inc(R, 17);
2014
      T := M xor X[6];
2015
      T := T shl R or T shr (32 - R);
2016
      X[5] := X[5] xor (Cast256_Data[0, T shr 24] -
2017
                        Cast256_Data[1, T shr 16 and $FF] +
2018
                        Cast256_Data[2, T shr  8 and $FF] xor
2019
                        Cast256_Data[3, T and $FF]);
2020
      Inc(M, $6ED9EBA1);
2021
      Inc(R, 17);
2022
      T := M - X[5];
2023
      T := T shl R or T shr (32 - R);
2024
      X[4] := X[4] xor (Cast256_Data[0, T shr 24] +
2025
                        Cast256_Data[1, T shr 16 and $FF] xor
2026
                        Cast256_Data[2, T shr  8 and $FF] -
2027
                        Cast256_Data[3, T and $FF]);
2028
      Inc(M, $6ED9EBA1);
2029
      Inc(R, 17);
2030
      T := M + X[4];
2031
      T := T shl R or T shr (32 - R);
2032
      X[3] := X[3] xor (Cast256_Data[0, T shr 24] xor
2033
                        Cast256_Data[1, T shr 16 and $FF] -
2034
                        Cast256_Data[2, T shr  8 and $FF] +
2035
                        Cast256_Data[3, T and $FF]);
2036
      Inc(M, $6ED9EBA1);
2037
      Inc(R, 17);
2038
      T := M xor X[3];
2039
      T := T shl R or T shr (32 - R);
2040
      X[2] := X[2] xor (Cast256_Data[0, T shr 24] -
2041
                        Cast256_Data[1, T shr 16 and $FF] +
2042
                        Cast256_Data[2, T shr  8 and $FF] xor
2043
                        Cast256_Data[3, T and $FF]);
2044
      Inc(M, $6ED9EBA1);
2045
      Inc(R, 17);
2046
      T := M - X[2];
2047
      T := T shl R or T shr (32 - R);
2048
      X[1] := X[1] xor (Cast256_Data[0, T shr 24] +
2049
                        Cast256_Data[1, T shr 16 and $FF] xor
2050
                        Cast256_Data[2, T shr  8 and $FF] -
2051
                        Cast256_Data[3, T and $FF]);
2052
      Inc(M, $6ED9EBA1);
2053
      Inc(R, 17);
2054
      T := M + X[1];
2055
      T := T shl R or T shr (32 - R);
2056
      X[0] := X[0] xor (Cast256_Data[0, T shr 24] xor
2057
                        Cast256_Data[1, T shr 16 and $FF] -
2058
                        Cast256_Data[2, T shr  8 and $FF] +
2059
                        Cast256_Data[3, T and $FF]);
2060
      Inc(M, $6ED9EBA1);
2061
      Inc(R, 17);
2062
      T := M xor X[0];
2063
      T := T shl R or T shr (32 - R);
2064
      X[7] := X[7] xor (Cast256_Data[0, T shr 24] -
2065
                        Cast256_Data[1, T shr 16 and $FF] +
2066
                        Cast256_Data[2, T shr  8 and $FF] xor
2067
                        Cast256_Data[3, T and $FF]);
2068
      Inc(M, $6ED9EBA1);
2069
      Inc(R, 17);
2070
    end;
2071
    if I < 6 then
2072
    begin
2073
      K[48] := X[0] and $1F;
2074
      K[49] := X[2] and $1F;
2075
      K[50] := X[4] and $1F;
2076
      K[51] := X[6] and $1F;
2077
      K[0] := X[7];
2078
      K[1] := X[5];
2079
      K[2] := X[3];
2080
      K[3] := X[1];
2081
    end else
2082
    begin
2083
      K[48] := X[6] and $1F;
2084
      K[49] := X[4] and $1F;
2085
      K[50] := X[2] and $1F;
2086
      K[51] := X[0] and $1F;
2087
      K[0] := X[1];
2088
      K[1] := X[3];
2089
      K[2] := X[5];
2090
      K[3] := X[7];
2091
    end;
2092
    K := @K[4];
2093
  end;
2094
  ProtectBuffer(X, SizeOf(X));
2095
end;
2096
 
2097
procedure TCipher_Cast256.DoEncode(Source, Dest: Pointer; Size: Integer);
2098
var
2099
  I,T,A,B,C,D: LongWord;
2100
  K: PLongArray;
2101
begin
2102
  Assert(Size = Context.BlockSize);
2103
 
2104
  K := FUser;
2105
  SwapLongBuffer(Source^, Dest^, 4);
2106
  A := PLongArray(Dest)[0];
2107
  B := PLongArray(Dest)[1];
2108
  C := PLongArray(Dest)[2];
2109
  D := PLongArray(Dest)[3];
2110
  for I := 0 to 5 do
2111
  begin
2112
    T := K[0] + D;
2113
    T := T shl K[48] or T shr (32 - K[48]);
2114
    C := C xor (Cast256_Data[0, T shr 24] xor
2115
                Cast256_Data[1, T shr 16 and $FF] -
2116
                Cast256_Data[2, T shr  8 and $FF] +
2117
                Cast256_Data[3, T and $FF]);
2118
    T := K[1] xor C;
2119
    T := T shl K[49] or T shr (32 - K[49]);
2120
    B := B xor (Cast256_Data[0, T shr 24] -
2121
                Cast256_Data[1, T shr 16 and $FF] +
2122
                Cast256_Data[2, T shr  8 and $FF] xor
2123
                Cast256_Data[3, T and $FF]);
2124
    T := K[2] - B;
2125
    T := T shl K[50] or T shr (32 - K[50]);
2126
    A := A xor (Cast256_Data[0, T shr 24] +
2127
                Cast256_Data[1, T shr 16 and $FF] xor
2128
                Cast256_Data[2, T shr  8 and $FF] -
2129
                Cast256_Data[3, T and $FF]);
2130
    T := K[3] + A;
2131
    T := T shl K[51] or T shr (32 - K[51]);
2132
    D := D xor (Cast256_Data[0, T shr 24] xor
2133
                Cast256_Data[1, T shr 16 and $FF] -
2134
                Cast256_Data[2, T shr  8 and $FF] +
2135
                Cast256_Data[3, T and $FF]);
2136
    K := @K[4];
2137
  end;
2138
  for I := 0 to 5 do
2139
  begin
2140
    T := K[0] + A;
2141
    T := T shl K[48] or T shr (32 - K[48]);
2142
    D := D xor (Cast256_Data[0, T shr 24] xor
2143
                Cast256_Data[1, T shr 16 and $FF] -
2144
                Cast256_Data[2, T shr  8 and $FF] +
2145
                Cast256_Data[3, T and $FF]);
2146
    T := K[1] - B;
2147
    T := T shl K[49] or T shr (32 - K[49]);
2148
    A := A xor (Cast256_Data[0, T shr 24] +
2149
                Cast256_Data[1, T shr 16 and $FF] xor
2150
                Cast256_Data[2, T shr  8 and $FF] -
2151
                Cast256_Data[3, T and $FF]);
2152
    T := K[2] xor C;
2153
    T := T shl K[50] or T shr (32 - K[50]);
2154
    B := B xor (Cast256_Data[0, T shr 24] -
2155
                Cast256_Data[1, T shr 16 and $FF] +
2156
                Cast256_Data[2, T shr  8 and $FF] xor
2157
                Cast256_Data[3, T and $FF]);
2158
    T := K[3] + D;
2159
    T := T shl K[51] or T shr (32 - K[51]);
2160
    C := C xor (Cast256_Data[0, T shr 24] xor
2161
                Cast256_Data[1, T shr 16 and $FF] -
2162
                Cast256_Data[2, T shr  8 and $FF] +
2163
                Cast256_Data[3, T and $FF]);
2164
    K := @K[4];
2165
  end;
2166
  PLongArray(Dest)[0] := A;
2167
  PLongArray(Dest)[1] := B;
2168
  PLongArray(Dest)[2] := C;
2169
  PLongArray(Dest)[3] := D;
2170
  SwapLongBuffer(Dest^, Dest^, 4);
2171
end;
2172
 
2173
procedure TCipher_Cast256.DoDecode(Source, Dest: Pointer; Size: Integer);
2174
var
2175
  I,T,A,B,C,D: LongWord;
2176
  K: PLongArray;
2177
begin
2178
  Assert(Size = Context.BlockSize);
2179
 
2180
  K := @PLongArray(FUser)[44];
2181
  SwapLongBuffer(Source^, Dest^, 4);
2182
  A := PLongArray(Dest)[0];
2183
  B := PLongArray(Dest)[1];
2184
  C := PLongArray(Dest)[2];
2185
  D := PLongArray(Dest)[3];
2186
  for I := 0 to 5 do
2187
  begin
2188
    T := K[3] + D;
2189
    T := T shl K[51] or T shr (32 - K[51]);
2190
    C := C xor (Cast256_Data[0, T shr 24] xor
2191
                Cast256_Data[1, T shr 16 and $FF] -
2192
                Cast256_Data[2, T shr  8 and $FF] +
2193
                Cast256_Data[3, T and $FF]);
2194
    T := K[2] xor C;
2195
    T := T shl K[50] or T shr (32 - K[50]);
2196
    B := B xor (Cast256_Data[0, T shr 24] -
2197
                Cast256_Data[1, T shr 16 and $FF] +
2198
                Cast256_Data[2, T shr  8 and $FF] xor
2199
                Cast256_Data[3, T and $FF]);
2200
    T := K[1] - B;
2201
    T := T shl K[49] or T shr (32 - K[49]);
2202
    A := A xor (Cast256_Data[0, T shr 24] +
2203
                Cast256_Data[1, T shr 16 and $FF] xor
2204
                Cast256_Data[2, T shr  8 and $FF] -
2205
                Cast256_Data[3, T and $FF]);
2206
    T := K[0] + A;
2207
    T := T shl K[48] or T shr (32 - K[48]);
2208
    D := D xor (Cast256_Data[0, T shr 24] xor
2209
                Cast256_Data[1, T shr 16 and $FF] -
2210
                Cast256_Data[2, T shr  8 and $FF] +
2211
                Cast256_Data[3, T and $FF]);
2212
    Dec(PLongWord(K), 4);
2213
  end;
2214
  for I := 0 to 5 do
2215
  begin
2216
    T := K[3] + A;
2217
    T := T shl K[51] or T shr (32 - K[51]);
2218
    D := D xor (Cast256_Data[0, T shr 24] xor
2219
                Cast256_Data[1, T shr 16 and $FF] -
2220
                Cast256_Data[2, T shr  8 and $FF] +
2221
                Cast256_Data[3, T and $FF]);
2222
    T := K[2] - B;
2223
    T := T shl K[50] or T shr (32 - K[50]);
2224
    A := A xor (Cast256_Data[0, T shr 24] +
2225
                Cast256_Data[1, T shr 16 and $FF] xor
2226
                Cast256_Data[2, T shr  8 and $FF] -
2227
                Cast256_Data[3, T and $FF]);
2228
    T := K[1] xor C;
2229
    T := T shl K[49] or T shr (32 - K[49]);
2230
    B := B xor (Cast256_Data[0, T shr 24] -
2231
                Cast256_Data[1, T shr 16 and $FF] +
2232
                Cast256_Data[2, T shr  8 and $FF] xor
2233
                Cast256_Data[3, T and $FF]);
2234
    T := K[0] + D;
2235
    T := T shl K[48] or T shr (32 - K[48]);
2236
    C := C xor (Cast256_Data[0, T shr 24] xor
2237
                Cast256_Data[1, T shr 16 and $FF] -
2238
                Cast256_Data[2, T shr  8 and $FF] +
2239
                Cast256_Data[3, T and $FF]);
2240
    Dec(PLongWord(K), 4);
2241
  end;
2242
  PLongArray(Dest)[0] := A;
2243
  PLongArray(Dest)[1] := B;
2244
  PLongArray(Dest)[2] := C;
2245
  PLongArray(Dest)[3] := D;
2246
  SwapLongBuffer(Dest^, Dest^, 4);
2247
end;
2248
 
2249
// .TCipher_Mars
2250
class function TCipher_Mars.Context: TCipherContext;
2251
begin
2252
  Result.KeySize := 56;
2253
  Result.BlockSize := 16;
2254
  Result.BufferSize := 16;
2255
  Result.UserSize := 160;
2256
  Result.UserSave := False;
2257
end;
2258
 
2259
procedure TCipher_Mars.DoInit(const Key; Size: Integer);
2260
var
2261
  B: PLongArray;
2262
 
2263
  function FixKey(K, R: LongWord): LongWord;
2264
  var
2265
    M1,M2: LongWord;
2266
    I: LongWord;
2267
  begin
2268
    I := K and 3;
2269
    K := K or 3;
2270
    M1 := not K xor (K shl 1);
2271
    M2 := M1 and (M1 shl 1);
2272
    M2 := M2 and (M2 shl 2);
2273
    M2 := M2 and (M2 shl 4);
2274
    M2 := M2 and (M1 shl 8);
2275
    M2 := M2 and $FFFFFE00;
2276
    if M2 = 0 then
2277
    begin
2278
      Result := K;
2279
      Exit;
2280
    end;
2281
    M1 := M2 or (M2 shr 1);
2282
    M1 := M1 or (M1 shr 2);
2283
    M1 := M1 or (M2 shr 4);
2284
    M1 := M1 or (M1 shr 5);
2285
    M1 := M1 and ((not K xor (K shl 1)) and (not K xor (K shr 1)) and $7FFFFFFC);
2286
    Result := K xor ((B[265 + I] shl R or B[265 + I] shr (32 - R)) and M1);
2287
  end;
2288
 
2289
var
2290
  T: array[0..14] of LongWord;
2291
  I,J,L: LongWord;
2292
  U: LongWord;
2293
  K: PLongArray;
2294
begin
2295
  K := FUser;
2296
  B := @Mars_Data;
2297
  FillChar(T, SizeOf(T), 0);
2298
  Move(Key, T, Size);
2299
  Size := Size div 4;
2300
  T[Size] := Size;
2301
  for J := 0 to 3 do
2302
  begin
2303
    for I := 0 to 14 do
2304
    begin
2305
      U := T[(I + 8) mod 15] xor T[(I + 13) mod 15];
2306
      T[I] := T[I] xor (U shl 3 or U shr 29) xor (I * 4 + J);
2307
    end;
2308
    for L := 0 to 3 do
2309
    begin
2310
      for I := 0 to 14 do
2311
      begin
2312
        Inc(T[I], B[T[(I + 14) mod 15] and $1FF]);
2313
        T[I] := T[I] shl 9 or T[I] shr 23;
2314
      end;
2315
    end;
2316
    for I := 0 to 9 do
2317
      K[(J * 10) + I] := T[(I * 4) mod 15];
2318
  end;
2319
  I := 5;
2320
  repeat
2321
    K[I] := FixKey(K[I], K[I - 1]);
2322
    Inc(I, 2);
2323
  until I >= 37;
2324
end;
2325
 
2326
 
2327
procedure TCipher_Mars.DoEncode(Source, Dest: Pointer; Size: Integer);
2328
var
2329
  K: PLongArray;
2330
  I,L,R,A,B,C,D: LongWord;
2331
begin
2332
  Assert(Size = Context.BlockSize);
2333
 
2334
  K := FUser;
2335
  A := PLongArray(Source)[0] + K[0];
2336
  B := PLongArray(Source)[1] + K[1];
2337
  C := PLongArray(Source)[2] + K[2];
2338
  D := PLongArray(Source)[3] + K[3];
2339
  K := @K[4];
2340
  for I := 0 to 1 do
2341
  begin
2342
    B := B xor Mars_Data[A and $FF] + Mars_Data[A shr 8 and $FF + 256];
2343
    Inc(C, Mars_Data[A shr 16 and $FF]);
2344
    D := D xor Mars_Data[A shr 24 + 256];
2345
    A := (A shr 24 or A shl 8) + D;
2346
 
2347
    C := C xor Mars_Data[B and $FF] + Mars_Data[B shr 8 and $FF + 256];
2348
    Inc(D, Mars_Data[B shr 16 and $FF]);
2349
    A := A xor Mars_Data[B shr 24 + 256];
2350
    B := (B shr 24 or B shl 8) + C;
2351
 
2352
    D := D xor Mars_Data[C and $FF] + Mars_Data[C shr 8 and $FF + 256];
2353
    Inc(A, Mars_Data[C shr 16 and $FF]);
2354
    B := B xor Mars_Data[C shr 24 + 256];
2355
    C := C shr 24 or C shl 8;
2356
 
2357
    A := A xor Mars_Data[D and $FF] + Mars_Data[D shr 8 and $FF + 256];
2358
    Inc(B, Mars_Data[D shr 16 and $FF]);
2359
    C := C xor Mars_Data[D shr 24 + 256];
2360
    D := D shr 24 or D shl 8;
2361
  end;
2362
 
2363
  for I := 0 to 3 do
2364
  begin
2365
    L := A + K[0];
2366
    A := A shl 13 or A shr 19;
2367
    R := A * K[1];
2368
    R := R shl 5 or R shr 27;
2369
    Inc(C, L shl R or L shr (32 - R));
2370
    L := Mars_Data[L and $1FF] xor R;
2371
    R := R shl 5 or R shr 27;
2372
    L := L xor R;
2373
    L := L shl R or L shr (32 - R);
2374
 
2375
    if I <= 1 then
2376
    begin
2377
      Inc(B, L);
2378
      D := D xor R;
2379
    end else
2380
    begin
2381
      Inc(D, L);
2382
      B := B xor R;
2383
    end;
2384
    L := B + K[2];
2385
    B := B shl 13 or B shr 19;
2386
    R := B * K[3];
2387
    R := R shl 5 or R shr 27;
2388
    Inc(D, L shl R or L shr (32 - R));
2389
    L := Mars_Data[L and $1FF] xor R;
2390
    R := R shl 5 or R shr 27;
2391
    L := L xor R;
2392
    L := L shl R or L shr (32 - R);
2393
    if I <= 1 then
2394
    begin
2395
      Inc(C, L);
2396
      A := A xor R;
2397
    end else
2398
    begin
2399
      Inc(A, L);
2400
      C := C xor R;
2401
    end;
2402
    L := C + K[4];
2403
    C := C shl 13 or C shr 19;
2404
    R := C * K[5];
2405
    R := R shl 5 or R shr 27;
2406
    Inc(A, L shl R or L shr (32 - R));
2407
    L := Mars_Data[L and $1FF] xor R;
2408
    R := R shl 5 or R shr 27;
2409
    L := L xor R;
2410
    L := L shl R or L shr (32 - R);
2411
    if I <= 1 then
2412
    begin
2413
      Inc(D, L);
2414
      B := B xor R;
2415
    end else
2416
    begin
2417
      Inc(B, L);
2418
      D := D xor R;
2419
    end;
2420
    L := D + K[6];
2421
    D := D shl 13 or D shr 19;
2422
    R := D * K[7];
2423
    R := R shl 5 or R shr 27;
2424
    Inc(B, L shl R or L shr (32 - R));
2425
    L := Mars_Data[L and $1FF] xor R;
2426
    R := R shl 5 or R shr 27;
2427
    L := L xor R;
2428
    L := L shl R or L shr (32 - R);
2429
    if I <= 1 then
2430
    begin
2431
      Inc(A, L);
2432
      C := C xor R;
2433
    end else
2434
    begin
2435
      Inc(C, L);
2436
      A := A xor R;
2437
    end;
2438
    K := @K[8];
2439
  end;
2440
  for I := 0 to 1 do
2441
  begin
2442
    B := B xor Mars_Data[A and $FF + 256];
2443
    Dec(C, Mars_Data[A shr 24]);
2444
    D := D - Mars_Data[A shr 16 and $FF + 256] xor Mars_Data[A shr 8 and $FF];
2445
    A := A shl 24 or A shr 8;
2446
    C := C xor Mars_Data[B and $FF + 256];
2447
    Dec(D, Mars_Data[B shr 24]);
2448
    A := A - Mars_Data[B shr 16 and $FF + 256] xor Mars_Data[B shr 8 and $FF];
2449
    B := B shl 24 or B shr 8;
2450
    Dec(C, B);
2451
    D := D xor Mars_Data[C and $FF + 256];
2452
    Dec(A, Mars_Data[C shr 24]);
2453
    B := B - Mars_Data[C shr 16 and $FF + 256] xor Mars_Data[C shr 8 and $FF];
2454
    C := C shl 24 or C shr 8;
2455
    Dec(D, A);
2456
    A := A xor Mars_Data[D and $FF + 256];
2457
    Dec(B, Mars_Data[D shr 24]);
2458
    C := C - Mars_Data[D shr 16 and $FF + 256] xor Mars_Data[D shr 8 and $FF];
2459
    D := D shl 24 or D shr 8;
2460
  end;
2461
  PLongArray(Dest)[0] := A - K[0];
2462
  PLongArray(Dest)[1] := B - K[1];
2463
  PLongArray(Dest)[2] := C - K[2];
2464
  PLongArray(Dest)[3] := D - K[3];
2465
end;
2466
 
2467
procedure TCipher_Mars.DoDecode(Source, Dest: Pointer; Size: Integer);
2468
var
2469
  K: PLongArray;
2470
  I,L,R,A,B,C,D: LongWord;
2471
begin
2472
  Assert(Size = Context.BlockSize);
2473
 
2474
  K := @PLongArray(FUser)[28];
2475
  A := PLongArray(Source)[0] + K[8];
2476
  B := PLongArray(Source)[1] + K[9];
2477
  C := PLongArray(Source)[2] + K[10];
2478
  D := PLongArray(Source)[3] + K[11];
2479
  for I := 0 to 1 do
2480
  begin
2481
    D := D shr 24 or D shl 8;
2482
    C := C xor Mars_Data[D shr 8 and $FF] + Mars_Data[D shr 16 and $FF + 256];
2483
    Inc(B, Mars_Data[D shr 24]);
2484
    A := A xor Mars_Data[D and $FF + 256];
2485
    Inc(D, A);
2486
    C := C shr 24 or C shl 8;
2487
    B := B xor Mars_Data[C shr 8 and $FF] + Mars_Data[C shr 16 and $FF + 256];
2488
    Inc(A, Mars_Data[C shr 24]);
2489
    D := D xor Mars_Data[C and $FF + 256];
2490
    Inc(C, B);
2491
    B := B shr 24 or B shl 8;
2492
    A := A xor Mars_Data[B shr 8 and $FF] + Mars_Data[B shr 16 and $FF + 256];
2493
    Inc(D, Mars_Data[B shr 24]);
2494
    C := C xor Mars_Data[B and $FF + 256];
2495
    A := A shr 24 or A shl 8;
2496
    D := D xor Mars_Data[A shr 8 and $FF] + Mars_Data[A shr 16 and $FF + 256];
2497
    Inc(C, Mars_Data[A shr 24]);
2498
    B := B xor Mars_Data[A and $FF + 256];
2499
  end;
2500
  for I := 0 to 3 do
2501
  begin
2502
    R := D * K[7];
2503
    R := R shl 5 or R shr 27;
2504
    D := D shr 13 or D shl 19;
2505
    L := D + K[6];
2506
    Dec(B, L shl R or L shr (32 - R));
2507
    L := Mars_Data[L and $1FF] xor R;
2508
    R := R shl 5 or R shr 27;
2509
    L := L xor R;
2510
    L := L shl R or L shr (32 - R);
2511
    if I <= 1 then
2512
    begin
2513
      Dec(C, L);
2514
      A := A xor R;
2515
    end else
2516
    begin
2517
      Dec(A, L);
2518
      C := C xor R;
2519
    end;
2520
    R := C * K[5];
2521
    R := R shl 5 or R shr 27;
2522
    C := C shr 13 or C shl 19;
2523
    L := C + K[4];
2524
    Dec(A, L shl R or L shr (32 - R));
2525
    L := Mars_Data[L and $1FF] xor R;
2526
    R := R shl 5 or R shr 27;
2527
    L := L xor R;
2528
    L := L shl R or L shr (32 - R);
2529
    if I <= 1 then
2530
    begin
2531
      Dec(B, L);
2532
      D := D xor R;
2533
    end else
2534
    begin
2535
      Dec(D, L);
2536
      B := B xor R;
2537
    end;
2538
    R := B * K[3];
2539
    R := R shl 5 or R shr 27;
2540
    B := B shr 13 or B shl 19;
2541
    L := B + K[2];
2542
    Dec(D, L shl R or L shr (32 - R));
2543
    L := Mars_Data[L and $1FF] xor R;
2544
    R := R shl 5 or R shr 27;
2545
    L := L xor R;
2546
    L := L shl R or L shr (32 - R);
2547
    if I <= 1 then
2548
    begin
2549
      Dec(A, L);
2550
      C := C xor R;
2551
    end else
2552
    begin
2553
      Dec(C, L);
2554
      A := A xor R;
2555
    end;
2556
    R := A * K[1];
2557
    R := R shl 5 or R shr 27;
2558
    A := A shr 13 or A shl 19;
2559
    L := A + K[0];
2560
    Dec(C, L shl R or L shr (32 - R));
2561
    L := Mars_Data[L and $1FF] xor R;
2562
    R := R shl 5 or R shr 27;
2563
    L := L xor R;
2564
    L := L shl R or L shr (32 - R);
2565
    if I <= 1 then
2566
    begin
2567
      Dec(D, L);
2568
      B := B xor R;
2569
    end else
2570
    begin
2571
      Dec(B, L);
2572
      D := D xor R;
2573
    end;
2574
    Dec(PLongWord(K), 8);
2575
  end;
2576
  for I := 0 to 1 do
2577
  begin
2578
    D := D shl 24 or D shr 8;
2579
    C := C xor Mars_Data[D shr 24 + 256];
2580
    Dec(B, Mars_Data[D shr 16 and $FF]);
2581
    A := A - Mars_Data[D shr 8 and $FF + 256] xor Mars_Data[D and $FF];
2582
    C := C shl 24 or C shr 8;
2583
    B := B xor Mars_Data[C shr 24 + 256];
2584
    Dec(A, Mars_Data[C shr 16 and $FF]);
2585
    D := D - Mars_Data[C shr 8 and $FF + 256] xor Mars_Data[C and $FF];
2586
    Dec(B, C);
2587
    B := B shl 24 or B shr 8;
2588
    A := A xor Mars_Data[B shr 24 + 256];
2589
    Dec(D, Mars_Data[B shr 16 and $FF]);
2590
    C := C - Mars_Data[B shr 8 and $FF + 256] xor Mars_Data[B and $FF];
2591
    Dec(A, D);
2592
    A := A shl 24 or A shr 8;
2593
    D := D xor Mars_Data[A shr 24 + 256];
2594
    Dec(C, Mars_Data[A shr 16 and $FF]);
2595
    B := B - Mars_Data[A shr 8 and $FF + 256] xor Mars_Data[A and $FF];
2596
  end;
2597
  PLongArray(Dest)[0] := A - K[4];
2598
  PLongArray(Dest)[1] := B - K[5];
2599
  PLongArray(Dest)[2] := C - K[6];
2600
  PLongArray(Dest)[3] := D - K[7];
2601
end;
2602
 
2603
// .TCipher_RC4
2604
class function TCipher_RC4.Context: TCipherContext;
2605
begin
2606
  Result.KeySize := 256;
2607
  Result.BlockSize := 1;
2608
  Result.BufferSize := 16;
2609
  Result.UserSize := 256 + 2;
2610
  Result.UserSave := True;
2611
end;
2612
 
2613
procedure TCipher_RC4.DoInit(const Key; Size: Integer);
2614
var
2615
  K: array[0..255] of Byte;
2616
  D: PByteArray;
2617
  I,J,T: Byte;
2618
begin
2619
  D := FUser;
2620
  for I := 0 to 255 do
2621
  begin
2622
    D[I] := I;
2623
    if Size > 0 then
2624
      K[I] := TByteArray(Key)[I mod Size];
2625
  end;
2626
  J := 0;
2627
  for I := 0 to 255 do
2628
  begin
2629
    J := J + D[I] + K[I];
2630
    T := D[I];
2631
    D[I] := D[J];
2632
    D[J] := T;
2633
  end;
2634
  D[256] := 0;
2635
  D[257] := 0;
2636
  ProtectBuffer(K, SizeOf(K));
2637
end;
2638
 
2639
procedure TCipher_RC4.DoEncode(Source, Dest: Pointer; Size: Integer);
2640
var
2641
  D: PByteArray;
2642
  S: Integer;
2643
  T,I,J: Byte;
2644
begin
2645
  D := FUser;
2646
  I := D[256];
2647
  J := D[257];
2648
  for S := 0 to Size -1 do
2649
  begin
2650
    Inc(I);
2651
    T := D[I];
2652
    Inc(J, T);
2653
    D[I] := D[J];
2654
    D[J] := T;
2655
    PByteArray(Dest)[S] := PByteArray(Source)[S] xor D[Byte(D[I] + T)];
2656
  end;
2657
  D[256] := I;
2658
  D[257] := J;
2659
end;
2660
 
2661
procedure TCipher_RC4.DoDecode(Source, Dest: Pointer; Size: Integer);
2662
begin
2663
  DoEncode(Source, Dest, Size);
2664
end;
2665
 
2666
// .TCipher_RC6
2667
class function TCipher_RC6.Context: TCipherContext;
2668
begin
2669
  Result.KeySize := 256;
2670
  Result.BlockSize := 16;
2671
  Result.BufferSize := 16;
2672
  Result.UserSize := 272;
2673
  Result.UserSave := False;
2674
end;
2675
 
2676
procedure TCipher_RC6.SetRounds(Value: Integer);
2677
begin
2678
  if Value < 16 then Value := 16 else
2679
    if Value > 24 then Value := 24;
2680
  if Value <> FRounds then
2681
  begin
2682
    if not (FState in [csNew, csInitialized, csDone]) then Done;
2683
    FRounds := Value;
2684
  end;
2685
end;
2686
 
2687
procedure TCipher_RC6.DoInit(const Key; Size: Integer);
2688
var
2689
  K: array[0..63] of LongWord;
2690
  D: PLongArray;
2691
  I,J,L,A,B,Z,T: LongWord;
2692
begin
2693
  if FRounds = 0 then FRounds := 20 else
2694
    if FRounds < 16 then FRounds := 16 else
2695
      if FRounds > 24 then FRounds := 24;
2696
  D := FUser;
2697
  FillChar(K, SizeOf(K), 0);
2698
  Move(Key, K, Size);
2699
  L := Size shr 2;
2700
  if Size and 3 <> 0 then Inc(L);
2701
  if L <= 0 then L := 1;
2702
  J := $B7E15163;
2703
  for I := 0 to (FRounds + 2) * 2 do
2704
  begin
2705
    D[I] := J;
2706
    Inc(J, $9E3779B9);
2707
  end;
2708
  if L > LongWord(FRounds + 2) * 2 then Z := L * 3
2709
    else Z := (FRounds + 2) * 6;
2710
  I := 0;
2711
  J := 0;
2712
  A := 0;
2713
  B := 0;
2714
  for Z := Z downto 1 do
2715
  begin
2716
    A := A + B + D[I];
2717
    A := A shl 3 or A shr 29;
2718
    D[I] := A;
2719
    T := A + B;
2720
    B := T + K[J];
2721
    B := B shl T or B shr (32 - T);
2722
    K[J] := B;
2723
    I := (I + 1) mod (LongWord(FRounds + 2) * 2);
2724
    J := (J + 1) mod L;
2725
  end;
2726
  ProtectBuffer(K, SizeOf(K));
2727
end;
2728
 
2729
procedure TCipher_RC6.DoEncode(Source, Dest: Pointer; Size: Integer);
2730
{$IFDEF UseASM}
2731
asm
2732
      PUSH  EBX
2733
      PUSH  ESI
2734
      PUSH  EDI
2735
      PUSH  EBP
2736
      PUSH  ECX
2737
      MOV   EBP,[EAX].TCipher_RC6.FRounds  // Rounds
2738
      MOV   ESI,[EAX].TCipher_RC6.FUser    // Key
2739
      MOV   EAX,[EDX +  0]   // A
2740
      MOV   EBX,[EDX +  4]   // B
2741
      MOV   EDI,[EDX +  8]   // C
2742
      MOV   EDX,[EDX + 12]   // D
2743
      ADD   EBX,[ESI + 0]    // Inc(B, K[0])
2744
      ADD   EDX,[ESI + 4]    // Inc(D, K[1])
2745
      ADD   ESI,8            // Inc(PInteger(K), 2)
2746
@@1:  LEA   ECX,[EBX * 2 +1] // ECX := B * 2 +1
2747
      IMUL  ECX,EBX          // ECX := ECX * B
2748
      ROL   ECX,5            // T := ROL(B * (B * 2 +1), 5)
2749
      PUSH  ECX              // save T
2750
      XOR   EAX,ECX          // A := A xor T
2751
      LEA   ECX,[EDX * 2 +1] // ECX := D * 2 +1
2752
      IMUL  ECX,EDX          // ECX := ECX * D
2753
      ROL   ECX,5            // U := ROL(D * (D * 2 +1), 5)
2754
      XOR   EDI,ECX          // C := C xor U
2755
      ROL   EAX,CL           // A := ROL(A xor T, U)
2756
      POP   ECX              // restore T
2757
      ADD   EAX,[ESI + 0]    // Inc(A, K[0])
2758
      ROL   EDI,CL           // C := ROL(C xor U, T)
2759
      MOV   ECX,EAX          // T := A
2760
      ADD   EDI,[ESI + 4]    // Inc(C, K[1])
2761
      MOV   EAX,EBX          // A := B
2762
      MOV   EBX,EDI          // B := C
2763
      MOV   EDI,EDX          // C := D
2764
      DEC   EBP
2765
      MOV   EDX,ECX          // D := T;
2766
      LEA   ESI,[ESI + 8]    // Inc(PInteger(K), 2)
2767
      JNZ   @@1
2768
      ADD   EAX,[ESI + 0]    // Inc(A, K[0])
2769
      ADD   EDI,[ESI + 4]    // Inc(C, K[1])
2770
      POP   ECX
2771
      MOV   [ECX +  0],EAX   // A
2772
      MOV   [ECX +  4],EBX   // B
2773
      MOV   [ECX +  8],EDI   // C
2774
      MOV   [ECX + 12],EDX   // D
2775
      POP   EBP
2776
      POP   EDI
2777
      POP   ESI
2778
      POP   EBX
2779
end;
2780
{$ELSE}
2781
var
2782
  K: PLongArray;
2783
  I,T,U,A,B,C,D: LongWord;
2784
begin
2785
  Assert(Size = Context.BlockSize);
2786
 
2787
  K := FUser;
2788
  A := PLongArray(Source)[0];
2789
  B := PLongArray(Source)[1] + K[0];
2790
  C := PLongArray(Source)[2];
2791
  D := PLongArray(Source)[3] + K[1];
2792
  for I := 1 to FRounds do
2793
  begin
2794
    K := @K[2];
2795
    T := B * (B + B +1);
2796
    T := T shl 5 or T shr 27;
2797
    U := D * (D + D +1);
2798
    U := U shl 5 or U shr 27;
2799
    A := A xor T;
2800
    A := A shl U or A shr (32 - U) + K[0];
2801
    C := C xor U;
2802
    C := C shl T or C shr (32 - T) + K[1];
2803
    T := A; A := B; B := C; C := D; D := T;
2804
  end;
2805
  PLongArray(Dest)[0] := A + K[2];
2806
  PLongArray(Dest)[1] := B;
2807
  PLongArray(Dest)[2] := C + K[3];
2808
  PLongArray(Dest)[3] := D;
2809
end;
2810
{$ENDIF}
2811
 
2812
procedure TCipher_RC6.DoDecode(Source, Dest: Pointer; Size: Integer);
2813
{$IFDEF UseASM}
2814
asm
2815
      PUSH  EBX
2816
      PUSH  ESI
2817
      PUSH  EDI
2818
      PUSH  EBP
2819
      PUSH  ECX
2820
      MOV   EBP,[EAX].TCipher_RC6.FRounds  // Rounds
2821
      MOV   ESI,[EAX].TCipher_RC6.FUser    // Key
2822
      LEA   ESI,[ESI + EBP * 8]            // Key[FRounds * 2]
2823
      MOV   EAX,[EDX +  0]   // A
2824
      MOV   EBX,[EDX +  4]   // B
2825
      MOV   EDI,[EDX +  8]   // C
2826
      MOV   EDX,[EDX + 12]   // D
2827
      SUB   EDI,[ESI + 12]   // Dec(C, K[3])
2828
      SUB   EAX,[ESI +  8]   // Dec(A, K[2])
2829
@@1:  MOV   ECX,EAX          // T := A
2830
      SUB   EDX,[ESI + 0]    // Dec(A, K[0])
2831
      MOV   EAX,EDX          // A := D
2832
      MOV   EDX,EDI          // D := C
2833
      SUB   EBX,[ESI + 4]    // Dec(C, K[1])
2834
      MOV   EDI,EBX          // C := B
2835
      MOV   EBX,ECX          // B := T;
2836
      LEA   ECX,[EDX * 2 +1] // ECX := D * 2 +1
2837
      IMUL  ECX,EDX          // ECX := ECX * D
2838
      ROL   ECX,5            // U := ROL(D * (D * 2 +1), 5)
2839
      PUSH  ECX              // save U
2840
      ROR   EAX,CL           // A := ROR(A - K[0], U)
2841
      LEA   ECX,[EBX * 2 +1] // ECX := B * 2 +1
2842
      IMUL  ECX,EBX          // ECX := ECX * B
2843
      ROL   ECX,5            // T := ROL(B * (B * 2 +1), 5)
2844
      XOR   EAX,ECX          // A := A xor T
2845
      ROR   EDI,CL           // C := ROR(C - K[1], T)
2846
      POP   ECX              // restore U
2847
      XOR   EDI,ECX          // C := C xor U
2848
      DEC   EBP
2849
      LEA   ESI,[ESI - 8]    // Dec(PInteger(K), 2)
2850
      JNZ   @@1
2851
      SUB   EBX,[ESI + 0]    // Dec(B, K[0])
2852
      SUB   EDX,[ESI + 4]    // Inc(D, K[1])
2853
      POP   ECX
2854
      MOV   [ECX +  0],EAX   // A
2855
      MOV   [ECX +  4],EBX   // B
2856
      MOV   [ECX +  8],EDI   // C
2857
      MOV   [ECX + 12],EDX   // D
2858
      POP   EBP
2859
      POP   EDI
2860
      POP   ESI
2861
      POP   EBX
2862
end;
2863
{$ELSE}
2864
var
2865
  I,U,T,A,B,C,D: LongWord;
2866
  K: PLongArray;
2867
begin
2868
  Assert(Size = Context.BlockSize);
2869
 
2870
  K := @PLongArray(FUser)[FRounds * 2];
2871
  A := PLongArray(Source)[0] - K[2];
2872
  B := PLongArray(Source)[1];
2873
  C := PLongArray(Source)[2] - K[3];
2874
  D := PLongArray(Source)[3];
2875
  for I := 1 to FRounds do
2876
  begin
2877
    T := A; A := D; D := C; C := B; B := T;
2878
    U := D * (D + D +1);
2879
    U := U shl 5 or U shr 27;
2880
    T := B * (B + B +1);
2881
    T := T shl 5 or T shr 27;
2882
    C := C - K[1];
2883
    C := C shr T or C shl (32 - T) xor U;
2884
    A := A - K[0];
2885
    A := A shr U or A shl (32 - U) xor T;
2886
    Dec(PLongWord(K), 2);
2887
  end;
2888
  PLongArray(Dest)[0] := A;
2889
  PLongArray(Dest)[1] := B - K[0];
2890
  PLongArray(Dest)[2] := C;
2891
  PLongArray(Dest)[3] := D - K[1];
2892
end;
2893
{$ENDIF}
2894
 
2895
// .TCipher_Rijndael
2896
const
2897
{don't change this}
2898
  Rijndael_Blocks =  4;
2899
  Rijndael_Rounds = 14;
2900
 
2901
class function TCipher_Rijndael.Context: TCipherContext;
2902
begin
2903
  Result.KeySize := 32;
2904
  Result.BlockSize := Rijndael_Blocks * 4;
2905
  Result.BufferSize := Rijndael_Blocks * 4;
2906
  Result.UserSize := (Rijndael_Rounds + 1) * Rijndael_Blocks * SizeOf(LongWord) * 2;
2907
  Result.UserSave := False;
2908
end;
2909
 
2910
procedure TCipher_Rijndael.DoInit(const Key; Size: Integer);
2911
{  old Rijndael keyshedulling
2912
 
2913
  procedure BuildEncodeKey;
2914
  const
2915
    RND_Data: array[0..29] of Byte = (
2916
      $01,$02,$04,$08,$10,$20,$40,$80,$1B,$36,$6C,$D8,$AB,$4D,$9A,
2917
      $2F,$5E,$BC,$63,$C6,$97,$35,$6A,$D4,$B3,$7D,$FA,$EF,$C5,$91);
2918
  var
2919
    T,R: Integer;
2920
 
2921
    procedure NextRounds;
2922
    var
2923
      J: Integer;
2924
    begin
2925
      J := 0;
2926
      while (J < FRounds -6) and (R <= FRounds) do
2927
      begin
2928
        while (J < FRounds -6) and (T < Rijndael_Blocks) do
2929
        begin
2930
          PLongArray(FUser)[R * Rijndael_Blocks + T] := K[J];
2931
          Inc(J);
2932
          Inc(T);
2933
        end;
2934
        if T = Rijndael_Blocks then
2935
        begin
2936
          T := 0;
2937
          Inc(R);
2938
        end;
2939
      end;
2940
    end;
2941
 
2942
  var
2943
    RND: PByte;
2944
    B: PByte;
2945
    I: Integer;
2946
  begin
2947
    R := 0;
2948
    T := 0;
2949
    RND := @RND_Data;
2950
    NextRounds;
2951
    while R <= FRounds do
2952
    begin
2953
      B  := @K;
2954
      B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr  8 and $FF] xor RND^; Inc(B);
2955
      B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 16 and $FF];          Inc(B);
2956
      B^ := B^ xor Rijndael_S[0, K[FRounds -7] shr 24];                  Inc(B);
2957
      B^ := B^ xor Rijndael_S[0, K[FRounds -7] and $FF];
2958
      Inc(RND);
2959
      if FRounds = 14 then
2960
      begin
2961
        for I := 1 to 7 do K[I] := K[I] xor K[I -1];
2962
        B  := @K[4];
2963
        B^ := B^ xor Rijndael_S[0, K[3] and $FF];         Inc(B);
2964
        B^ := B^ xor Rijndael_S[0, K[3] shr  8 and $FF];  Inc(B);
2965
        B^ := B^ xor Rijndael_S[0, K[3] shr 16 and $FF];  Inc(B);
2966
        B^ := B^ xor Rijndael_S[0, K[3] shr 24];
2967
        for I := 5 to 7 do K[I] := K[I] xor K[I -1];
2968
      end else
2969
        for I := 1 to FRounds -7 do K[I] := K[I] xor K[I -1];
2970
      NextRounds;
2971
    end;
2972
  end;
2973
 
2974
  procedure BuildDecodeKey;
2975
  var
2976
    I: Integer;
2977
    D: PLongWord;
2978
  begin
2979
    D := Pointer(PChar(FUser) + FUserSize shr 1);
2980
    Move(FUser^, D^, FUserSize shr 1);
2981
    Inc(D, 4);
2982
    for I := 0 to FRounds * 4 - 5 do
2983
    begin
2984
      D^ :=  Rijndael_Key[D^ and $FF] xor
2985
            (Rijndael_Key[D^ shr  8 and $FF] shl  8 or Rijndael_Key[D^ shr  8 and $FF] shr 24) xor
2986
            (Rijndael_Key[D^ shr 16 and $FF] shl 16 or Rijndael_Key[D^ shr 16 and $FF] shr 16) xor
2987
            (Rijndael_Key[D^ shr 24]         shl 24 or Rijndael_Key[D^ shr 24]          shr 8);
2988
      Inc(D);
2989
    end;
2990
  end; }
2991
 
2992
// new AES conform Keyshedulling
2993
 
2994
  procedure BuildEncodeKey;
2995
  const
2996
    RCon: array[0..9] of LongWord = ($01,$02,$04,$08,$10,$20,$40,$80,$1b,$36);
2997
  var
2998
    I: Integer;
2999
    T: LongWord;
3000
    P: PLongArray;
3001
  begin
3002
    P := FUser;
3003
    if Size <= 16 then
3004
    begin
3005
      for I := 0 to 9 do
3006
      begin
3007
        T := P[3];
3008
        P[4] := Rijndael_S[0, T shr  8 and $FF]        xor
3009
                Rijndael_S[0, T shr 16 and $FF] shl  8 xor
3010
                Rijndael_S[0, T shr 24        ] shl 16 xor
3011
                Rijndael_S[0, T        and $FF] shl 24 xor P[0] xor RCon[I];
3012
        P[5] := P[1] xor P[4];
3013
        P[6] := P[2] xor P[5];
3014
        P[7] := P[3] xor P[6];
3015
        P    := @P[4];
3016
      end;
3017
    end else
3018
      if Size <= 24 then
3019
      begin
3020
        for I := 0 to 7 do
3021
        begin
3022
          T := P[5];
3023
          P[6] := Rijndael_S[0, T shr  8 and $FF]        xor
3024
                  Rijndael_S[0, T shr 16 and $FF] shl  8 xor
3025
                  Rijndael_S[0, T shr 24        ] shl 16 xor
3026
                  Rijndael_S[0, T        and $FF] shl 24 xor P[0] xor RCon[I];
3027
          P[7] := P[1] xor P[6];
3028
          P[8] := P[2] xor P[7];
3029
          P[9] := P[3] xor P[8];
3030
          if I = 7 then Break;
3031
          P[10] := P[4] xor P[9];
3032
          P[11] := P[5] xor P[10];
3033
          P     := @P[6];
3034
        end;
3035
      end else
3036
      begin
3037
        for I :=0 to 6 do
3038
        begin
3039
          T := P[7];
3040
          P[8] := Rijndael_S[0, T shr  8 and $FF]        xor
3041
                  Rijndael_S[0, T shr 16 and $FF] shl  8 xor
3042
                  Rijndael_S[0, T shr 24        ] shl 16 xor
3043
                  Rijndael_S[0, T        and $FF] shl 24 xor P[0] xor RCon[I];
3044
          P[9] := P[1] xor P[8];
3045
          P[10] := P[2] xor P[9];
3046
          P[11] := P[3] xor P[10];
3047
          if I = 6 then Break;
3048
          T := P[11];
3049
          P[12] := Rijndael_S[0, T        and $FF]        xor
3050
                   Rijndael_S[0, T shr  8 and $FF] shl  8 xor
3051
                   Rijndael_S[0, T shr 16 and $FF] shl 16 xor
3052
                   Rijndael_S[0, T shr 24        ] shl 24 xor P[4];
3053
          P[13] := P[5] xor P[12];
3054
          P[14] := P[6] xor P[13];
3055
          P[15] := P[7] xor P[14];
3056
          P     := @P[8];
3057
        end;
3058
      end;
3059
  end;
3060
 
3061
 
3062
  procedure BuildDecodeKey;
3063
  var
3064
    P: PLongWord;
3065
    I: Integer;
3066
  begin
3067
    P := Pointer(PChar(FUser) + FUserSize shr 1);
3068
    Move(FUser^, P^, FUserSize shr 1);
3069
    Inc(P, 4);
3070
    for I := 0 to FRounds * 4 -5 do
3071
    begin
3072
      P^ := Rijndael_T[4, Rijndael_S[0, P^        and $FF]] xor
3073
            Rijndael_T[5, Rijndael_S[0, P^ shr  8 and $FF]] xor
3074
            Rijndael_T[6, Rijndael_S[0, P^ shr 16 and $FF]] xor
3075
            Rijndael_T[7, Rijndael_S[0, P^ shr 24        ]];
3076
      Inc(P);
3077
    end;
3078
  end;
3079
 
3080
 
3081
begin
3082
  if Size <= 16 then FRounds := 10 else
3083
    if Size <= 24 then FRounds := 12
3084
      else FRounds := 14;
3085
  FillChar(FUser^, 32, 0);      
3086
  Move(Key, FUser^, Size);
3087
  BuildEncodeKey;
3088
  BuildDecodeKey;
3089
end;
3090
 
3091
procedure TCipher_Rijndael.DoEncode(Source, Dest: Pointer; Size: Integer);
3092
var
3093
  P: PLongArray;
3094
  I: Integer;
3095
  A2,B2,C2,D2: LongWord;
3096
  A1,B1,C1,D1: LongWord;
3097
begin
3098
  Assert(Size = Context.BlockSize);
3099
  P  := FUser;
3100
  A1 := PLongArray(Source)[0];
3101
  B1 := PLongArray(Source)[1];
3102
  C1 := PLongArray(Source)[2];
3103
  D1 := PLongArray(Source)[3];
3104
  for I := 2 to FRounds do
3105
  begin
3106
    A2 := A1 xor P[0];
3107
    B2 := B1 xor P[1];
3108
    C2 := C1 xor P[2];
3109
    D2 := D1 xor P[3];
3110
 
3111
    A1 := Rijndael_T[0, A2        and $FF] xor
3112
          Rijndael_T[1, B2 shr  8 and $FF] xor
3113
          Rijndael_T[2, C2 shr 16 and $FF] xor
3114
          Rijndael_T[3, D2 shr 24        ];
3115
    B1 := Rijndael_T[0, B2        and $FF] xor
3116
          Rijndael_T[1, C2 shr  8 and $FF] xor
3117
          Rijndael_T[2, D2 shr 16 and $FF] xor
3118
          Rijndael_T[3, A2 shr 24        ];
3119
    C1 := Rijndael_T[0, C2        and $FF] xor
3120
          Rijndael_T[1, D2 shr  8 and $FF] xor
3121
          Rijndael_T[2, A2 shr 16 and $FF] xor
3122
          Rijndael_T[3, B2 shr 24        ];
3123
    D1 := Rijndael_T[0, D2        and $FF] xor
3124
          Rijndael_T[1, A2 shr  8 and $FF] xor
3125
          Rijndael_T[2, B2 shr 16 and $FF] xor
3126
          Rijndael_T[3, C2 shr 24        ];
3127
 
3128
    P := @P[4];
3129
  end;
3130
 
3131
  A2 := A1 xor P[0];
3132
  B2 := B1 xor P[1];
3133
  C2 := C1 xor P[2];
3134
  D2 := D1 xor P[3];
3135
 
3136
  PLongArray(Dest)[0] := (Rijndael_S[0, A2        and $FF]        or
3137
                          Rijndael_S[0, B2 shr  8 and $FF] shl  8 or
3138
                          Rijndael_S[0, C2 shr 16 and $FF] shl 16 or
3139
                          Rijndael_S[0, D2 shr 24        ] shl 24)     xor P[4];
3140
  PLongArray(Dest)[1] := (Rijndael_S[0, B2        and $FF]        or
3141
                          Rijndael_S[0, C2 shr  8 and $FF] shl  8 or
3142
                          Rijndael_S[0, D2 shr 16 and $FF] shl 16 or
3143
                          Rijndael_S[0, A2 shr 24        ] shl 24)     xor P[5];
3144
  PLongArray(Dest)[2] := (Rijndael_S[0, C2        and $FF]        or
3145
                          Rijndael_S[0, D2 shr  8 and $FF] shl  8 or
3146
                          Rijndael_S[0, A2 shr 16 and $FF] shl 16 or
3147
                          Rijndael_S[0, B2 shr 24        ] shl 24)     xor P[6];
3148
  PLongArray(Dest)[3] := (Rijndael_S[0, D2        and $FF]        or
3149
                          Rijndael_S[0, A2 shr  8 and $FF] shl  8 or
3150
                          Rijndael_S[0, B2 shr 16 and $FF] shl 16 or
3151
                          Rijndael_S[0, C2 shr 24        ] shl 24)     xor P[7];
3152
end;
3153
 
3154
procedure TCipher_Rijndael.DoDecode(Source, Dest: Pointer; Size: Integer);
3155
var
3156
  P: PLongArray;
3157
  I: Integer;
3158
  A2,B2,C2,D2: LongWord;
3159
  A1,B1,C1,D1: LongWord;
3160
begin
3161
  Assert(Size = Context.BlockSize);
3162
 
3163
  P  := Pointer(PChar(FUser) + FUserSize shr 1 + FRounds * 16);
3164
  A1 := PLongArray(Source)[0];
3165
  B1 := PLongArray(Source)[1];
3166
  C1 := PLongArray(Source)[2];
3167
  D1 := PLongArray(Source)[3];
3168
 
3169
  for I := 2 to FRounds do
3170
  begin
3171
    A2 := A1 xor P[0];
3172
    B2 := B1 xor P[1];
3173
    C2 := C1 xor P[2];
3174
    D2 := D1 xor P[3];
3175
 
3176
    A1 := Rijndael_T[4, A2        and $FF] xor
3177
          Rijndael_T[5, D2 shr  8 and $FF] xor
3178
          Rijndael_T[6, C2 shr 16 and $FF] xor
3179
          Rijndael_T[7, B2 shr 24        ];
3180
    B1 := Rijndael_T[4, B2        and $FF] xor
3181
          Rijndael_T[5, A2 shr  8 and $FF] xor
3182
          Rijndael_T[6, D2 shr 16 and $FF] xor
3183
          Rijndael_T[7, C2 shr 24        ];
3184
    C1 := Rijndael_T[4, C2        and $FF] xor
3185
          Rijndael_T[5, B2 shr  8 and $FF] xor
3186
          Rijndael_T[6, A2 shr 16 and $FF] xor
3187
          Rijndael_T[7, D2 shr 24        ];
3188
    D1 := Rijndael_T[4, D2        and $FF] xor
3189
          Rijndael_T[5, C2 shr  8 and $FF] xor
3190
          Rijndael_T[6, B2 shr 16 and $FF] xor
3191
          Rijndael_T[7, A2 shr 24        ];
3192
 
3193
    Dec(PLongWord(P), 4);
3194
  end;
3195
 
3196
  A2 := A1 xor P[0];
3197
  B2 := B1 xor P[1];
3198
  C2 := C1 xor P[2];
3199
  D2 := D1 xor P[3];
3200
 
3201
  Dec(PLongWord(P), 4);
3202
 
3203
  PLongArray(Dest)[0] := (Rijndael_S[1, A2        and $FF]        or
3204
                          Rijndael_S[1, D2 shr  8 and $FF] shl  8 or
3205
                          Rijndael_S[1, C2 shr 16 and $FF] shl 16 or
3206
                          Rijndael_S[1, B2 shr 24]         shl 24)    xor P[0];
3207
  PLongArray(Dest)[1] := (Rijndael_S[1, B2        and $FF]        or
3208
                          Rijndael_S[1, A2 shr  8 and $FF] shl  8 or
3209
                          Rijndael_S[1, D2 shr 16 and $FF] shl 16 or
3210
                          Rijndael_S[1, C2 shr 24]         shl 24)    xor P[1];
3211
  PLongArray(Dest)[2] := (Rijndael_S[1, C2        and $FF]        or
3212
                          Rijndael_S[1, B2 shr  8 and $FF] shl  8 or
3213
                          Rijndael_S[1, A2 shr 16 and $FF] shl 16 or
3214
                          Rijndael_S[1, D2 shr 24]         shl 24)    xor P[2];
3215
  PLongArray(Dest)[3] := (Rijndael_S[1, D2        and $FF]        or
3216
                          Rijndael_S[1, C2 shr  8 and $FF] shl  8 or
3217
                          Rijndael_S[1, B2 shr 16 and $FF] shl 16 or
3218
                          Rijndael_S[1, A2 shr 24]         shl 24)    xor P[3];
3219
end;
3220
 
3221
// .TCipher_Square
3222
class function TCipher_Square.Context: TCipherContext;
3223
begin
3224
  Result.KeySize := 16;
3225
  Result.BlockSize := 16;
3226
  Result.BufferSize := 16;
3227
  Result.UserSize := 9 * 4 * 2 * SizeOf(LongWord);
3228
  Result.UserSave := False;
3229
end;
3230
 
3231
procedure TCipher_Square.DoInit(const Key; Size: Integer);
3232
type
3233
  PSquare_Key = ^TSquare_Key;
3234
  TSquare_Key = array[0..8, 0..3] of LongWord;
3235
var
3236
  E,D: PSquare_Key;
3237
  S,T,R: LongWord;
3238
  I,J: Integer;
3239
begin
3240
  E := FUser;
3241
  D := FUser; Inc(D);
3242
  Move(Key, E^, Size);
3243
  for I := 1 to 8 do
3244
  begin
3245
    T := E[I -1, 3];
3246
    T := T shr 8 or T shl 24;
3247
    E[I, 0] := E[I -1, 0] xor T xor 1 shl (I - 1);
3248
    E[I, 1] := E[I -1, 1] xor E[I, 0];
3249
    E[I, 2] := E[I -1, 2] xor E[I, 1];
3250
    E[I, 3] := E[I -1, 3] xor E[I, 2];
3251
 
3252
    D[8 -I, 0] := E[I, 0];
3253
    D[8 -I, 1] := E[I, 1];
3254
    D[8 -I, 2] := E[I, 2];
3255
    D[8 -I, 3] := E[I, 3];
3256
 
3257
    for J := 0 to 3 do
3258
    begin
3259
      R := E[I -1, J];
3260
      S := Square_PHI[R and $FF];
3261
      T := Square_PHI[R shr  8 and $FF];
3262
      T := T shl 8 or T shr 24;
3263
      S := S xor T;
3264
      T := Square_PHI[R shr 16 and $FF];
3265
      T := T shl 16 or T shr 16;
3266
      S := S xor T;
3267
      T := Square_PHI[R shr 24];
3268
      T := T shl 24 or T shr 8;
3269
      S := S xor T;
3270
      E[I -1, J] := S;
3271
    end;
3272
  end;
3273
  D[8] := E[0];
3274
end;
3275
 
3276
procedure TCipher_Square.DoEncode(Source, Dest: Pointer; Size: Integer);
3277
var
3278
  Key: PLongArray;
3279
  A,B,C,D: LongWord;
3280
  AA,BB,CC: LongWord;
3281
  I: Integer;
3282
begin
3283
  Key := FUser;
3284
  A := PLongArray(Source)[0] xor Key[0];
3285
  B := PLongArray(Source)[1] xor Key[1];
3286
  C := PLongArray(Source)[2] xor Key[2];
3287
  D := PLongArray(Source)[3] xor Key[3];
3288
  Key := @Key[4];
3289
  for I := 0 to 6 do
3290
  begin
3291
    AA := Square_TE[0, A        and $FF] xor
3292
          Square_TE[1, B        and $FF] xor
3293
          Square_TE[2, C        and $FF] xor
3294
          Square_TE[3, D        and $FF] xor Key[0];
3295
    BB := Square_TE[0, A shr  8 and $FF] xor
3296
          Square_TE[1, B shr  8 and $FF] xor
3297
          Square_TE[2, C shr  8 and $FF] xor
3298
          Square_TE[3, D shr  8 and $FF] xor Key[1];
3299
    CC := Square_TE[0, A shr 16 and $FF] xor
3300
          Square_TE[1, B shr 16 and $FF] xor
3301
          Square_TE[2, C shr 16 and $FF] xor
3302
          Square_TE[3, D shr 16 and $FF] xor Key[2];
3303
    D  := Square_TE[0, A shr 24        ] xor
3304
          Square_TE[1, B shr 24        ] xor
3305
          Square_TE[2, C shr 24        ] xor
3306
          Square_TE[3, D shr 24        ] xor Key[3];
3307
 
3308
    A := AA; B := BB; C := CC;
3309
 
3310
    Key := @Key[4];
3311
  end;
3312
 
3313
  PLongArray(Dest)[0] := LongWord(Square_SE[A        and $FF])        xor
3314
                         LongWord(Square_SE[B        and $FF]) shl  8 xor
3315
                         LongWord(Square_SE[C        and $FF]) shl 16 xor
3316
                         LongWord(Square_SE[D        and $FF]) shl 24 xor Key[0];
3317
  PLongArray(Dest)[1] := LongWord(Square_SE[A shr  8 and $FF])        xor
3318
                         LongWord(Square_SE[B shr  8 and $FF]) shl  8 xor
3319
                         LongWord(Square_SE[C shr  8 and $FF]) shl 16 xor
3320
                         LongWord(Square_SE[D shr  8 and $FF]) shl 24 xor Key[1];
3321
  PLongArray(Dest)[2] := LongWord(Square_SE[A shr 16 and $FF])        xor
3322
                         LongWord(Square_SE[B shr 16 and $FF]) shl  8 xor
3323
                         LongWord(Square_SE[C shr 16 and $FF]) shl 16 xor
3324
                         LongWord(Square_SE[D shr 16 and $FF]) shl 24 xor Key[2];
3325
  PLongArray(Dest)[3] := LongWord(Square_SE[A shr 24        ])        xor
3326
                         LongWord(Square_SE[B shr 24        ]) shl  8 xor
3327
                         LongWord(Square_SE[C shr 24        ]) shl 16 xor
3328
                         LongWord(Square_SE[D shr 24        ]) shl 24 xor Key[3];
3329
end;
3330
 
3331
procedure TCipher_Square.DoDecode(Source, Dest: Pointer; Size: Integer);
3332
var
3333
  Key: PLongArray;
3334
  A,B,C,D: LongWord;
3335
  AA,BB,CC: LongWord;
3336
  I: Integer;
3337
begin
3338
  Key := @PLongArray(FUser)[9 * 4];
3339
  A := PLongArray(Source)[0] xor Key[0];
3340
  B := PLongArray(Source)[1] xor Key[1];
3341
  C := PLongArray(Source)[2] xor Key[2];
3342
  D := PLongArray(Source)[3] xor Key[3];
3343
  Key := @Key[4];
3344
  for I := 0 to 6 do
3345
  begin
3346
    AA := Square_TD[0, A        and $FF] xor
3347
          Square_TD[1, B        and $FF] xor
3348
          Square_TD[2, C        and $FF] xor
3349
          Square_TD[3, D        and $FF] xor Key[0];
3350
    BB := Square_TD[0, A shr  8 and $FF] xor
3351
          Square_TD[1, B shr  8 and $FF] xor
3352
          Square_TD[2, C shr  8 and $FF] xor
3353
          Square_TD[3, D shr  8 and $FF] xor Key[1];
3354
    CC := Square_TD[0, A shr 16 and $FF] xor
3355
          Square_TD[1, B shr 16 and $FF] xor
3356
          Square_TD[2, C shr 16 and $FF] xor
3357
          Square_TD[3, D shr 16 and $FF] xor Key[2];
3358
    D  := Square_TD[0, A shr 24        ] xor
3359
          Square_TD[1, B shr 24        ] xor
3360
          Square_TD[2, C shr 24        ] xor
3361
          Square_TD[3, D shr 24        ] xor Key[3];
3362
 
3363
    A := AA; B := BB; C := CC;
3364
    Key := @Key[4];
3365
  end;
3366
 
3367
  PLongArray(Dest)[0] := LongWord(Square_SD[A        and $FF])        xor
3368
                         LongWord(Square_SD[B        and $FF]) shl  8 xor
3369
                         LongWord(Square_SD[C        and $FF]) shl 16 xor
3370
                         LongWord(Square_SD[D        and $FF]) shl 24 xor Key[0];
3371
  PLongArray(Dest)[1] := LongWord(Square_SD[A shr  8 and $FF])        xor
3372
                         LongWord(Square_SD[B shr  8 and $FF]) shl  8 xor
3373
                         LongWord(Square_SD[C shr  8 and $FF]) shl 16 xor
3374
                         LongWord(Square_SD[D shr  8 and $FF]) shl 24 xor Key[1];
3375
  PLongArray(Dest)[2] := LongWord(Square_SD[A shr 16 and $FF])        xor
3376
                         LongWord(Square_SD[B shr 16 and $FF]) shl  8 xor
3377
                         LongWord(Square_SD[C shr 16 and $FF]) shl 16 xor
3378
                         LongWord(Square_SD[D shr 16 and $FF]) shl 24 xor Key[2];
3379
  PLongArray(Dest)[3] := LongWord(Square_SD[A shr 24        ])        xor
3380
                         LongWord(Square_SD[B shr 24        ]) shl  8 xor
3381
                         LongWord(Square_SD[C shr 24        ]) shl 16 xor
3382
                         LongWord(Square_SD[D shr 24        ]) shl 24 xor Key[3];
3383
end;
3384
 
3385
// .TCipher_SCOP
3386
class function TCipher_SCOP.Context: TCipherContext;
3387
begin
3388
  Result.KeySize := 48;
3389
  Result.BlockSize := 4;
3390
  Result.BufferSize := 32;
3391
  Result.UserSize := 384 * 4 + 3 * SizeOf(LongWord);
3392
  Result.UserSave := True;
3393
end;
3394
 
3395
procedure TCipher_SCOP.DoInit(const Key; Size: Integer);
3396
var
3397
  Init_State: packed record
3398
                Coef: array[0..7, 0..3] of Byte;
3399
                X: array[0..3] of LongWord;
3400
              end;
3401
 
3402
  procedure ExpandKey;
3403
  var
3404
    P: PByteArray;
3405
    I,C: Integer;
3406
  begin
3407
    C := 1;
3408
    P := @Init_State;
3409
    Move(Key, P^, Size);
3410
    for I := Size to 47 do P[I] := P[I - Size] + P[I - Size +1];
3411
    for I := 0 to 31 do
3412
      if P[I] = 0 then
3413
      begin
3414
        P[I] := C;
3415
        Inc(C);
3416
      end;
3417
  end;
3418
 
3419
  procedure GP8(Data: PLongArray);
3420
  var
3421
    I,I2: Integer;
3422
    NewX: array[0..3] of LongWord;
3423
    X1,X2,X3,X4: LongWord;
3424
    Y1,Y2: LongWord;
3425
  begin
3426
    I := 0;
3427
    I2 := 0;
3428
    while I < 8 do
3429
    begin
3430
      X1 := Init_State.X[I2] shr 16;
3431
      X2 := X1 * X1;
3432
      X3 := X2 * X1;
3433
      X4 := X3 * X1;
3434
      Y1 := Init_State.Coef[I][0] * X4 +
3435
            Init_State.Coef[I][1] * X3 +
3436
            Init_State.Coef[I][2] * X2 +
3437
            Init_State.Coef[I][3] * X1 + 1;
3438
      X1 := Init_State.X[I2] and $FFFF;
3439
      X2 := X1 * X1;
3440
      X3 := X2 * X1;
3441
      X4 := X3 * X1;
3442
      Y2 := Init_State.Coef[I +1][0] * X4 +
3443
            Init_State.Coef[I +2][1] * X3 +
3444
            Init_State.Coef[I +3][2] * X2 +
3445
            Init_State.Coef[I +4][3] * X1 + 1;
3446
      Data[I2] := Y1 shl 16 or Y2 and $FFFF;
3447
      NewX[I2] := Y1 and $FFFF0000 or Y2 shr 16;
3448
      Inc(I2);
3449
      Inc(I, 2);
3450
    end;
3451
    Init_State.X[0] := NewX[0] shr 16 or NewX[3] shl 16;
3452
    Init_State.X[1] := NewX[0] shl 16 or NewX[1] shr 16;
3453
    Init_State.X[2] := NewX[1] shl 16 or NewX[2] shr 16;
3454
    Init_State.X[3] := NewX[2] shl 16 or NewX[3] shr 16;
3455
  end;
3456
 
3457
var
3458
  I,J: Integer;
3459
  T: array[0..3] of Integer;
3460
  P: PLongArray;
3461
begin
3462
  FillChar(Init_State, SizeOf(Init_State), 0);
3463
  FillChar(T, SizeOf(T), 0);
3464
  P := Pointer(PChar(FUser) + 12);
3465
  ExpandKey;
3466
  for I := 0 to 7 do GP8(@T);
3467
  for I := 0 to 11 do
3468
  begin
3469
    for J := 0 to 7 do GP8(@P[I * 32 + J * 4]);
3470
    GP8(@T);
3471
  end;
3472
  GP8(@T);
3473
  I := T[3] and $7F;
3474
  P[I + 3] := P[I + 3] or 1;
3475
  P := FUser;
3476
  P[0] := T[3] shr 24 and $FF;
3477
  P[1] := T[3] shr 16 and $FF;
3478
  P[2] := T[3] shr  8 and $FF;
3479
  ProtectBuffer(Init_State, SizeOf(Init_State));
3480
end;
3481
 
3482
procedure TCipher_SCOP.DoEncode(Source, Dest: Pointer; Size: Integer);
3483
var
3484
  I,J: Byte;
3485
  T2,T3,T1: LongWord;
3486
  P: PLongArray;
3487
  W: Integer;
3488
begin
3489
  P  := FUser;
3490
  I  := P[0];
3491
  J  := P[1];
3492
  T3 := P[2];
3493
  for W := 0 to Size div 4 -1 do
3494
  begin
3495
    T1 := P[J + 3 + 128]; Inc(J, T3);
3496
    T2 := P[J + 3 + 128];
3497
    PLongArray(Dest)[W] := PLongArray(Source)[W] + T1 + T2;
3498
    T3 := T2 + P[I + 3];  Inc(I);
3499
    P[J + 3 + 128] := T3;
3500
    Inc(J, T2);
3501
  end;
3502
  P[0] := I;
3503
  P[1] := J;
3504
  P[2] := T3;
3505
end;
3506
 
3507
procedure TCipher_SCOP.DoDecode(Source, Dest: Pointer; Size: Integer);
3508
var
3509
  I, J: Byte;
3510
  T1,T2,T3: LongWord;
3511
  P: PLongArray;
3512
  W: Integer;
3513
begin
3514
  P  := FUser;
3515
  I  := P[0];
3516
  J  := P[1];
3517
  T3 := P[2];
3518
  for W := 0 to Size div 4 -1 do
3519
  begin
3520
    T1 := P[J + 3 + 128]; Inc(J, T3);
3521
    T2 := P[J + 3 + 128];
3522
    PLongArray(Dest)[W] := PLongArray(Source)[W] - T1 - T2;
3523
    T3 := T2 + P[I + 3];
3524
    Inc(I);
3525
    P[J + 3 + 128] := T3;
3526
    Inc(J, T2);
3527
  end;
3528
  P[0] := I;
3529
  P[1] := J;
3530
  P[2] := T3;
3531
end;
3532
 
3533
 
3534
// .TCipher_Sapphire
3535
type
3536
  PSapphireKey = ^TSapphireKey;
3537
  TSapphireKey = packed record
3538
                   Cards: array[0..255] of LongWord;
3539
                   Rotor: LongWord;
3540
                   Ratchet: LongWord;
3541
                   Avalanche: LongWord;
3542
                   Plain: LongWord;
3543
                   Cipher: LongWord;
3544
                 end;
3545
 
3546
class function TCipher_Sapphire.Context: TCipherContext;
3547
begin
3548
  Result.KeySize := 1024;
3549
  Result.BlockSize := 1;
3550
  Result.BufferSize := 32;
3551
  Result.UserSize := SizeOf(TSapphireKey);
3552
  Result.UserSave := True;
3553
end;
3554
 
3555
procedure TCipher_Sapphire.DoInit(const Key; Size: Integer);
3556
var
3557
  Sum: Byte;
3558
  P: Integer;
3559
 
3560
  function KeyRand(Max: LongWord): Byte;
3561
  var
3562
    I,M: LongWord;
3563
  begin
3564
    Result := 0;
3565
    if Max = 0 then Exit;
3566
    I := 0;
3567
    M := 1;
3568
    while M < Max do
3569
     Inc(M, M or 1);
3570
    repeat
3571
      Inc(Sum, TByteArray(Key)[P]);
3572
      Inc(P);
3573
      if P >= Size then
3574
      begin
3575
        P := 0;
3576
        Inc(Sum, Size);
3577
      end;
3578
      Result := M and Sum;
3579
      Inc(I);
3580
      if I > 11 then Result := Result mod Max;
3581
    until Result <= Max;
3582
  end;
3583
 
3584
var
3585
  I,S,T: Integer;
3586
begin
3587
  with PSapphireKey(FUser)^ do
3588
    if Size <= 0 then
3589
    begin
3590
      Rotor := 1;
3591
      Ratchet := 3;
3592
      Avalanche := 5;
3593
      Plain := 7;
3594
      Cipher := 11;
3595
      for I := 0 to 255 do Cards[I] := 255 - I;
3596
    end else
3597
    begin
3598
      for I := 0 to 255 do Cards[I] := I;
3599
      P   := 0;
3600
      Sum := 0;
3601
      for I := 255 downto 1 do
3602
      begin
3603
        S := KeyRand(I);
3604
        T := Cards[I];
3605
        Cards[I] := Cards[S];
3606
        Cards[S] := T;
3607
      end;
3608
      Rotor := Cards[1];
3609
      Ratchet := Cards[3];
3610
      Avalanche := Cards[5];
3611
      Plain := Cards[7];
3612
      Cipher := Cards[Sum];
3613
    end;
3614
end;
3615
 
3616
procedure TCipher_Sapphire.DoEncode(Source, Dest: Pointer; Size: Integer);
3617
var
3618
  T: LongWord;
3619
  I: Integer;
3620
begin
3621
  with PSapphireKey(FUser)^ do
3622
    for I := 0 to Size -1 do
3623
    begin
3624
      Ratchet := (Ratchet + Cards[Rotor]) and $FF;
3625
      Rotor := (Rotor + 1) and $FF;
3626
      T := Cards[Cipher];
3627
      Cards[Cipher] := Cards[Ratchet];
3628
      Cards[Ratchet] := Cards[Plain];
3629
      Cards[Plain] := Cards[Rotor];
3630
      Cards[Rotor] := T;
3631
      Avalanche := (Avalanche + Cards[T]) and $FF;
3632
      T := (Cards[Plain] + Cards[Cipher] + Cards[Avalanche]) and $FF;
3633
      Plain := PByteArray(Source)[I];
3634
      Cipher := Plain xor Cards[Cards[T]] xor Cards[(Cards[Ratchet] + Cards[Rotor]) and $FF];
3635
      PByteArray(Dest)[I] := Cipher;
3636
    end;
3637
end;
3638
 
3639
procedure TCipher_Sapphire.DoDecode(Source, Dest: Pointer; Size: Integer);
3640
var
3641
  T: LongWord;
3642
  I: Integer;
3643
begin
3644
  with PSapphireKey(FUser)^ do
3645
    for I := 0 to Size -1 do
3646
    begin
3647
      Ratchet := (Ratchet + Cards[Rotor]) and $FF;
3648
      Rotor := (Rotor + 1) and $FF;
3649
      T := Cards[Cipher];
3650
      Cards[Cipher] := Cards[Ratchet];
3651
      Cards[Ratchet] := Cards[Plain];
3652
      Cards[Plain] := Cards[Rotor];
3653
      Cards[Rotor] := T;
3654
      Avalanche := (Avalanche + Cards[T]) and $FF;
3655
      T := (Cards[Plain] + Cards[Cipher] + Cards[Avalanche]) and $FF;
3656
      Cipher := PByteArray(Source)[I];
3657
      Plain := Cipher xor Cards[Cards[T]] xor Cards[(Cards[Ratchet] + Cards[Rotor]) and $FF];
3658
      PByteArray(Dest)[I] := Plain;
3659
    end;
3660
end;
3661
 
3662
// .DES
3663
procedure DES_Func(Source, Dest, Key: PLongArray);
3664
var
3665
  L,R,X,Y,I: LongWord;
3666
begin
3667
  L := SwapLong(Source[0]);
3668
  R := SwapLong(Source[1]);
3669
 
3670
  X := (L shr  4 xor R) and $0F0F0F0F; R := R xor X; L := L xor X shl  4;
3671
  X := (L shr 16 xor R) and $0000FFFF; R := R xor X; L := L xor X shl 16;
3672
  X := (R shr  2 xor L) and $33333333; L := L xor X; R := R xor X shl  2;
3673
  X := (R shr  8 xor L) and $00FF00FF; L := L xor X; R := R xor X shl  8;
3674
 
3675
  R := R shl 1 or R shr 31;
3676
  X := (L xor R) and $AAAAAAAA;
3677
  R := R xor X;
3678
  L := L xor X;
3679
  L := L shl 1 or L shr 31;
3680
 
3681
  for I := 0 to 7 do
3682
  begin
3683
    X := (R shl 28 or R shr 4) xor Key[0];
3684
    Y := R xor Key[1];
3685
    L := L xor (DES_Data[0, X        and $3F] or DES_Data[1, X shr  8 and $3F] or
3686
                DES_Data[2, X shr 16 and $3F] or DES_Data[3, X shr 24 and $3F] or
3687
                DES_Data[4, Y        and $3F] or DES_Data[5, Y shr  8 and $3F] or
3688
                DES_Data[6, Y shr 16 and $3F] or DES_Data[7, Y shr 24 and $3F]);
3689
 
3690
    X := (L shl 28 or L shr 4) xor Key[2];
3691
    Y := L xor Key[3];
3692
    R := R xor (DES_Data[0, X        and $3F] or DES_Data[1, X shr  8 and $3F] or
3693
                DES_Data[2, X shr 16 and $3F] or DES_Data[3, X shr 24 and $3F] or
3694
                DES_Data[4, Y        and $3F] or DES_Data[5, Y shr  8 and $3F] or
3695
                DES_Data[6, Y shr 16 and $3F] or DES_Data[7, Y shr 24 and $3F]);
3696
    Key := @Key[4];            
3697
  end;
3698
 
3699
  R := R shl 31 or R shr 1;
3700
  X := (L xor R) and $AAAAAAAA;
3701
  R := R xor X;
3702
  L := L xor X;
3703
  L := L shl 31 or L shr 1;
3704
 
3705
  X := (L shr  8 xor R) and $00FF00FF; R := R xor X; L := L xor X shl  8;
3706
  X := (L shr  2 xor R) and $33333333; R := R xor X; L := L xor X shl  2;
3707
  X := (R shr 16 xor L) and $0000FFFF; L := L xor X; R := R xor X shl 16;
3708
  X := (R shr  4 xor L) and $0F0F0F0F; L := L xor X; R := R xor X shl  4;
3709
 
3710
  Dest[0] := SwapLong(R);
3711
  Dest[1] := SwapLong(L);
3712
end;
3713
 
3714
// .TCipher_1DES
3715
class function TCipher_1DES.Context: TCipherContext;
3716
begin
3717
  Result.KeySize := 8;
3718
  Result.BlockSize := 8;
3719
  Result.BufferSize := 8;
3720
  Result.UserSize := 32 * 4 * 2;
3721
  Result.UserSave := False;
3722
end;
3723
 
3724
procedure TCipher_1DES.DoInitKey(const Data: array of Byte; Key: PLongArray; Reverse: Boolean);
3725
const
3726
  ROT: array[0..15] of Byte = (1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28);
3727
var
3728
  I,J,L,M,N: LongWord;
3729
  PC_M,PC_R: array[0..55] of Byte;
3730
  K: array[0..31] of LongWord;
3731
begin
3732
  FillChar(K, SizeOf(K), 0);
3733
  for I := 0 to 55 do
3734
    if Data[DES_PC1[I] shr 3] and ($80 shr (DES_PC1[I] and $07)) <> 0 then PC_M[I] := 1
3735
      else PC_M[I] := 0;
3736
  for I := 0 to 15 do
3737
  begin
3738
    if Reverse then M := (15 - I) shl 1
3739
      else M := I shl 1;
3740
    N := M + 1;
3741
    for J := 0 to 27 do
3742
    begin
3743
      L := J + ROT[I];
3744
      if L < 28 then PC_R[J] := PC_M[L] else PC_R[J] := PC_M[L - 28];
3745
    end;
3746
    for J := 28 to 55 do
3747
    begin
3748
      L := J + ROT[I];
3749
      if L < 56 then PC_R[J] := PC_M[L] else PC_R[J] := PC_M[L - 28];
3750
    end;
3751
    L := $1000000;
3752
    for J := 0 to 23 do
3753
    begin
3754
      L := L shr 1;
3755
      if PC_R[DES_PC2[J     ]] <> 0 then K[M] := K[M] or L;
3756
      if PC_R[DES_PC2[J + 24]] <> 0 then K[N] := K[N] or L;
3757
    end;
3758
  end;
3759
  for I := 0 to 15 do
3760
  begin
3761
    M := I shl 1;
3762
    N := M + 1;
3763
    Key[0] := K[M] and $00FC0000 shl  6 or
3764
              K[M] and $00000FC0 shl 10 or
3765
              K[N] and $00FC0000 shr 10 or
3766
              K[N] and $00000FC0 shr  6;
3767
    Key[1] := K[M] and $0003F000 shl 12 or
3768
              K[M] and $0000003F shl 16 or
3769
              K[N] and $0003F000 shr  4 or
3770
              K[N] and $0000003F;
3771
    Key := @Key[2];
3772
  end;
3773
  ProtectBuffer(K, SizeOf(K));
3774
  ProtectBuffer(PC_M, SizeOf(PC_M));
3775
  ProtectBuffer(PC_R, SizeOf(PC_R));
3776
end;
3777
 
3778
procedure TCipher_1DES.DoInit(const Key; Size: Integer);
3779
var
3780
  K: array[0..7] of Byte;
3781
begin
3782
  FillChar(K, SizeOf(K), 0);
3783
  Move(Key, K, Size);
3784
  DoInitKey(K, FUser, False);
3785
  DoInitKey(K, @PLongArray(FUser)[32], True);
3786
  ProtectBuffer(K, SizeOf(K));
3787
end;
3788
 
3789
procedure TCipher_1DES.DoEncode(Source, Dest: Pointer; Size: Integer);
3790
begin
3791
  Assert(Size = Context.BufferSize);
3792
  DES_Func(Source, Dest, FUser);
3793
end;
3794
 
3795
procedure TCipher_1DES.DoDecode(Source, Dest: Pointer; Size: Integer);
3796
begin
3797
  Assert(Size = Context.BufferSize);
3798
  DES_Func(Source,Dest, @PLongArray(FUser)[32]);
3799
end;
3800
 
3801
// .TCipher_2DES
3802
class function TCipher_2DES.Context: TCipherContext;
3803
begin
3804
  Result.KeySize := 16;
3805
  Result.BlockSize := 8;
3806
  Result.BufferSize := 8;
3807
  Result.UserSize := 32 * 4 * 2 * 2;
3808
  Result.UserSave := False;
3809
end;
3810
 
3811
procedure TCipher_2DES.DoInit(const Key; Size: Integer);
3812
var
3813
  K: array[0..15] of Byte;
3814
  P: PLongArray;
3815
begin
3816
  FillChar(K, SizeOf(K), 0);
3817
  Move(Key, K, Size);
3818
  P := FUser;
3819
  DoInitKey(K[0], @P[ 0], False);
3820
  DoInitKey(K[8], @P[32], True);
3821
  DoInitKey(K[0], @P[64], True);
3822
  DoInitKey(K[8], @P[96], False);
3823
  ProtectBuffer(K, SizeOf(K));
3824
end;
3825
 
3826
procedure TCipher_2DES.DoEncode(Source, Dest: Pointer; Size: Integer);
3827
begin
3828
  Assert(Size = Context.BufferSize);
3829
  DES_Func(Source, Dest, FUser);
3830
  DES_Func(Source, Dest, @PLongArray(FUser)[32]);
3831
  DES_Func(Source, Dest, FUser);
3832
end;
3833
 
3834
procedure TCipher_2DES.DoDecode(Source, Dest: Pointer; Size: Integer);
3835
begin
3836
  Assert(Size = Context.BufferSize);
3837
  DES_Func(Source, Dest, @PLongArray(FUser)[64]);
3838
  DES_Func(Source, Dest, @PLongArray(FUser)[96]);
3839
  DES_Func(Source, Dest, @PLongArray(FUser)[64]);
3840
end;
3841
 
3842
// .TCipher_3DES
3843
class function TCipher_3DES.Context: TCipherContext;
3844
begin
3845
  Result.KeySize := 24;
3846
  Result.BlockSize := 8;
3847
  Result.BufferSize := 8;
3848
  Result.UserSize := 32 * 4 * 2 * 3;
3849
  Result.UserSave := False;
3850
end;
3851
 
3852
procedure TCipher_3DES.DoInit(const Key; Size: Integer);
3853
var
3854
  K: array[0..23] of Byte;
3855
  P: PLongArray;
3856
begin
3857
  FillChar(K, SizeOf(K), 0);
3858
  Move(Key, K, Size);
3859
  P := FUser;
3860
  DoInitKey(K[ 0], @P[  0], False);
3861
  DoInitKey(K[ 8], @P[ 32], True);
3862
  DoInitKey(K[16], @P[ 64], False);
3863
  DoInitKey(K[16], @P[ 96], True);
3864
  DoInitKey(K[ 8], @P[128], False);
3865
  DoInitKey(K[ 0], @P[160], True);
3866
  ProtectBuffer(K, SizeOf(K));
3867
end;
3868
 
3869
procedure TCipher_3DES.DoEncode(Source, Dest: Pointer; Size: Integer);
3870
begin
3871
  Assert(Size = Context.BufferSize);
3872
  DES_Func(Source, Dest, @PLongArray(FUser)[ 0]);
3873
  DES_Func(Source, Dest, @PLongArray(FUser)[32]);
3874
  DES_Func(Source, Dest, @PLongArray(FUser)[64]);
3875
end;
3876
 
3877
procedure TCipher_3DES.DoDecode(Source, Dest: Pointer; Size: Integer);
3878
begin
3879
  Assert(Size = Context.BufferSize);
3880
  DES_Func(Source, Dest, @PLongArray(FUser)[96]);
3881
  DES_Func(Source, Dest, @PLongArray(FUser)[128]);
3882
  DES_Func(Source, Dest, @PLongArray(FUser)[160]);
3883
end;
3884
 
3885
// .TCipher_2DDES
3886
class function TCipher_2DDES.Context: TCipherContext;
3887
begin
3888
  Result := inherited Context;
3889
  Result.BlockSize := 16;
3890
  Result.BufferSize := 16;
3891
end;
3892
 
3893
procedure TCipher_2DDES.DoEncode(Source, Dest: Pointer; Size: Integer);
3894
var
3895
  T: LongWord;
3896
  S: PLongArray absolute Source;
3897
  D: PLongArray absolute Dest;
3898
begin
3899
  Assert(Size = Context.BufferSize);
3900
 
3901
  DES_Func(@S[0], @D[0], FUser);
3902
  DES_Func(@S[2], @D[2], FUser);
3903
  T := D[1]; D[1] := D[2]; D[2] := T;
3904
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]);
3905
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]);
3906
  T := D[1]; D[1] := D[2]; D[2] := T;
3907
  DES_Func(@D[0], @D[0], FUser);
3908
  DES_Func(@D[2], @D[2], FUser);
3909
end;
3910
 
3911
procedure TCipher_2DDES.DoDecode(Source, Dest: Pointer; Size: Integer);
3912
var
3913
  T: LongWord;
3914
  S: PLongArray absolute Source;
3915
  D: PLongArray absolute Dest;
3916
begin
3917
  Assert(Size = Context.BufferSize);
3918
 
3919
  DES_Func(@S[0], @D[0], @PLongArray(FUser)[64]);
3920
  DES_Func(@S[2], @D[2], @PLongArray(FUser)[64]);
3921
  T := D[1]; D[1] := D[2]; D[2] := T;
3922
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[96]);
3923
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[96]);
3924
  T := D[1]; D[1] := D[2]; D[2] := T;
3925
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]);
3926
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]);
3927
end;
3928
 
3929
// .TCipher_3DDES
3930
class function TCipher_3DDES.Context: TCipherContext;
3931
begin
3932
  Result := inherited Context;
3933
  Result.BlockSize := 16;
3934
  Result.BufferSize := 16;
3935
end;
3936
 
3937
procedure TCipher_3DDES.DoEncode(Source, Dest: Pointer; Size: Integer);
3938
var
3939
  T: LongWord;
3940
  S: PLongArray absolute Source;
3941
  D: PLongArray absolute Dest;
3942
begin
3943
  Assert(Size = Context.BufferSize);
3944
 
3945
  DES_Func(@S[0], @D[0], FUser);
3946
  DES_Func(@S[2], @D[2], FUser);
3947
  T := D[1]; D[1] := D[2]; D[2] := T;
3948
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]);
3949
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]);
3950
  T := D[1]; D[1] := D[2]; D[2] := T;
3951
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]);
3952
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]);
3953
end;
3954
 
3955
procedure TCipher_3DDES.DoDecode(Source, Dest: Pointer; Size: Integer);
3956
var
3957
  T: LongWord;
3958
  S: PLongArray absolute Source;
3959
  D: PLongArray absolute Dest;
3960
begin
3961
  Assert(Size = Context.BufferSize);
3962
 
3963
  DES_Func(@S[0], @D[0], @PLongArray(FUser)[96]);
3964
  DES_Func(@S[2], @D[2], @PLongArray(FUser)[96]);
3965
  T := D[1]; D[1] := D[2]; D[2] := T;
3966
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[128]);
3967
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[128]);
3968
  T := D[1]; D[1] := D[2]; D[2] := T;
3969
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[160]);
3970
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[160]);
3971
end;
3972
 
3973
 
3974
// .TCipher_3TDES
3975
class function TCipher_3TDES.Context: TCipherContext;
3976
begin
3977
  Result := inherited Context;
3978
  Result.BlockSize := 24;
3979
  Result.BufferSize := 24;
3980
end;
3981
 
3982
procedure TCipher_3TDES.DoEncode(Source, Dest: Pointer; Size: Integer);
3983
var
3984
  T: LongWord;
3985
  S: PLongArray absolute Source;
3986
  D: PLongArray absolute Dest;
3987
begin
3988
  Assert(Size = Context.BufferSize);
3989
 
3990
  DES_Func(@S[0], @D[0], FUser);
3991
  DES_Func(@S[2], @D[2], FUser);
3992
  DES_Func(@S[4], @D[4], FUser);
3993
  T := D[1]; D[1] := D[2]; D[2] := T;
3994
  T := D[3]; D[3] := D[4]; D[4] := T;
3995
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[32]);
3996
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[32]);
3997
  DES_Func(@D[4], @D[4], @PLongArray(FUser)[32]);
3998
  T := D[1]; D[1] := D[2]; D[2] := T;
3999
  T := D[3]; D[3] := D[4]; D[4] := T;
4000
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[64]);
4001
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[64]);
4002
  DES_Func(@D[4], @D[4], @PLongArray(FUser)[64]);
4003
end;
4004
 
4005
procedure TCipher_3TDES.DoDecode(Source, Dest: Pointer; Size: Integer);
4006
var
4007
  T: LongWord;
4008
  S: PLongArray absolute Source;
4009
  D: PLongArray absolute Dest;
4010
begin
4011
  Assert(Size = Context.BufferSize);
4012
 
4013
  DES_Func(@S[0], @D[0], @PLongArray(FUser)[96]);
4014
  DES_Func(@S[2], @D[2], @PLongArray(FUser)[96]);
4015
  DES_Func(@S[4], @D[4], @PLongArray(FUser)[96]);
4016
  T := D[1]; D[1] := D[2]; D[2] := T;
4017
  T := D[3]; D[3] := D[4]; D[4] := T;
4018
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[128]);
4019
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[128]);
4020
  DES_Func(@D[4], @D[4], @PLongArray(FUser)[128]);
4021
  T := D[1]; D[1] := D[2]; D[2] := T;
4022
  T := D[3]; D[3] := D[4]; D[4] := T;
4023
  DES_Func(@D[0], @D[0], @PLongArray(FUser)[160]);
4024
  DES_Func(@D[2], @D[2], @PLongArray(FUser)[160]);
4025
  DES_Func(@D[4], @D[4], @PLongArray(FUser)[160]);
4026
end;
4027
 
4028
 
4029
// .TCipher_3Way
4030
type
4031
  P3Way_Key = ^T3Way_Key;
4032
  T3Way_Key = packed record
4033
                E_Key: array[0..2] of LongWord;
4034
                E_Data: array[0..11] of LongWord;
4035
                D_Key: array[0..2] of LongWord;
4036
                D_Data: array[0..11] of LongWord;
4037
              end;
4038
 
4039
class function TCipher_3Way.Context: TCipherContext;
4040
begin
4041
  Result.KeySize := 12;
4042
  Result.BlockSize := 12;
4043
  Result.BufferSize := 12;
4044
  Result.UserSize := SizeOf(T3Way_Key);
4045
  Result.UserSave := False;
4046
end;
4047
 
4048
procedure TCipher_3Way.DoInit(const Key; Size: Integer);
4049
 
4050
  procedure RANDGenerate(Start: LongWord; var P: Array of LongWord);
4051
  var
4052
    I: Integer;
4053
  begin
4054
    for I := 0 to 11 do
4055
    begin
4056
      P[I] := Start;
4057
      Start := Start shl 1;
4058
      if Start and $10000 <> 0 then Start := Start xor $11011;
4059
    end;
4060
  end;
4061
 
4062
var
4063
  A0,A1,A2: LongWord;
4064
  B0,B1,B2: LongWord;
4065
begin
4066
  with P3Way_Key(FUser)^ do
4067
  begin
4068
    Move(Key, E_Key, Size);
4069
    Move(Key, D_Key, Size);
4070
    RANDGenerate($0B0B, E_Data);
4071
    RANDGenerate($B1B1, D_Data);
4072
    A0 := D_Key[0];
4073
    A1 := D_Key[1];
4074
    A2 := D_Key[2];
4075
    B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
4076
                 A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
4077
                 A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
4078
    B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
4079
                 A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
4080
                 A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
4081
    B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
4082
                 A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
4083
                 A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
4084
    D_Key[2] := SwapBits(B0, 0);
4085
    D_Key[1] := SwapBits(B1, 0);
4086
    D_Key[0] := SwapBits(B2, 0);
4087
  end;
4088
end;
4089
 
4090
procedure TCipher_3Way.DoEncode(Source, Dest: Pointer; Size: Integer);
4091
var
4092
  I: Integer;
4093
  A0,A1,A2: LongWord;
4094
  B0,B1,B2: LongWord;
4095
  K0,K1,K2: LongWord;
4096
  E: PLongWord;
4097
begin
4098
  Assert(Size = Context.BufferSize);
4099
 
4100
  with P3Way_Key(FUser)^ do
4101
  begin
4102
    K0 := E_Key[0];
4103
    K1 := E_Key[1];
4104
    K2 := E_Key[2];
4105
    E  := @E_Data;
4106
  end;
4107
  A0 := PLongArray(Source)[0];
4108
  A1 := PLongArray(Source)[1];
4109
  A2 := PLongArray(Source)[2];
4110
  for I := 0 to 10 do
4111
  begin
4112
    A0 := A0 xor K0 xor E^ shl 16;
4113
    A1 := A1 xor K1;
4114
    A2 := A2 xor K2 xor E^;
4115
    Inc(E);
4116
 
4117
    B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
4118
                 A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
4119
                 A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
4120
    B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
4121
                 A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
4122
                 A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
4123
    B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
4124
                 A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
4125
                 A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
4126
    B0 := B0 shr 10 or B0 shl 22;
4127
    B2 := B2 shl  1 or B2 shr 31;
4128
    A0 := B0 xor (B1 or not B2);
4129
    A1 := B1 xor (B2 or not B0);
4130
    A2 := B2 xor (B0 or not B1);
4131
    A0 := A0 shl  1 or A0 shr 31;
4132
    A2 := A2 shr 10 or A2 shl 22;
4133
  end;
4134
  A0 := A0 xor K0 xor E^ shl 16;
4135
  A1 := A1 xor K1;
4136
  A2 := A2 xor K2 xor E^;
4137
  PLongArray(Dest)[0] := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
4138
                                A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
4139
                                A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
4140
  PLongArray(Dest)[1] := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
4141
                                A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
4142
                                A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
4143
  PLongArray(Dest)[2] := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
4144
                                A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
4145
                                A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
4146
end;
4147
 
4148
procedure TCipher_3Way.DoDecode(Source, Dest: Pointer; Size: Integer);
4149
var
4150
  I: Integer;
4151
  A0,A1,A2: LongWord;
4152
  B0,B1,B2: LongWord;
4153
  K0,K1,K2: LongWord;
4154
  E: PLongWord;
4155
begin
4156
  Assert(Size = Context.BufferSize);
4157
 
4158
  with P3Way_Key(FUser)^ do
4159
  begin
4160
    K0 := D_Key[0];
4161
    K1 := D_Key[1];
4162
    K2 := D_Key[2];
4163
    E  := @D_Data;
4164
  end;
4165
  A0 := SwapBits(PLongArray(Source)[2], 0);
4166
  A1 := SwapBits(PLongArray(Source)[1], 0);
4167
  A2 := SwapBits(PLongArray(Source)[0], 0);
4168
  for I := 0 to 10 do
4169
  begin
4170
    A0 := A0 xor K0 xor E^ shl 16;
4171
    A1 := A1 xor K1;
4172
    A2 := A2 xor K2 xor E^;
4173
    Inc(E);
4174
 
4175
    B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
4176
                 A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
4177
                 A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
4178
    B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
4179
                 A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
4180
                 A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
4181
    B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
4182
                 A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
4183
                 A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
4184
    B0 := B0 shr 10 or B0 shl 22;
4185
    B2 := B2 shl  1 or B2 shr 31;
4186
    A0 := B0 xor (B1 or not B2);
4187
    A1 := B1 xor (B2 or not B0);
4188
    A2 := B2 xor (B0 or not B1);
4189
    A0 := A0 shl  1 or A0 shr 31;
4190
    A2 := A2 shr 10 or A2 shl 22;
4191
  end;
4192
  A0 := A0 xor K0 xor E^ shl 16;
4193
  A1 := A1 xor K1;
4194
  A2 := A2 xor K2 xor E^;
4195
  B0 := A0 xor A0 shr 16 xor A1 shl 16 xor A1 shr 16 xor A2 shl 16 xor
4196
               A1 shr 24 xor A2 shl  8 xor A2 shr  8 xor A0 shl 24 xor
4197
               A2 shr 16 xor A0 shl 16 xor A2 shr 24 xor A0 shl  8;
4198
  B1 := A1 xor A1 shr 16 xor A2 shl 16 xor A2 shr 16 xor A0 shl 16 xor
4199
               A2 shr 24 xor A0 shl  8 xor A0 shr  8 xor A1 shl 24 xor
4200
               A0 shr 16 xor A1 shl 16 xor A0 shr 24 xor A1 shl  8;
4201
  B2 := A2 xor A2 shr 16 xor A0 shl 16 xor A0 shr 16 xor A1 shl 16 xor
4202
               A0 shr 24 xor A1 shl  8 xor A1 shr  8 xor A2 shl 24 xor
4203
               A1 shr 16 xor A2 shl 16 xor A1 shr 24 xor A2 shl  8;
4204
 
4205
  PLongArray(Dest)[2] := SwapBits(B0, 0);
4206
  PLongArray(Dest)[1] := SwapBits(B1, 0);
4207
  PLongArray(Dest)[0] := SwapBits(B2, 0);
4208
end;
4209
 
4210
 
4211
// .TCipher_Cast128
4212
class function TCipher_Cast128.Context: TCipherContext;
4213
begin
4214
  Result.KeySize := 16;
4215
  Result.BlockSize := 8;
4216
  Result.BufferSize := 8;
4217
  Result.UserSize := 128;
4218
  Result.UserSave := False;
4219
end;
4220
 
4221
procedure TCipher_Cast128.SetRounds(Value: Integer);
4222
begin
4223
  if Value <> FRounds then
4224
  begin
4225
    if not (FState in [csNew, csInitialized, csDone]) then Done;
4226
    if (FState <> csNew) and (Value <= 0) then Value := 16;
4227
    FRounds := Value;
4228
  end;
4229
end;
4230
 
4231
procedure TCipher_Cast128.DoInit(const Key; Size: Integer);
4232
var
4233
  Z,X,T: array[0..3] of LongWord;
4234
  K: PLongArray;
4235
  I: LongWord;
4236
begin
4237
  if FRounds <= 0 then
4238
    if Size <= 10 then FRounds := 12
4239
      else FRounds := 16;
4240
  K := FUser;
4241
  FillChar(X, SizeOf(X), 0);
4242
  Move(Key, X, Size);
4243
  SwapLongBuffer(X, X, 4);
4244
  I := 0;
4245
  while I < 32 do
4246
  begin
4247
    if I and 4 = 0 then
4248
    begin
4249
      Z[0] := X[0] xor Cast128_Key[0, X[3] shr 16 and $FF] xor
4250
                       Cast128_Key[1, X[3] and $FF] xor
4251
                       Cast128_Key[2, X[3] shr 24] xor
4252
                       Cast128_Key[3, X[3] shr  8 and $FF] xor
4253
                       Cast128_Key[2, X[2] shr 24];
4254
      T[0] := Z[0];
4255
      Z[1] := X[2] xor Cast128_Key[0, Z[0] shr 24] xor
4256
                       Cast128_Key[1, Z[0] shr  8 and $FF] xor
4257
                       Cast128_Key[2, Z[0] shr 16 and $FF] xor
4258
                       Cast128_Key[3, Z[0] and $FF] xor
4259
                       Cast128_Key[3, X[2] shr  8 and $FF];
4260
      T[1] := Z[1];
4261
      Z[2] := X[3] xor Cast128_Key[0, Z[1] and $FF] xor
4262
                       Cast128_Key[1, Z[1] shr  8 and $FF] xor
4263
                       Cast128_Key[2, Z[1] shr 16 and $FF] xor
4264
                       Cast128_Key[3, Z[1] shr 24] xor
4265
                       Cast128_Key[0, X[2] shr 16 and $FF];
4266
      T[2] := Z[2];
4267
      Z[3] := X[1] xor Cast128_Key[0, Z[2] shr  8 and $FF] xor
4268
                       Cast128_Key[1, Z[2] shr 16 and $FF] xor
4269
                       Cast128_Key[2, Z[2] and $FF] xor
4270
                       Cast128_Key[3, Z[2] shr 24] xor
4271
                       Cast128_Key[1, X[2] and $FF];
4272
      T[3] := Z[3];
4273
    end else
4274
    begin
4275
      X[0] := Z[2] xor Cast128_Key[0, Z[1] shr 16 and $FF] xor
4276
                       Cast128_Key[1, Z[1] and $FF] xor
4277
                       Cast128_Key[2, Z[1] shr 24] xor
4278
                       Cast128_Key[3, Z[1] shr  8 and $FF] xor
4279
                       Cast128_Key[2, Z[0] shr 24];
4280
      T[0] := X[0];
4281
      X[1] := Z[0] xor Cast128_Key[0, X[0] shr 24] xor
4282
                       Cast128_Key[1, X[0] shr  8 and $FF] xor
4283
                       Cast128_Key[2, X[0] shr 16 and $FF] xor
4284
                       Cast128_Key[3, X[0] and $FF] xor
4285
                       Cast128_Key[3, Z[0] shr  8 and $FF];
4286
      T[1] := X[1];
4287
      X[2] := Z[1] xor Cast128_Key[0, X[1] and $FF] xor
4288
                       Cast128_Key[1, X[1] shr  8 and $FF] xor
4289
                       Cast128_Key[2, X[1] shr 16 and $FF] xor
4290
                       Cast128_Key[3, X[1] shr 24] xor
4291
                       Cast128_Key[0, Z[0] shr 16 and $FF];
4292
      T[2] := X[2];
4293
      X[3] := Z[3] xor Cast128_Key[0, X[2] shr  8 and $FF] xor
4294
                       Cast128_Key[1, X[2] shr 16 and $FF] xor
4295
                       Cast128_Key[2, X[2] and $FF] xor
4296
                       Cast128_Key[3, X[2] shr 24] xor
4297
                       Cast128_Key[1, Z[0] and $FF];
4298
      T[3] := X[3];
4299
    end;
4300
    case I and 12 of
4301
      0,12:
4302
        begin
4303
          K[I +0] := Cast128_Key[0, T[2] shr 24] xor
4304
                     Cast128_Key[1, T[2] shr 16 and $FF] xor
4305
                     Cast128_Key[2, T[1] and $FF] xor
4306
                     Cast128_Key[3, T[1] shr  8 and $FF];
4307
          K[I +1] := Cast128_Key[0, T[2] shr  8 and $FF] xor
4308
                     Cast128_Key[1, T[2] and $FF] xor
4309
                     Cast128_Key[2, T[1] shr 16 and $FF] xor
4310
                     Cast128_Key[3, T[1] shr 24];
4311
          K[I +2] := Cast128_Key[0, T[3] shr 24] xor
4312
                     Cast128_Key[1, T[3] shr 16 and $FF] xor
4313
                     Cast128_Key[2, T[0] and $FF] xor
4314
                     Cast128_Key[3, T[0] shr  8 and $FF];
4315
          K[I +3] := Cast128_Key[0, T[3] shr  8 and $FF] xor
4316
                     Cast128_Key[1, T[3] and $FF] xor
4317
                     Cast128_Key[2, T[0] shr 16 and $FF] xor
4318
                     Cast128_Key[3, T[0] shr 24];
4319
        end;
4320
      4,8:
4321
        begin
4322
          K[I +0] := Cast128_Key[0, T[0] and $FF] xor
4323
                     Cast128_Key[1, T[0] shr  8 and $FF] xor
4324
                     Cast128_Key[2, T[3] shr 24] xor
4325
                     Cast128_Key[3, T[3] shr 16 and $FF];
4326
          K[I +1] := Cast128_Key[0, T[0] shr 16 and $FF] xor
4327
                     Cast128_Key[1, T[0] shr 24] xor
4328
                     Cast128_Key[2, T[3] shr  8 and $FF] xor
4329
                     Cast128_Key[3, T[3] and $FF];
4330
          K[I +2] := Cast128_Key[0, T[1] and $FF] xor
4331
                     Cast128_Key[1, T[1] shr  8 and $FF] xor
4332
                     Cast128_Key[2, T[2] shr 24] xor
4333
                     Cast128_Key[3, T[2] shr 16 and $FF];
4334
          K[I +3] := Cast128_Key[0, T[1] shr 16 and $FF] xor
4335
                     Cast128_Key[1, T[1] shr 24] xor
4336
                     Cast128_Key[2, T[2] shr  8 and $FF] xor
4337
                     Cast128_Key[3, T[2] and $FF];
4338
        end;
4339
    end;
4340
    case I and 12 of
4341
      0: begin
4342
           K[I +0] := K[I +0] xor Cast128_Key[0, Z[0] shr  8 and $FF];
4343
           K[I +1] := K[I +1] xor Cast128_Key[1, Z[1] shr  8 and $FF];
4344
           K[I +2] := K[I +2] xor Cast128_Key[2, Z[2] shr 16 and $FF];
4345
           K[I +3] := K[I +3] xor Cast128_Key[3, Z[3] shr 24];
4346
         end;
4347
      4: begin
4348
           K[I +0] := K[I +0] xor Cast128_Key[0, X[2] shr 24];
4349
           K[I +1] := K[I +1] xor Cast128_Key[1, X[3] shr 16 and $FF];
4350
           K[I +2] := K[I +2] xor Cast128_Key[2, X[0] and $FF];
4351
           K[I +3] := K[I +3] xor Cast128_Key[3, X[1] and $FF];
4352
         end;
4353
      8: begin
4354
           K[I +0] := K[I +0] xor Cast128_Key[0, Z[2] shr 16 and $FF];
4355
           K[I +1] := K[I +1] xor Cast128_Key[1, Z[3] shr 24];
4356
           K[I +2] := K[I +2] xor Cast128_Key[2, Z[0] shr  8 and $FF];
4357
           K[I +3] := K[I +3] xor Cast128_Key[3, Z[1] shr  8 and $FF];
4358
         end;
4359
     12: begin
4360
          K[I +0] := K[I +0] xor Cast128_Key[0, X[0] and $FF];
4361
          K[I +1] := K[I +1] xor Cast128_Key[1, X[1] and $FF];
4362
          K[I +2] := K[I +2] xor Cast128_Key[2, X[2] shr 24];
4363
          K[I +3] := K[I +3] xor Cast128_Key[3, X[3] shr 16 and $FF];
4364
        end;
4365
    end;
4366
    if I >= 16 then
4367
    begin
4368
      K[I +0] := K[I +0] and $1F;
4369
      K[I +1] := K[I +1] and $1F;
4370
      K[I +2] := K[I +2] and $1F;
4371
      K[I +3] := K[I +3] and $1F;
4372
    end;
4373
    Inc(I, 4);
4374
  end;
4375
  ProtectBuffer(X, SizeOf(X));
4376
  ProtectBuffer(Z, SizeOf(Z));
4377
  ProtectBuffer(T, SizeOf(T));
4378
end;
4379
 
4380
procedure TCipher_Cast128.DoEncode(Source, Dest: Pointer; Size: Integer);
4381
var
4382
  T,I,A,B: LongWord;
4383
  K: PLongArray;
4384
begin
4385
  Assert(Size = Context.BufferSize);
4386
 
4387
  K := FUser;
4388
  A := SwapLong(PLongArray(Source)[0]);
4389
  B := SwapLong(PLongArray(Source)[1]);
4390
  for I := 0 to 2 do
4391
  begin
4392
    T := K[0] + B;
4393
    T := T shl K[16] or T shr (32 - K[16]);
4394
    A := A xor (Cast128_Data[0, T shr 24] xor
4395
                Cast128_Data[1, T shr 16 and $FF] -
4396
                Cast128_Data[2, T shr  8 and $FF] +
4397
                Cast128_Data[3, T and $FF]);
4398
    T := K[1] xor A;
4399
    T := T shl K[17] or T shr (32 - K[17]);
4400
    B := B xor (Cast128_Data[0, T shr 24] -
4401
                Cast128_Data[1, T shr 16 and $FF] +
4402
                Cast128_Data[2, T shr  8 and $FF] xor
4403
                Cast128_Data[3, T and $FF]);
4404
    T := K[2] - B;
4405
    T := T shl K[18] or T shr (32 - K[18]);
4406
    A := A xor (Cast128_Data[0, T shr 24] +
4407
                Cast128_Data[1, T shr 16 and $FF] xor
4408
                Cast128_Data[2, T shr  8 and $FF] -
4409
                Cast128_Data[3, T and $FF]);
4410
    T := K[3] + A;
4411
    T := T shl K[19] or T shr (32 - K[19]);
4412
    B := B xor (Cast128_Data[0, T shr 24] xor
4413
                Cast128_Data[1, T shr 16 and $FF] -
4414
                Cast128_Data[2, T shr  8 and $FF] +
4415
                Cast128_Data[3, T and $FF]);
4416
    if I = 2 then Break;
4417
    T := K[4] xor B;
4418
    T := T shl K[20] or T shr (32 - K[20]);
4419
    A := A xor (Cast128_Data[0, T shr 24] -
4420
                Cast128_Data[1, T shr 16 and $FF] +
4421
                Cast128_Data[2, T shr  8 and $FF] xor
4422
                Cast128_Data[3, T and $FF]);
4423
    T := K[5] - A;
4424
    T := T shl K[21] or T shr (32 - K[21]);
4425
    B := B xor (Cast128_Data[0, T shr 24] +
4426
                Cast128_Data[1, T shr 16 and $FF] xor
4427
                Cast128_Data[2, T shr  8 and $FF] -
4428
                Cast128_Data[3, T and $FF]);
4429
    if (I = 1) and (FRounds <= 12) then Break;
4430
    K := @K[6];
4431
  end;
4432
  PLongArray(Dest)[0] := SwapLong(B);
4433
  PLongArray(Dest)[1] := SwapLong(A);
4434
end;
4435
 
4436
procedure TCipher_Cast128.DoDecode(Source, Dest: Pointer; Size: Integer);
4437
var
4438
  T,I,A,B: LongWord;
4439
  K: PLongArray;
4440
label
4441
  Start;
4442
begin
4443
  Assert(Size = Context.BufferSize);
4444
 
4445
  K := @PLongArray(FUser)[12];
4446
  B := SwapLong(PLongArray(Source)[0]);
4447
  A := SwapLong(PLongArray(Source)[1]);
4448
  I := 2;
4449
  if FRounds <= 12 then Dec(PLongWord(K), 6)
4450
    else goto Start;
4451
  while I > 0 do
4452
  begin
4453
    Dec(I);
4454
    T := K[5] - A;
4455
    T := T shl K[21] or T shr (32 - K[21]);
4456
    B := B xor (Cast128_Data[0, T shr 24] +
4457
                Cast128_Data[1, T shr 16 and $FF] xor
4458
                Cast128_Data[2, T shr  8 and $FF] -
4459
                Cast128_Data[3, T and $FF]);
4460
    T := K[4] xor B;
4461
    T := T shl K[20] or T shr (32 - K[20]);
4462
    A := A xor (Cast128_Data[0, T shr 24] -
4463
                Cast128_Data[1, T shr 16 and $FF] +
4464
                Cast128_Data[2, T shr  8 and $FF] xor
4465
                Cast128_Data[3, T and $FF]);
4466
Start:
4467
    T := K[3] + A;
4468
    T := T shl K[19] or T shr (32 - K[19]);
4469
    B := B xor (Cast128_Data[0, T shr 24] xor
4470
                Cast128_Data[1, T shr 16 and $FF] -
4471
                Cast128_Data[2, T shr  8 and $FF] +
4472
                Cast128_Data[3, T and $FF]);
4473
    T := K[2] - B;
4474
    T := T shl K[18] or T shr (32 - K[18]);
4475
    A := A xor (Cast128_Data[0, T shr 24] +
4476
                Cast128_Data[1, T shr 16 and $FF] xor
4477
                Cast128_Data[2, T shr  8 and $FF] -
4478
                Cast128_Data[3, T and $FF]);
4479
    T := K[1] xor A;
4480
    T := T shl K[17] or T shr (32 - K[17]);
4481
    B := B xor (Cast128_Data[0, T shr 24] -
4482
                Cast128_Data[1, T shr 16 and $FF] +
4483
                Cast128_Data[2, T shr  8 and $FF] xor
4484
                Cast128_Data[3, T and $FF]);
4485
    T := K[0] + B;
4486
    T := T shl K[16] or T shr (32 - K[16]);
4487
    A := A xor (Cast128_Data[0, T shr 24] xor
4488
                Cast128_Data[1, T shr 16 and $FF] -
4489
                Cast128_Data[2, T shr  8 and $FF] +
4490
                Cast128_Data[3, T and $FF]);
4491
    Dec(PLongWord(K), 6);
4492
  end;
4493
  PLongArray(Dest)[0] := SwapLong(A);
4494
  PLongArray(Dest)[1] := SwapLong(B);
4495
end;
4496
 
4497
// .TCipher_Gost
4498
class function TCipher_Gost.Context: TCipherContext;
4499
begin
4500
  Result.KeySize := 32;
4501
  Result.BlockSize := 8;
4502
  Result.BufferSize := 8;
4503
  Result.UserSize := 32;
4504
  Result.UserSave := False;
4505
end;
4506
 
4507
procedure TCipher_Gost.DoInit(const Key; Size: Integer);
4508
begin
4509
  Move(Key, FUser^, Size);
4510
end;
4511
 
4512
procedure TCipher_Gost.DoEncode(Source, Dest: Pointer; Size: Integer);
4513
var
4514
  I,A,B,T: LongWord;
4515
  K: PLongArray;
4516
begin
4517
  Assert(Size = Context.BufferSize);
4518
 
4519
  K := FUser;
4520
  A := PLongArray(Source)[0];
4521
  B := PLongArray(Source)[1];
4522
  for I := 0 to 11 do
4523
  begin
4524
    if I and 3 = 0 then K := FUser;
4525
    T := A + K[0];
4526
    B := B xor Gost_Data[0, T        and $FF] xor
4527
               Gost_Data[1, T shr  8 and $FF] xor
4528
               Gost_Data[2, T shr 16 and $FF] xor
4529
               Gost_Data[3, T shr 24        ];
4530
    T := B + K[1];
4531
    A := A xor Gost_Data[0, T        and $FF] xor
4532
               Gost_Data[1, T shr  8 and $FF] xor
4533
               Gost_Data[2, T shr 16 and $FF] xor
4534
               Gost_Data[3, T shr 24        ];
4535
    K := @K[2];
4536
  end;
4537
  K := @PLongArray(FUser)[6];
4538
  for I := 0 to 3 do
4539
  begin
4540
    T := A + K[1];
4541
    B := B xor Gost_Data[0, T        and $FF] xor
4542
               Gost_Data[1, T shr  8 and $FF] xor
4543
               Gost_Data[2, T shr 16 and $FF] xor
4544
               Gost_Data[3, T shr 24        ];
4545
    T := B + K[0];
4546
    A := A xor Gost_Data[0, T        and $FF] xor
4547
               Gost_Data[1, T shr  8 and $FF] xor
4548
               Gost_Data[2, T shr 16 and $FF] xor
4549
               Gost_Data[3, T shr 24        ];
4550
    Dec(PLongWord(K), 2);
4551
  end;
4552
  PLongArray(Dest)[0] := B;
4553
  PLongArray(Dest)[1] := A;
4554
end;
4555
 
4556
procedure TCipher_Gost.DoDecode(Source, Dest: Pointer; Size: Integer);
4557
var
4558
  I,A,B,T: LongWord;
4559
  K: PLongArray;
4560
begin
4561
  Assert(Size = Context.BufferSize);
4562
 
4563
  A := PLongArray(Source)[0];
4564
  B := PLongArray(Source)[1];
4565
  K := FUser;
4566
  for I := 0 to 3 do
4567
  begin
4568
    T := A + K[0];
4569
    B := B xor Gost_Data[0, T and $FF] xor
4570
               Gost_Data[1, T shr  8 and $FF] xor
4571
               Gost_Data[2, T shr 16 and $FF] xor
4572
               Gost_Data[3, T shr 24];
4573
    T := B + K[1];
4574
    A := A xor Gost_Data[0, T and $FF] xor
4575
               Gost_Data[1, T shr  8 and $FF] xor
4576
               Gost_Data[2, T shr 16 and $FF] xor
4577
               Gost_Data[3, T shr 24];
4578
    K := @K[2];
4579
  end;
4580
  for I := 0 to 11 do
4581
  begin
4582
    if I and 3 = 0 then K := @PLongArray(FUser)[6];
4583
    T := A + K[1];
4584
    B := B xor Gost_Data[0, T and $FF] xor
4585
               Gost_Data[1, T shr  8 and $FF] xor
4586
               Gost_Data[2, T shr 16 and $FF] xor
4587
               Gost_Data[3, T shr 24];
4588
    T := B + K[0];
4589
    A := A xor Gost_Data[0, T and $FF] xor
4590
               Gost_Data[1, T shr  8 and $FF] xor
4591
               Gost_Data[2, T shr 16 and $FF] xor
4592
               Gost_Data[3, T shr 24];
4593
    Dec(PLongWord(K), 2);
4594
  end;
4595
  PLongArray(Dest)[0] := B;
4596
  PLongArray(Dest)[1] := A;
4597
end;
4598
 
4599
// .TCipher_Misty
4600
class function TCipher_Misty.Context: TCipherContext;
4601
begin
4602
  Result.KeySize := 16;
4603
  Result.BlockSize := 8;
4604
  Result.BufferSize := 8;
4605
  Result.UserSize := 128;
4606
  Result.UserSave := False;
4607
end;
4608
 
4609
function Misty_I(Value, Key: LongWord): LongWord;
4610
begin
4611
  Result := Misty_Data9[Value shr 7 and $1FF] xor (Value and $7F);
4612
  Value := (Misty_Data7[Value and $7F] xor Result and $7F) xor (Key shr 9 and $7F);
4613
  Result := Misty_Data9[Result xor (Key and $1FF)] xor Value or Value shl 9;
4614
end;
4615
 
4616
function Misty_O(Value, K: LongWord; Key: PLongArray): LongWord;
4617
begin
4618
  Result := Misty_I((Value shr 16) xor Key[K], Key[(K + 5) and 7 + 8]) xor (Value and $FFFF);
4619
  Value  := Misty_I((Value and $FFFF) xor Key[(K + 2) and 7], Key[(K + 1) and 7 + 8]) xor Result;
4620
  Result := Misty_I(Result xor Key[(K + 7) and 7], Key[(K + 3) and 7 + 8]) xor Value;
4621
  Result := Result or (Value xor Key[(k+4) and 7]) shl 16;
4622
end;
4623
 
4624
function Misty_E(Value, K: LongWord; Key: PLongArray): LongWord;
4625
begin
4626
  Result := Value shr 16;
4627
  Value  := Value and $FFFF;
4628
  if K and 1 <> 0 then
4629
  begin
4630
    K      := K shr 1;
4631
    Value  := Value  xor (Result and Key[(K + 2) and 7 + 8]);
4632
    Result := Result xor (Value  or  Key[(K + 4) and 7]);
4633
  end else
4634
  begin
4635
    K      := K shr 1;
4636
    Value  := Value  xor (Result and Key[K]);
4637
    Result := Result xor (Value  or  Key[(K + 6) and 7 + 8]);
4638
  end;
4639
  Result:= (Result shl 16) or Value;
4640
end;
4641
 
4642
function Misty_D(Value, K: LongWord; Key: PLongArray): LongWord;
4643
begin
4644
  Result := Value shr 16;
4645
  Value  := Value and $FFFF;
4646
  if K and 1 <> 0 then
4647
  begin
4648
    K      := K shr 1;
4649
    Result := Result xor (Value  or  Key[(K + 4) and 7]);
4650
    Value  := Value  xor (Result and Key[(K + 2) and 7 + 8]);
4651
  end else
4652
  begin
4653
    K      := K shr 1;
4654
    Result := Result xor (Value  or  Key[(K +6) and 7 + 8]);
4655
    Value  := Value  xor (Result and Key[K]);
4656
  end;
4657
  Result:= (Result shl 16) or Value;
4658
end;
4659
 
4660
procedure TCipher_Misty.DoInit(const Key; Size: Integer);
4661
var
4662
  K: array[0..15] of Byte;
4663
  D: PLongArray;
4664
  I: Integer;
4665
begin
4666
  FillChar(K, SizeOf(K), 0);
4667
  Move(Key, K, Size);
4668
  D := FUser;
4669
  for I := 0 to 7 do
4670
    D[I] := K[I * 2] * 256 + K[I * 2 +1];
4671
  for I := 0 to 7 do
4672
  begin
4673
    D[I +  8] := Misty_I(D[I], D[(I + 1) and 7]);
4674
    D[I + 16] := D[I + 8] and $1FF;
4675
    D[I + 24] := D[I + 8] shr 9;
4676
  end;
4677
  ProtectBuffer(K, SizeOf(K));
4678
end;
4679
 
4680
procedure TCipher_Misty.DoEncode(Source, Dest: Pointer; Size: Integer);
4681
var
4682
  A,B: LongWord;
4683
begin
4684
  Assert(Size = Context.BufferSize);
4685
 
4686
  A := PLongArray(Source)[0];
4687
  B := PLongArray(Source)[1];
4688
  A := Misty_E(A, 0, FUser);
4689
  B := Misty_E(B, 1, FUser) xor Misty_O(A, 0, FUser);
4690
  A := A xor Misty_O(B, 1, FUser);
4691
  A := Misty_E(A, 2, FUser);
4692
  B := Misty_E(B, 3, FUser) xor Misty_O(A, 2, FUser);
4693
  A := A xor Misty_O(B, 3, FUser);
4694
  A := Misty_E(A, 4, FUser);
4695
  B := Misty_E(B, 5, FUser) xor Misty_O(A, 4, FUser);
4696
  A := A xor Misty_O(B, 5, FUser);
4697
  A := Misty_E(A, 6, FUser);
4698
  B := Misty_E(B, 7, FUser) xor Misty_O(A, 6, FUser);
4699
  A := A xor Misty_O(B, 7, FUser);
4700
  PLongArray(Dest)[0] := Misty_E(B, 9, FUser);
4701
  PLongArray(Dest)[1] := Misty_E(A, 8, FUser);
4702
end;
4703
 
4704
procedure TCipher_Misty.DoDecode(Source, Dest: Pointer; Size: Integer);
4705
var
4706
  A,B: LongWord;
4707
begin
4708
  Assert(Size = Context.BufferSize);
4709
 
4710
  B := Misty_D(PLongArray(Source)[0], 9, FUser);
4711
  A := Misty_D(PLongArray(Source)[1], 8, FUser);
4712
  A := A xor Misty_O(B, 7, FUser);
4713
  B := Misty_D(B xor Misty_O(A, 6, FUser), 7, FUser);
4714
  A := Misty_D(A, 6, FUser);
4715
  A := A xor Misty_O(B, 5, FUser);
4716
  B := Misty_D(B xor Misty_O(A, 4, FUser), 5, FUser);
4717
  A := Misty_D(A, 4, FUser);
4718
  A := A xor Misty_O(B, 3, FUser);
4719
  B := Misty_D(B xor Misty_O(A, 2, FUser), 3, FUser);
4720
  A := Misty_D(A, 2, FUser);
4721
  A := A xor Misty_O(B, 1, FUser);
4722
  PLongArray(Dest)[0] := Misty_D(A, 0, FUser);
4723
  PLongArray(Dest)[1] := Misty_D(B xor Misty_O(A, 0, FUser), 1, FUser);
4724
end;
4725
 
4726
// .TCipher_NewDES
4727
class function TCipher_NewDES.Context: TCipherContext;
4728
begin
4729
  Result.KeySize := 15;
4730
  Result.BlockSize := 8;
4731
  Result.BufferSize := 8;
4732
  Result.UserSize := 60 * 2;
4733
  Result.UserSave := True;
4734
end;
4735
 
4736
procedure TCipher_NewDES.DoInit(const Key; Size: Integer);
4737
var
4738
  K: array[0..14] of Byte;
4739
  E: PByteArray;
4740
  I: Integer;
4741
begin
4742
  FillChar(K, SizeOf(K), 0);
4743
  Move(Key, K, Size);
4744
  E := FUser;
4745
  Move(K, E[ 0], 15);
4746
  Move(K, E[15], 15);
4747
  Move(K, E[30], 15);
4748
  Move(K, E[45], 15);
4749
  E := @E[60];
4750
  I := 11;
4751
  repeat
4752
    E[0] := K[I]; I := (I +1) mod 15;
4753
    E[1] := K[I]; I := (I +1) mod 15;
4754
    E[2] := K[I]; I := (I +1) mod 15;
4755
    E[3] := K[I]; I := (I +9) mod 15;
4756
    if I = 12 then Break;
4757
    E[4] := K[I]; Inc(I);
4758
    E[5] := K[I]; Inc(I);
4759
    E[6] := K[I]; I := (I + 9) mod 15;
4760
    E := @E[7];
4761
  until False;
4762
  ProtectBuffer(K, SizeOf(K));
4763
end;
4764
 
4765
procedure NewDES_Func(Source, Dest, Key: PByteArray);
4766
var
4767
  I: Integer;
4768
  A,B,C,D,E,F,G,H: Byte;
4769
begin
4770
  A := Source[0];
4771
  B := Source[1];
4772
  C := Source[2];
4773
  D := Source[3];
4774
  E := Source[4];
4775
  F := Source[5];
4776
  G := Source[6];
4777
  H := Source[7];
4778
  for I := 0 to 7 do
4779
  begin
4780
    E := E xor NewDES_Data[A xor Key[0]];
4781
    F := F xor NewDES_Data[B xor Key[1]];
4782
    G := G xor NewDES_Data[C xor Key[2]];
4783
    H := H xor NewDES_Data[D xor Key[3]];
4784
    B := B xor NewDES_Data[E xor Key[4]];
4785
    C := C xor NewDES_Data[F xor E];
4786
    D := D xor NewDES_Data[G xor Key[5]];
4787
    A := A xor NewDES_Data[H xor Key[6]];
4788
    Key := @Key[7];
4789
  end;
4790
  E := E xor NewDES_Data[A xor Key[0]];
4791
  F := F xor NewDES_Data[B xor Key[1]];
4792
  G := G xor NewDES_Data[C xor Key[2]];
4793
  H := H xor NewDES_Data[D xor Key[3]];
4794
  Dest[0] := A;
4795
  Dest[1] := B;
4796
  Dest[2] := C;
4797
  Dest[3] := D;
4798
  Dest[4] := E;
4799
  Dest[5] := F;
4800
  Dest[6] := G;
4801
  Dest[7] := H;
4802
end;
4803
 
4804
procedure TCipher_NewDES.DoEncode(Source, Dest: Pointer; Size: Integer);
4805
begin
4806
  Assert(Size = Context.BufferSize);
4807
  NewDES_Func(Source, Dest, FUser);
4808
end;
4809
 
4810
procedure TCipher_NewDES.DoDecode(Source, Dest: Pointer; Size: Integer);
4811
begin
4812
  Assert(Size = Context.BufferSize);
4813
  NewDES_Func(Source, Dest, @PByteArray(FUser)[60]);
4814
end;
4815
 
4816
// .TCipher_Q128
4817
class function TCipher_Q128.Context: TCipherContext;
4818
begin
4819
  Result.KeySize := 16;
4820
  Result.BlockSize := 16;
4821
  Result.BufferSize := 16;
4822
  Result.UserSize := 256;
4823
  Result.UserSave := False;
4824
end;
4825
 
4826
procedure TCipher_Q128.DoInit(const Key; Size: Integer);
4827
var
4828
  K: array[0..3] of LongWord;
4829
  D: PLongArray;
4830
  I: Integer;
4831
begin
4832
  FillChar(K, SizeOf(K), 0);
4833
  Move(Key, K, Size);
4834
  D := FUser;
4835
  for I := 19 downto 1 do
4836
  begin
4837
    K[1] := K[1] xor Q128_Data[K[0] and $03FF]; K[0] := K[0] shr 10 or K[0] shl 22;
4838
    K[2] := K[2] xor Q128_Data[K[1] and $03FF]; K[1] := K[1] shr 10 or K[1] shl 22;
4839
    K[3] := K[3] xor Q128_Data[K[2] and $03FF]; K[2] := K[2] shr 10 or K[2] shl 22;
4840
    K[0] := K[0] xor Q128_Data[K[3] and $03FF]; K[3] := K[3] shr 10 or K[3] shl 22;
4841
    if I <= 16 then
4842
    begin
4843
      D[0] := K[0];
4844
      D[1] := K[1];
4845
      D[2] := K[2];
4846
      D[3] := K[3];
4847
      D := @D[4];
4848
    end;
4849
  end;
4850
  ProtectBuffer(K, SizeOf(K));
4851
end;
4852
 
4853
procedure TCipher_Q128.DoEncode(Source, Dest: Pointer; Size: Integer);
4854
{$IFDEF UseASM}
4855
asm
4856
       PUSH   ESI
4857
       PUSH   EDI
4858
       PUSH   EBX
4859
       PUSH   EBP
4860
       PUSH   ECX
4861
       MOV    EDI,[EAX].TCipher_Q128.FUser
4862
       MOV    EAX,[EDX +  0]  // B0
4863
       MOV    EBX,[EDX +  4]  // B1
4864
       MOV    ECX,[EDX +  8]  // B2
4865
       MOV    EDX,[EDX + 12]  // B3
4866
       MOV    EBP,16
4867
@@1:   MOV    ESI,EAX
4868
       ROL    ESI,10
4869
       AND    EAX,03FFh
4870
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4871
       ADD    EAX,[EDI + 0]
4872
       XOR    EAX,EBX
4873
       MOV    EBX,EAX
4874
       ROL    EBX,10
4875
       AND    EAX,03FFh
4876
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4877
       ADD    EAX,[EDI + 4]
4878
       XOR    EAX,ECX
4879
       MOV    ECX,EAX
4880
       ROL    ECX,10
4881
       AND    EAX,03FFh
4882
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4883
       ADD    EAX,[EDI + 8]
4884
       XOR    EAX,EDX
4885
       MOV    EDX,EAX
4886
       ROL    EDX,10
4887
       AND    EAX,03FFh
4888
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4889
       ADD    EAX,[EDI + 12]
4890
       XOR    EAX,ESI
4891
       DEC    EBP
4892
       LEA    EDI,[EDI + 16]
4893
       JNZ    @@1
4894
       POP    ESI
4895
       MOV    [ESI +  0],EAX  // B0
4896
       MOV    [ESI +  4],EBX  // B1
4897
       MOV    [ESI +  8],ECX  // B2
4898
       MOV    [ESI + 12],EDX  // B3
4899
       POP    EBP
4900
       POP    EBX
4901
       POP    EDI
4902
       POP    ESI
4903
end;
4904
{$ELSE}
4905
var
4906
  D: PLongArray;
4907
  B0,B1,B2,B3,I: LongWord;
4908
begin
4909
  Assert(Size = Context.BufferSize);
4910
 
4911
  D  := FUser;
4912
  B0 := PLongArray(Source)[0];
4913
  B1 := PLongArray(Source)[1];
4914
  B2 := PLongArray(Source)[2];
4915
  B3 := PLongArray(Source)[3];
4916
  for I := 0 to 15 do
4917
  begin
4918
    B1 := B1 xor (Q128_Data[B0 and $03FF] + D[0]); B0 := B0 shl 10 or B0 shr 22;
4919
    B2 := B2 xor (Q128_Data[B1 and $03FF] + D[1]); B1 := B1 shl 10 or B1 shr 22;
4920
    B3 := B3 xor (Q128_Data[B2 and $03FF] + D[2]); B2 := B2 shl 10 or B2 shr 22;
4921
    B0 := B0 xor (Q128_Data[B3 and $03FF] + D[3]); B3 := B3 shl 10 or B3 shr 22;
4922
    D := @D[4];
4923
  end;
4924
  PLongArray(Dest)[0] := B0;
4925
  PLongArray(Dest)[1] := B1;
4926
  PLongArray(Dest)[2] := B2;
4927
  PLongArray(Dest)[3] := B3;
4928
end;
4929
{$ENDIF}
4930
 
4931
procedure TCipher_Q128.DoDecode(Source, Dest: Pointer; Size: Integer);
4932
{$IFDEF UseASM}
4933
asm
4934
       PUSH   ESI
4935
       PUSH   EDI
4936
       PUSH   EBX
4937
       PUSH   EBP
4938
       PUSH   ECX
4939
       MOV    EDI,[EAX].TCipher_Q128.FUser
4940
       LEA    EDI,[EDI + 64 * 4]
4941
       MOV    ESI,[EDX +  0]   // B0
4942
       MOV    EBX,[EDX +  4]  // B1
4943
       MOV    ECX,[EDX +  8]  // B2
4944
       MOV    EDX,[EDX + 12]  // B3
4945
       MOV    EBP,16
4946
@@1:   SUB    EDI,16
4947
       ROR    EDX,10
4948
       MOV    EAX,EDX
4949
       AND    EAX,03FFh
4950
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4951
       ADD    EAX,[EDI + 12]
4952
       XOR    ESI,EAX
4953
       ROR    ECX,10
4954
       MOV    EAX,ECX
4955
       AND    EAX,03FFh
4956
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4957
       ADD    EAX,[EDI +  8]
4958
       XOR    EDX,EAX
4959
       ROR    EBX,10
4960
       MOV    EAX,EBX
4961
       AND    EAX,03FFh
4962
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4963
       ADD    EAX,[EDI +  4]
4964
       XOR    ECX,EAX
4965
       ROR    ESI,10
4966
       MOV    EAX,ESI
4967
       AND    EAX,03FFh
4968
       MOV    EAX,[EAX * 4 + OFFSET Q128_DATA]
4969
       ADD    EAX,[EDI]
4970
       XOR    EBX,EAX
4971
       DEC    EBP
4972
       JNZ    @@1
4973
       POP    EAX
4974
       MOV    [EAX +  0],ESI  // B0
4975
       MOV    [EAX +  4],EBX  // B1
4976
       MOV    [EAX +  8],ECX  // B2
4977
       MOV    [EAX + 12],EDX  // B3
4978
       POP    EBP
4979
       POP    EBX
4980
       POP    EDI
4981
       POP    ESI
4982
end;
4983
{$ELSE}
4984
var
4985
  D: PLongArray;
4986
  B0,B1,B2,B3,I: LongWord;
4987
begin
4988
  Assert(Size = Context.BufferSize);
4989
 
4990
  D  := @PLongArray(FUser)[60];
4991
  B0 := PLongArray(Source)[0];
4992
  B1 := PLongArray(Source)[1];
4993
  B2 := PLongArray(Source)[2];
4994
  B3 := PLongArray(Source)[3];
4995
  for I := 0 to 15 do
4996
  begin
4997
    B3 := B3 shr 10 or B3 shl 22; B0 := B0 xor (Q128_Data[B3 and $03FF] + D[3]);
4998
    B2 := B2 shr 10 or B2 shl 22; B3 := B3 xor (Q128_Data[B2 and $03FF] + D[2]);
4999
    B1 := B1 shr 10 or B1 shl 22; B2 := B2 xor (Q128_Data[B1 and $03FF] + D[1]);
5000
    B0 := B0 shr 10 or B0 shl 22; B1 := B1 xor (Q128_Data[B0 and $03FF] + D[0]);
5001
    Dec(PLongWord(D), 4);
5002
  end;
5003
  PLongArray(Dest)[0] := B0;
5004
  PLongArray(Dest)[1] := B1;
5005
  PLongArray(Dest)[2] := B2;
5006
  PLongArray(Dest)[3] := B3;
5007
end;
5008
{$ENDIF}
5009
 
5010
// .TCipher_RC2
5011
class function TCipher_RC2.Context: TCipherContext;
5012
begin
5013
  Result.KeySize := 128;
5014
  Result.BlockSize := 8;
5015
  Result.BufferSize := 8;
5016
  Result.UserSize := 128;
5017
  Result.UserSave := False;
5018
end;
5019
 
5020
procedure TCipher_RC2.DoInit(const Key; Size: Integer);
5021
// New keysheduling according to RFC2268 and its testcases.
5022
// the v3.0 keysetup was an older, bad version
5023
// special thanks goes to Brendan Bosnan to pointing me out that.
5024
var
5025
  I,L,Mask,KeyEffectiveBits: Integer;
5026
  K: PByteArray;
5027
begin
5028
  if Size <= 0 then Exit;
5029
  KeyEffectiveBits := Size * 8;
5030
  L := KeyEffectiveBits and 7;
5031
  if L = 0 then Mask := $FF
5032
    else Mask := $FF shr (8 - L);
5033
  L := (KeyEffectiveBits + 7) shr 3;
5034
  K := FUser;
5035
  Move(Key, K[0], Size);
5036
  for I := Size to 127 do
5037
    K[I] := RC2_Data[(K[I - Size] + K[I - 1]) and $FF];
5038
  K[128 - L] := RC2_Data[K[128 - L] and Mask];
5039
  for I := 127 - L downto 0 do
5040
     K[I] := RC2_Data[K[I + 1] xor K[I + L]];
5041
end;
5042
 
5043
procedure TCipher_RC2.DoEncode(Source, Dest: Pointer; Size: Integer);
5044
var
5045
  I: Integer;
5046
  K: PWordArray;
5047
  A,B,C,D: Word;
5048
begin
5049
  Assert(Size = Context.BufferSize);
5050
 
5051
  K := FUser;
5052
  A := PWordArray(Source)[0];
5053
  B := PWordArray(Source)[1];
5054
  C := PWordArray(Source)[2];
5055
  D := PWordArray(Source)[3];
5056
  for I := 0 to 15 do
5057
  begin
5058
    Inc(A, (B and not D) + (C and D) + K[I * 4 +0]); A := A shl 1 or A shr 15;
5059
    Inc(B, (C and not A) + (D and A) + K[I * 4 +1]); B := B shl 2 or B shr 14;
5060
    Inc(C, (D and not B) + (A and B) + K[I * 4 +2]); C := C shl 3 or C shr 13;
5061
    Inc(D, (A and not C) + (B and C) + K[I * 4 +3]); D := D shl 5 or D shr 11;
5062
    if I in [4, 10] then
5063
    begin
5064
      Inc(A, K[D and $3F]);
5065
      Inc(B, K[A and $3F]);
5066
      Inc(C, K[B and $3F]);
5067
      Inc(D, K[C and $3F]);
5068
    end;
5069
  end;
5070
  PWordArray(Dest)[0] := A;
5071
  PWordArray(Dest)[1] := B;
5072
  PWordArray(Dest)[2] := C;
5073
  PWordArray(Dest)[3] := D;
5074
end;
5075
 
5076
procedure TCipher_RC2.DoDecode(Source, Dest: Pointer; Size: Integer);
5077
var
5078
  I: Integer;
5079
  K: PWordArray;
5080
  A,B,C,D: Word;
5081
begin
5082
  Assert(Size = Context.BlockSize);
5083
 
5084
  K := FUser;
5085
  A := PWordArray(Source)[0];
5086
  B := PWordArray(Source)[1];
5087
  C := PWordArray(Source)[2];
5088
  D := PWordArray(Source)[3];
5089
  for I := 15 downto 0 do
5090
  begin
5091
    D := D shr 5 or D shl 11 - (A and not C) - (B and C) - K[I * 4 +3];
5092
    C := C shr 3 or C shl 13 - (D and not B) - (A and B) - K[I * 4 +2];
5093
    B := B shr 2 or B shl 14 - (C and not A) - (D and A) - K[I * 4 +1];
5094
    A := A shr 1 or A shl 15 - (B and not D) - (C and D) - K[I * 4 +0];
5095
    if I in [5, 11] then
5096
    begin
5097
      Dec(D, K[C and $3F]);
5098
      Dec(C, K[B and $3F]);
5099
      Dec(B, K[A and $3F]);
5100
      Dec(A, K[D and $3F]);
5101
    end;
5102
  end;
5103
  PWordArray(Dest)[0] := A;
5104
  PWordArray(Dest)[1] := B;
5105
  PWordArray(Dest)[2] := C;
5106
  PWordArray(Dest)[3] := D;
5107
end;
5108
 
5109
// .TCipher_RC5
5110
class function TCipher_RC5.Context: TCipherContext;
5111
begin
5112
  Result.KeySize := 256;
5113
  Result.BlockSize := 8;
5114
  Result.BufferSize := 8;
5115
  Result.UserSize := 136;
5116
  Result.UserSave := False;
5117
end;
5118
 
5119
procedure TCipher_RC5.SetRounds(Value: Integer);
5120
begin
5121
  if Value <> FRounds then
5122
  begin
5123
    if not (FState in [csNew, csInitialized, csDone]) then Done;
5124
    if Value <= 0 then Value := 12;
5125
    FRounds := Value;
5126
  end;
5127
end;
5128
 
5129
procedure TCipher_RC5.DoInit(const Key; Size: Integer);
5130
var
5131
  K: array[0..63] of LongWord;
5132
  L,Z,I,J: Integer;
5133
  D: PLongArray;
5134
  A,B,T: LongWord;
5135
begin
5136
  if FRounds <= 0 then FRounds := 12;
5137
  FillChar(K, SizeOf(K), 0);
5138
  Move(Key, K, Size);
5139
  D := FUser;
5140
  L := (Size +3) shr 2;
5141
  if L <= 0 then L := 1;
5142
  T := $B7E15163;
5143
  for I := 0 to (FRounds + 1) * 2 do
5144
  begin
5145
    D[I] := T;
5146
    Inc(T, $9E3779B9);
5147
  end;
5148
  if L > (FRounds + 1) * 2 then Z := L * 3
5149
    else Z := (FRounds + 1) * 6;
5150
  I := 0;
5151
  J := 0;
5152
  A := 0;
5153
  B := 0;
5154
  for Z := Z downto 1 do
5155
  begin
5156
    A := D[I] + A + B;
5157
    A := A shl 3 or A shr 29;
5158
    D[I] := A;
5159
    T := A + B;
5160
    B := K[J] + T;
5161
    B := B shl T or B shr (32 - T);
5162
    K[J] := B;
5163
    I := (I + 1) mod ((FRounds + 1) * 2);
5164
    J := (J + 1) mod L;
5165
  end;
5166
  ProtectBuffer(K, SizeOf(K));
5167
end;
5168
 
5169
procedure TCipher_RC5.DoEncode(Source, Dest: Pointer; Size: Integer);
5170
var
5171
  K: PLongArray;
5172
  I: Integer;
5173
  A,B: LongWord;
5174
begin
5175
  Assert(Size = Context.BufferSize);
5176
 
5177
  K := FUser;
5178
  A := PLongArray(Source)[0] + K[0];
5179
  B := PLongArray(Source)[1] + K[1];
5180
  for I := 1 to FRounds do
5181
  begin
5182
    A := A xor B; A := A shl B or A shr (32 - B) + K[I * 2 +0];
5183
    B := B xor A; B := B shl A or B shr (32 - A) + K[I * 2 +1];
5184
  end;
5185
  PLongArray(Dest)[0] := A;
5186
  PLongArray(Dest)[1] := B;
5187
end;
5188
 
5189
procedure TCipher_RC5.DoDecode(Source, Dest: Pointer; Size: Integer);
5190
var
5191
  K: PLongArray;
5192
  I: Integer;
5193
  A,B: LongWord;
5194
begin
5195
  Assert(Size = Context.BufferSize);
5196
 
5197
  K := @PLongArray(FUser)[0];
5198
  A := PLongArray(Source)[0];
5199
  B := PLongArray(Source)[1];
5200
  for I := FRounds downto 1 do
5201
  begin
5202
    B := B - K[I * 2 +1]; B := B shr A or B shl (32 - A) xor A;
5203
    A := A - K[I * 2 +0]; A := A shr B or A shl (32 - B) xor B;
5204
  end;
5205
  PLongArray(Dest)[0] := A - K[0];
5206
  PLongArray(Dest)[1] := B - K[1];
5207
end;
5208
 
5209
// .TCipher_SAFER
5210
class function TCipher_SAFER.Context: TCipherContext;
5211
begin
5212
  Result.KeySize := 16;
5213
  Result.BlockSize := 8;
5214
  Result.BufferSize := 8;
5215
  Result.UserSize := 768;
5216
  Result.UserSave := False;
5217
end;
5218
 
5219
procedure TCipher_SAFER.SetRounds(Value: Integer);
5220
begin
5221
  if not (FState in [csNew, csInitialized, csDone]) then Done;
5222
  if (Value < 4) or (Value > 13) then
5223
    case FVersion of  {Default Rounds}
5224
      svK40, svSK40: Value := 5;
5225
      svK64, svSK64: Value := 6;
5226
      svK128, svSK128: Value := 10;
5227
    else
5228
      Value := 8;
5229
    end;
5230
  FRounds := Value;
5231
end;
5232
 
5233
procedure TCipher_SAFER.SetVersion(Value: TSAFERVersion);
5234
begin
5235
  if Value <> FVersion then
5236
  begin
5237
    if not (FState in [csNew, csInitialized, csDone]) then Done;
5238
    FVersion := Value;
5239
    SetRounds(0);
5240
  end;
5241
end;
5242
 
5243
procedure TCipher_SAFER.DoInit(const Key; Size: Integer);
5244
 
5245
  procedure InitTab;
5246
  var
5247
    I,E: Integer;
5248
    Exp: PByteArray;
5249
    Log: PByteArray;
5250
  begin
5251
    Exp := FUser;
5252
    Log := @Exp[256];
5253
    E   := 1;
5254
    for I := 0 to 255 do
5255
    begin
5256
      Exp[I] := E and $FF;
5257
      Log[E and $FF] := I;
5258
      E := (E * 45) mod 257;
5259
    end;
5260
  end;
5261
 
5262
  procedure InitKey;
5263
  var
5264
    D: PByte;
5265
    Exp: PByteArray;
5266
    Strong: Boolean;
5267
    K: array[Boolean, 0..8] of Byte;
5268
    I,J: Integer;
5269
  begin
5270
    Strong := FVersion in [svSK40, svSK64, svSK128];
5271
    Exp := FUser;
5272
    D := @Exp[512];
5273
    FillChar(K, SizeOf(K), 0);
5274
{Setup Key A}
5275
    I := Size;
5276
    if I > 8 then I := 8;
5277
    Move(Key, K[False], I);
5278
{Setup the Key for K-40, SK-40}
5279
    if FVersion in [svK40, svSK40] then
5280
    begin
5281
      K[False, 5] := K[False, 0] xor K[False, 2] xor 129;
5282
      K[False, 6] := K[False, 0] xor K[False, 3] xor K[False, 4] xor 66;
5283
      K[False, 7] := K[False, 1] xor K[False, 2] xor K[False, 4] xor 36;
5284
      K[False, 8] := K[False, 1] xor K[False, 3] xor 24;
5285
      Move(K[False], K[True], SizeOf(K[False]));
5286
    end else
5287
    begin
5288
      if Size > 8 then
5289
      begin
5290
        I := Size - 8;
5291
        if I > 8 then I := 8;
5292
        Move(TByteArray(Key)[8], K[True], I);
5293
      end else Move(K[False], K[True], 9);
5294
      for I := 0 to 7 do
5295
      begin
5296
        K[False, 8] := K[False, 8] xor K[False, I];
5297
        K[True, 8]  := K[True, 8]  xor K[True, I];
5298
      end;
5299
    end;
5300
{Setup the KeyData}
5301
    Move(K[True], D^, 8);
5302
    Inc(D, 8);
5303
 
5304
    for I := 0 to 8 do
5305
      K[False, I] := K[False, I] shr 3 or K[False, I] shl 5;
5306
 
5307
    for I := 1 to FRounds do
5308
    begin
5309
      for J := 0 to 8 do
5310
      begin
5311
        K[False, J] := K[False, J] shl 6 or K[False, J] shr 2;
5312
        K[True, J] := K[True, J] shl 6 or K[True, J] shr 2;
5313
      end;
5314
      for J := 0 to 7 do
5315
      begin
5316
        if Strong then D^ := K[False, (J + I * 2 -1) mod 9] + Exp[Exp[18 * I + J +1]]
5317
          else D^ := K[False, J] + Exp[Exp[18 * I + J +1]];
5318
        Inc(D);
5319
      end;
5320
      for J := 0 to 7 do
5321
      begin
5322
        if Strong then D^ := K[True, (J + I * 2) mod 9] + Exp[Exp[18 * I + J +10]]
5323
          else D^ := K[True, J] + Exp[Exp[18 * I + J +10]];
5324
        Inc(D);
5325
      end;
5326
    end;
5327
    ProtectBuffer(K, SizeOf(K));
5328
  end;
5329
 
5330
begin
5331
  if (FRounds < 4) or (FRounds > 13) then
5332
    case FVersion of
5333
      svK40, svSK40: FRounds := 5;
5334
      svK64, svSK64: FRounds := 6;
5335
      svK128, svSK128: FRounds := 10;
5336
    else
5337
      FRounds := 8;
5338
    end;
5339
  InitTab;
5340
  InitKey;
5341
end;
5342
 
5343
procedure TCipher_SAFER.DoEncode(Source, Dest: Pointer; Size: Integer);
5344
var
5345
  Exp,Log,Key: PByteArray;
5346
  I: Integer;
5347
  A,B,C,D,E,F,G,H,T: Byte;
5348
begin
5349
  Assert(Size = Context.BufferSize);
5350
 
5351
  Exp := FUser;
5352
  Log := @Exp[256];
5353
  Key := @Exp[512];
5354
  A := PByteArray(Source)[0];
5355
  B := PByteArray(Source)[1];
5356
  C := PByteArray(Source)[2];
5357
  D := PByteArray(Source)[3];
5358
  E := PByteArray(Source)[4];
5359
  F := PByteArray(Source)[5];
5360
  G := PByteArray(Source)[6];
5361
  H := PByteArray(Source)[7];
5362
  for I := 0 to FRounds -1 do
5363
  begin
5364
    A := A xor Key[0];
5365
    B := B  +  Key[1];
5366
    C := C  +  Key[2];
5367
    D := D xor Key[3];
5368
    E := E xor Key[4];
5369
    F := F  +  Key[5];
5370
    G := G  +  Key[6];
5371
    H := H xor Key[7];
5372
    A := Exp[A]  +  Key[8];
5373
    B := Log[B] xor Key[9];
5374
    C := Log[C] xor Key[10];
5375
    D := Exp[D]  +  Key[11];
5376
    E := Exp[E]  +  Key[12];
5377
    F := Log[F] xor Key[13];
5378
    G := Log[G] xor Key[14];
5379
    H := Exp[H]  +  Key[15];
5380
    Inc(B, A); Inc(A, B);
5381
    Inc(D, C); Inc(C, D);
5382
    Inc(F, E); Inc(E, F);
5383
    Inc(H, G); Inc(G, H);
5384
    Inc(C, A); Inc(A, C);
5385
    Inc(G, E); Inc(E, G);
5386
    Inc(D, B); Inc(B, D);
5387
    Inc(H, F); Inc(F, H);
5388
    Inc(E, A); Inc(A, E);
5389
    Inc(F, B); Inc(B, F);
5390
    Inc(G, C); Inc(C, G);
5391
    Inc(H, D); Inc(D, H);
5392
    T := B; B := E; E := C; C := T;
5393
    T := D; D := F; F := G; G := T;
5394
    Key := @Key[16];
5395
  end;
5396
  PByteArray(Dest)[0] := A xor Key[0];
5397
  PByteArray(Dest)[1] := B  +  Key[1];
5398
  PByteArray(Dest)[2] := C  +  Key[2];
5399
  PByteArray(Dest)[3] := D xor Key[3];
5400
  PByteArray(Dest)[4] := E xor Key[4];
5401
  PByteArray(Dest)[5] := F  +  Key[5];
5402
  PByteArray(Dest)[6] := G  +  Key[6];
5403
  PByteArray(Dest)[7] := H xor Key[7];
5404
end;
5405
 
5406
procedure TCipher_SAFER.DoDecode(Source, Dest: Pointer; Size: Integer);
5407
var
5408
  Exp,Log,Key: PByteArray;
5409
  I: Integer;
5410
  A,B,C,D,E,F,G,H,T: Byte;
5411
begin
5412
  Assert(Size = Context.BufferSize);
5413
 
5414
  Exp := FUser;
5415
  Log := @Exp[256];
5416
  Key := @Exp[504 + 8 * (FRounds * 2 + 1)];
5417
  A := PByteArray(Source)[0] xor Key[0];
5418
  B := PByteArray(Source)[1]  -  Key[1];
5419
  C := PByteArray(Source)[2]  -  Key[2];
5420
  D := PByteArray(Source)[3] xor Key[3];
5421
  E := PByteArray(Source)[4] xor Key[4];
5422
  F := PByteArray(Source)[5]  -  Key[5];
5423
  G := PByteArray(Source)[6]  -  Key[6];
5424
  H := PByteArray(Source)[7] xor Key[7];
5425
  for I := 0 to FRounds -1 do
5426
  begin
5427
    Dec(PByte(Key), 16);
5428
    T := E; E := B; B := C; C := T;
5429
    T := F; F := D; D := G; G := T;
5430
    Dec(A, E); Dec(E, A);
5431
    Dec(B, F); Dec(F, B);
5432
    Dec(C, G); Dec(G, C);
5433
    Dec(D, H); Dec(H, D);
5434
    Dec(A, C); Dec(C, A);
5435
    Dec(E, G); Dec(G, E);
5436
    Dec(B, D); Dec(D, B);
5437
    Dec(F, H); Dec(H, F);
5438
    Dec(A, B); Dec(B, A);
5439
    Dec(C, D); Dec(D, C);
5440
    Dec(E, F); Dec(F, E);
5441
    Dec(G, H); Dec(H, G);
5442
    H := H  -  Key[15];
5443
    G := G xor Key[14];
5444
    F := F xor Key[13];
5445
    E := E  -  Key[12];
5446
    D := D  -  Key[11];
5447
    C := C xor Key[10];
5448
    B := B xor Key[9];
5449
    A := A  -  Key[8];
5450
    H := Log[H] xor Key[7];
5451
    G := Exp[G]  -  Key[6];
5452
    F := Exp[F]  -  Key[5];
5453
    E := Log[E] xor Key[4];
5454
    D := Log[D] xor Key[3];
5455
    C := Exp[C]  -  Key[2];
5456
    B := Exp[B]  -  Key[1];
5457
    A := Log[A] xor Key[0];
5458
  end;
5459
  PByteArray(Dest)[0] := A;
5460
  PByteArray(Dest)[1] := B;
5461
  PByteArray(Dest)[2] := C;
5462
  PByteArray(Dest)[3] := D;
5463
  PByteArray(Dest)[4] := E;
5464
  PByteArray(Dest)[5] := F;
5465
  PByteArray(Dest)[6] := G;
5466
  PByteArray(Dest)[7] := H;
5467
end;
5468
 
5469
// .TCipher_Shark
5470
type
5471
  PLong64 = ^TLong64;
5472
  TLong64  = packed record
5473
               L,R: LongWord;
5474
             end;
5475
 
5476
  PLong64Array = ^TLong64Array;
5477
  TLong64Array = array[0..1023] of TLong64;
5478
 
5479
class function TCipher_Shark.Context: TCipherContext;
5480
begin
5481
  Result.KeySize := 16;
5482
  Result.BlockSize := 8;
5483
  Result.BufferSize := 8;
5484
  Result.UserSize := 112;
5485
  Result.UserSave := False;
5486
end;
5487
 
5488
procedure TCipher_Shark.DoInit(const Key; Size: Integer);
5489
var
5490
  Log, ALog: array[0..255] of Byte;
5491
 
5492
  procedure InitLog;
5493
  var
5494
    I, J: Word;
5495
  begin
5496
    ALog[0] := 1;
5497
    for I := 1 to 255 do
5498
    begin
5499
      J := ALog[I-1] shl 1;
5500
      if J and $100 <> 0 then J := J xor $01F5;
5501
      ALog[I] := J;
5502
    end;
5503
    for I := 1 to 254 do Log[ALog[I]] := I;
5504
  end;
5505
 
5506
  function Transform(A: TLong64): TLong64;
5507
 
5508
    function Mul(A, B: Integer): Byte;
5509
    begin
5510
      Result := ALog[(Log[A] + Log[B]) mod 255];
5511
    end;
5512
 
5513
  var
5514
    I,J: Byte;
5515
    K,T: array[0..7] of Byte;
5516
  begin
5517
    Move(A.R, K[0], 4);
5518
    Move(A.L, K[4], 4);
5519
    SwapLongBuffer(K, K, 2);
5520
    for I := 0 to 7 do
5521
    begin
5522
      T[I] := Mul(Shark_I[I, 0], K[0]);
5523
      for J := 1 to 7 do T[I] := T[I] xor Mul(Shark_I[I, J], K[J]);
5524
    end;
5525
    Result.L := T[0];
5526
    Result.R := 0;
5527
    for I := 1 to 7 do
5528
    begin
5529
      Result.R := Result.R shl 8 or Result.L shr 24;
5530
      Result.L := Result.L shl 8 xor T[I];
5531
    end;
5532
  end;
5533
 
5534
  function Shark(D: TLong64; K: PLong64): TLong64;
5535
  var
5536
    R,T: Integer;
5537
  begin
5538
    for R := 0 to 4 do
5539
    begin
5540
      D.L := D.L xor K.L;
5541
      D.R := D.R xor K.R;
5542
      Inc(K);
5543
      T   := Shark_CE[0, D.R shr 23 and $1FE] xor
5544
             Shark_CE[1, D.R shr 15 and $1FE] xor
5545
             Shark_CE[2, D.R shr  7 and $1FE] xor
5546
             Shark_CE[3, D.R shl  1 and $1FE] xor
5547
             Shark_CE[4, D.L shr 23 and $1FE] xor
5548
             Shark_CE[5, D.L shr 15 and $1FE] xor
5549
             Shark_CE[6, D.L shr  7 and $1FE] xor
5550
             Shark_CE[7, D.L shl  1 and $1FE];
5551
 
5552
      D.R := Shark_CE[0, D.R shr 23 and $1FE or 1] xor
5553
             Shark_CE[1, D.R shr 15 and $1FE or 1] xor
5554
             Shark_CE[2, D.R shr  7 and $1FE or 1] xor
5555
             Shark_CE[3, D.R shl  1 and $1FE or 1] xor
5556
             Shark_CE[4, D.L shr 23 and $1FE or 1] xor
5557
             Shark_CE[5, D.L shr 15 and $1FE or 1] xor
5558
             Shark_CE[6, D.L shr  7 and $1FE or 1] xor
5559
             Shark_CE[7, D.L shl  1 and $1FE or 1];
5560
      D.L := T;
5561
    end;
5562
    D.L := D.L xor K.L;
5563
    D.R := D.R xor K.R;
5564
    Inc(K);
5565
    D.L := LongWord(Shark_SE[D.L shr 24 and $FF]) shl 24 xor
5566
           LongWord(Shark_SE[D.L shr 16 and $FF]) shl 16 xor
5567
           LongWord(Shark_SE[D.L shr  8 and $FF]) shl  8 xor
5568
           LongWord(Shark_SE[D.L        and $FF]);
5569
    D.R := LongWord(Shark_SE[D.R shr 24 and $FF]) shl 24 xor
5570
           LongWord(Shark_SE[D.R shr 16 and $FF]) shl 16 xor
5571
           LongWord(Shark_SE[D.R shr  8 and $FF]) shl  8 xor
5572
           LongWord(Shark_SE[D.R        and $FF]);
5573
    Result.L := D.L xor K.L;
5574
    Result.R := D.R xor K.R;
5575
  end;
5576
 
5577
var
5578
  T: array[0..6] of TLong64;
5579
  A: array[0..6] of TLong64;
5580
  K: array[0..15] of Byte;
5581
  I,J,R: Byte;
5582
  E,D: PLong64Array;
5583
  L: TLong64;
5584
begin
5585
  FillChar(K, SizeOf(K), 0);
5586
  Move(Key, K, Size);
5587
  InitLog;
5588
  E := FUser;
5589
  D := @E[7];
5590
  Move(Shark_CE[0], T, SizeOf(T));
5591
  T[6] := Transform(T[6]);
5592
  I := 0;
5593
  for R := 0 to 6 do
5594
  begin
5595
    Inc(I);
5596
    A[R].L := K[I and $F];
5597
    A[R].R := 0;
5598
    for J := 1 to 7 do
5599
    begin
5600
      Inc(I);
5601
      A[R].R := A[R].R shl 8 or A[R].L shr 24;
5602
      A[R].L := A[R].L shl 8 or K[I and $F];
5603
    end;
5604
  end;
5605
  L.L := 0;
5606
  L.R := 0;
5607
  L := Shark(L, @T);
5608
  E[0].L := A[0].L xor L.L;
5609
  E[0].R := A[0].R xor L.R;
5610
  for R := 1 to 6 do
5611
  begin
5612
    L := Shark(E[R - 1], @T);
5613
    E[R].L := A[R].L xor L.L;
5614
    E[R].R := A[R].R xor L.R;
5615
  end;
5616
  E[6] := Transform(E[6]);
5617
  D[0] := E[6];
5618
  D[6] := E[0];
5619
  for R := 1 to 5 do
5620
    D[R] := Transform(E[6-R]);
5621
  ProtectBuffer(Log, SizeOf(Log));
5622
  ProtectBuffer(ALog, SizeOf(ALog));
5623
  ProtectBuffer(T, SizeOf(T));
5624
  ProtectBuffer(A, SizeOf(A));
5625
  ProtectBuffer(K, SizeOf(K));
5626
end;
5627
 
5628
procedure TCipher_Shark.DoEncode(Source, Dest: Pointer; Size: Integer);
5629
var
5630
  I: Integer;
5631
  T,L,R: LongWord;
5632
  K: PLongArray;
5633
begin
5634
  Assert(Size = Context.BufferSize);
5635
 
5636
  K := FUser;
5637
  L := PLong64(Source).L;
5638
  R := PLong64(Source).R;
5639
  for I := 0 to 4 do
5640
  begin
5641
    L := L xor K[I * 2 +0];
5642
    R := R xor K[I * 2 +1];
5643
    T := Shark_CE[0, R shr 23 and $1FE] xor
5644
         Shark_CE[1, R shr 15 and $1FE] xor
5645
         Shark_CE[2, R shr  7 and $1FE] xor
5646
         Shark_CE[3, R shl  1 and $1FE] xor
5647
         Shark_CE[4, L shr 23 and $1FE] xor
5648
         Shark_CE[5, L shr 15 and $1FE] xor
5649
         Shark_CE[6, L shr  7 and $1FE] xor
5650
         Shark_CE[7, L shl  1 and $1FE];
5651
    R := Shark_CE[0, R shr 23 and $1FE or 1] xor
5652
         Shark_CE[1, R shr 15 and $1FE or 1] xor
5653
         Shark_CE[2, R shr  7 and $1FE or 1] xor
5654
         Shark_CE[3, R shl  1 and $1FE or 1] xor
5655
         Shark_CE[4, L shr 23 and $1FE or 1] xor
5656
         Shark_CE[5, L shr 15 and $1FE or 1] xor
5657
         Shark_CE[6, L shr  7 and $1FE or 1] xor
5658
         Shark_CE[7, L shl  1 and $1FE or 1];
5659
    L := T;
5660
  end;
5661
  L := L xor K[10];
5662
  R := R xor K[11];
5663
  L := LongWord(Shark_SE[L shr 24        ]) shl 24 xor
5664
       LongWord(Shark_SE[L shr 16 and $FF]) shl 16 xor
5665
       LongWord(Shark_SE[L shr  8 and $FF]) shl  8 xor
5666
       LongWord(Shark_SE[L        and $FF]);
5667
  R := LongWord(Shark_SE[R shr 24        ]) shl 24 xor
5668
       LongWord(Shark_SE[R shr 16 and $FF]) shl 16 xor
5669
       LongWord(Shark_SE[R shr  8 and $FF]) shl  8 xor
5670
       LongWord(Shark_SE[R        and $FF]);
5671
  PLong64(Dest).L := L xor K[12];
5672
  PLong64(Dest).R := R xor K[13];
5673
end;
5674
 
5675
procedure TCipher_Shark.DoDecode(Source, Dest: Pointer; Size: Integer);
5676
var
5677
  I: Integer;
5678
  T,R,L: LongWord;
5679
  K: PLongArray;
5680
begin
5681
  Assert(Size = Context.BufferSize);
5682
 
5683
  K := @PLongArray(FUser)[14];
5684
  L := PLong64(Source).L;
5685
  R := PLong64(Source).R;
5686
  for I := 0 to 4 do
5687
  begin
5688
    L := L xor K[I * 2 +0];
5689
    R := R xor K[I * 2 +1];
5690
    T := Shark_CD[0, R shr 23 and $1FE] xor
5691
         Shark_CD[1, R shr 15 and $1FE] xor
5692
         Shark_CD[2, R shr  7 and $1FE] xor
5693
         Shark_CD[3, R shl  1 and $1FE] xor
5694
         Shark_CD[4, L shr 23 and $1FE] xor
5695
         Shark_CD[5, L shr 15 and $1FE] xor
5696
         Shark_CD[6, L shr  7 and $1FE] xor
5697
         Shark_CD[7, L shl  1 and $1FE];
5698
    R := Shark_CD[0, R shr 23 and $1FE or 1] xor
5699
         Shark_CD[1, R shr 15 and $1FE or 1] xor
5700
         Shark_CD[2, R shr  7 and $1FE or 1] xor
5701
         Shark_CD[3, R shl  1 and $1FE or 1] xor
5702
         Shark_CD[4, L shr 23 and $1FE or 1] xor
5703
         Shark_CD[5, L shr 15 and $1FE or 1] xor
5704
         Shark_CD[6, L shr  7 and $1FE or 1] xor
5705
         Shark_CD[7, L shl  1 and $1FE or 1];
5706
    L := T;
5707
  end;
5708
  L := L xor K[10];
5709
  R := R xor K[11];
5710
  L := LongWord(Shark_SD[L shr 24        ]) shl 24 xor
5711
       LongWord(Shark_SD[L shr 16 and $FF]) shl 16 xor
5712
       LongWord(Shark_SD[L shr  8 and $FF]) shl  8 xor
5713
       LongWord(Shark_SD[L        and $FF]);
5714
  R := LongWord(Shark_SD[R shr 24        ]) shl 24 xor
5715
       LongWord(Shark_SD[R shr 16 and $FF]) shl 16 xor
5716
       LongWord(Shark_SD[R shr  8 and $FF]) shl  8 xor
5717
       LongWord(Shark_SD[R        and $FF]);
5718
  PLong64(Dest).L := L xor K[12];
5719
  PLong64(Dest).R := R xor K[13];
5720
end;
5721
 
5722
 
5723
// .TCipher_Skipjack
5724
type
5725
  PSkipjackTab = ^TSkipjackTab;
5726
  TSkipjackTab = array[0..255] of Byte;
5727
 
5728
class function TCipher_Skipjack.Context: TCipherContext;
5729
begin
5730
  Result.KeySize := 10;
5731
  Result.BlockSize := 8;
5732
  Result.BufferSize := 8;
5733
  Result.UserSize := $A00;
5734
  Result.UserSave := False;
5735
end;
5736
 
5737
procedure TCipher_Skipjack.DoInit(const Key; Size: Integer);
5738
var
5739
  K: array[0..9] of Byte;
5740
  D: PByte;
5741
  I,J: Integer;
5742
begin
5743
  FillChar(K, SizeOf(K), 0);
5744
  Move(Key, K, Size);
5745
  D := FUser;
5746
  for I := 0 to 9 do
5747
    for J := 0 to 255 do
5748
    begin
5749
      D^ := Skipjack_Data[J xor K[I]];
5750
      Inc(D);
5751
    end;
5752
  ProtectBuffer(K, SizeOf(K));
5753
end;
5754
 
5755
procedure TCipher_Skipjack.DoEncode(Source, Dest: Pointer; Size: Integer);
5756
var
5757
  Tab,Min: PSkipjackTab;
5758
  Max: PChar;
5759
  K,T,A,B,C,D: LongWord;
5760
begin
5761
  Assert(Size = Context.BufferSize);
5762
 
5763
  Min := FUser;
5764
  Max := PChar(Min) + 9 * 256;
5765
  Tab := Min;
5766
  A   := Swap(PWordArray(Source)[0]);
5767
  B   := Swap(PWordArray(Source)[1]);
5768
  C   := Swap(PWordArray(Source)[2]);
5769
  D   := Swap(PWordArray(Source)[3]);
5770
  K   := 0;
5771
  repeat
5772
    Inc(K);
5773
    T := A;
5774
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5775
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5776
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5777
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5778
    A := T xor D xor K;
5779
    D := C;
5780
    C := B;
5781
    B := T;
5782
  until K = 8;
5783
  repeat
5784
    Inc(K);
5785
    T := A;
5786
    A := D;
5787
    D := C;
5788
    C := T xor B xor K;
5789
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5790
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5791
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5792
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5793
    B := T;
5794
  until K = 16;
5795
  repeat
5796
    Inc(K);
5797
    T := A;
5798
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5799
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5800
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5801
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5802
    A := T xor D xor K;
5803
    D := C;
5804
    C := B;
5805
    B := T;
5806
  until K = 24;
5807
  repeat
5808
    Inc(K);
5809
    T := A;
5810
    A := D;
5811
    D := C;
5812
    C := T xor B xor K;
5813
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5814
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5815
    T := T xor Tab[T and $FF] shl 8;   Inc(Tab); if Tab > Max then Tab := Min;
5816
    T := T xor Tab[T shr 8];           Inc(Tab); if Tab > Max then Tab := Min;
5817
    B := T;
5818
  until K = 32;
5819
  PWordArray(Dest)[0] := Swap(A);
5820
  PWordArray(Dest)[1] := Swap(B);
5821
  PWordArray(Dest)[2] := Swap(C);
5822
  PWordArray(Dest)[3] := Swap(D);
5823
end;
5824
 
5825
procedure TCipher_Skipjack.DoDecode(Source, Dest: Pointer; Size: Integer);
5826
var
5827
  Tab,Max: PSkipjackTab;
5828
  Min: PChar;
5829
  K,T,A,B,C,D: LongWord;
5830
begin
5831
  Assert(Size = Context.BufferSize);
5832
 
5833
  Min := FUser;
5834
  Max := Pointer(Min + 9 * 256);
5835
  Tab := Pointer(Min + 7 * 256);
5836
  A   := Swap(PWordArray(Source)[0]); {holds as Integer, Compiler make faster Code}
5837
  B   := Swap(PWordArray(Source)[1]);
5838
  C   := Swap(PWordArray(Source)[2]);
5839
  D   := Swap(PWordArray(Source)[3]);
5840
  K   := 32;
5841
  repeat
5842
    T := B;
5843
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5844
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5845
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5846
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5847
    B := T xor C xor K;
5848
    C := D;
5849
    D := A;
5850
    A := T;
5851
    Dec(K);
5852
  until K = 24;
5853
  repeat
5854
    T := B;
5855
    B := C;
5856
    C := D;
5857
    D := T xor A xor K;
5858
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5859
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5860
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5861
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5862
    A := T;
5863
    Dec(K);
5864
  until K = 16;
5865
  repeat
5866
    T := B;
5867
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5868
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5869
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5870
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5871
    B := C xor T xor K;
5872
    C := D;
5873
    D := A;
5874
    A := T;
5875
    Dec(K);
5876
  until K = 8;
5877
  repeat
5878
    T := B;
5879
    B := C;
5880
    C := D;
5881
    D := T xor A xor K;
5882
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5883
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5884
    T := T xor Tab[T shr 8];           Dec(Tab); if Tab < Min then Tab := Max;
5885
    T := T xor Tab[T and $FF] shl 8;   Dec(Tab); if Tab < Min then Tab := Max;
5886
    A := T;
5887
    Dec(K);
5888
  until K = 0;
5889
  PWordArray(Dest)[0] := Swap(A);
5890
  PWordArray(Dest)[1] := Swap(B);
5891
  PWordArray(Dest)[2] := Swap(C);
5892
  PWordArray(Dest)[3] := Swap(D);
5893
end;
5894
 
5895
 
5896
// .TCipher_TEA
5897
const
5898
  TEA_Delta = $9E3779B9;
5899
 
5900
class function TCipher_TEA.Context: TCipherContext;
5901
begin
5902
  Result.KeySize := 16;
5903
  Result.BlockSize := 8;
5904
  Result.BufferSize := 8;
5905
  Result.UserSize := 32;
5906
  Result.UserSave := False;
5907
end;
5908
 
5909
procedure TCipher_TEA.SetRounds(Value: Integer);
5910
begin
5911
  if not (FState in [csNew, csInitialized, csDone]) then Done;
5912
  if Value < 16 then Value := 16 else
5913
    if Value > 32 then Value := 32;
5914
  FRounds := Value;
5915
end;
5916
 
5917
procedure TCipher_TEA.DoInit(const Key; Size: Integer);
5918
begin
5919
  Move(Key, FUser^, Size);
5920
  SetRounds(FRounds);
5921
end;
5922
 
5923
procedure TCipher_TEA.DoEncode(Source, Dest: Pointer; Size: Integer);
5924
var
5925
  I: Integer;
5926
  Sum,X,Y,A,B,C,D: LongWord;
5927
begin
5928
  Assert(Size = Context.BufferSize);
5929
 
5930
  Sum := 0;
5931
  A := PLongArray(FUser)[0];
5932
  B := PLongArray(FUser)[1];
5933
  C := PLongArray(FUser)[2];
5934
  D := PLongArray(FUser)[3];
5935
  X := PLongArray(Source)[0];
5936
  Y := PLongArray(Source)[1];
5937
  for I := 0 to FRounds -1 do
5938
  begin
5939
    Inc(Sum, TEA_Delta);
5940
    Inc(X, (((Y shl 4 + A) xor Y) + Sum) xor (Y shr 5 + B));
5941
    Inc(Y, (((X shl 4 + C) xor X) + Sum) xor (X shr 5 + D));
5942
  end;
5943
  PLongArray(Dest)[0] := X;
5944
  PLongArray(Dest)[1] := Y;
5945
end;
5946
 
5947
procedure TCipher_TEA.DoDecode(Source, Dest: Pointer; Size: Integer);
5948
var
5949
  I: Integer;
5950
  Sum,X,Y,A,B,C,D: LongWord;
5951
begin
5952
  Assert(Size = Context.BufferSize);
5953
 
5954
  Sum := TEA_Delta * LongWord(FRounds);
5955
  A := PLongArray(FUser)[0];
5956
  B := PLongArray(FUser)[1];
5957
  C := PLongArray(FUser)[2];
5958
  D := PLongArray(FUser)[3];
5959
  X := PLongArray(Source)[0];
5960
  Y := PLongArray(Source)[1];
5961
  for I := 0 to FRounds -1 do
5962
  begin
5963
    Dec(Y, (X shl 4 + C) xor X + Sum xor (X shr 5 + D));
5964
    Dec(X, (Y shl 4 + A) xor Y + Sum xor (Y shr 5 + B));
5965
    Dec(Sum, TEA_Delta);
5966
  end;
5967
  PLongArray(Dest)[0] := X;
5968
  PLongArray(Dest)[1] := Y;
5969
end;
5970
 
5971
// .TCipher_TEAN
5972
procedure TCipher_TEAN.DoEncode(Source, Dest: Pointer; Size: Integer);
5973
var
5974
  I,Sum,X,Y: LongWord;
5975
  K: PLongArray;
5976
begin
5977
  Assert(Size = Context.BufferSize);
5978
 
5979
  Sum := 0;
5980
  X := PLongArray(Source)[0];
5981
  Y := PLongArray(Source)[1];
5982
  K := FUser;
5983
  for I := 0 to FRounds -1 do
5984
  begin
5985
    Inc(X, (Y shl 4 xor Y shr 5) + (Y xor Sum) + K[Sum and 3]);
5986
    Inc(Sum, TEA_Delta);
5987
    Inc(Y, (X shl 4 xor X shr 5) + (X xor Sum) + K[Sum shr 11 and 3]);
5988
  end;
5989
  PLongArray(Dest)[0] := X;
5990
  PLongArray(Dest)[1] := Y;
5991
end;
5992
 
5993
procedure TCipher_TEAN.DoDecode(Source, Dest: Pointer; Size: Integer);
5994
var
5995
  I: Integer;
5996
  Sum,X,Y: LongWord;
5997
  K: PLongArray;
5998
begin
5999
  Assert(Size = Context.BufferSize);
6000
 
6001
  Sum := TEA_Delta * LongWord(FRounds);
6002
  X := PLongArray(Source)[0];
6003
  Y := PLongArray(Source)[1];
6004
  K := FUser;
6005
  for I := 0 to FRounds -1 do
6006
  begin
6007
    Dec(Y, (X shl 4 xor X shr 5) + (X xor Sum) + K[Sum shr 11 and 3]);
6008
    Dec(Sum, TEA_Delta);
6009
    Dec(X, (Y shl 4 xor Y shr 5) + (Y xor Sum) + K[Sum and 3]);
6010
  end;
6011
  PLongArray(Dest)[0] := X;
6012
  PLongArray(Dest)[1] := Y;
6013
end;
6014
 
6015
 
6016
end.
6017