2
This file is part of the Free Component Library (FCL)
3
Copyright (c) 1999-2000 by Michael Van Canneyt and Florian Klaempfl
5
See the file COPYING.FPC, included in this distribution,
6
for details about the copyright.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
**********************************************************************}
21
IDEA encryption routines for pascal
24
IDEA encryption routines for pascal, ported from PGP 2.3
25
Copyright (C) for this port 1998 Ingo Korb
26
Copyright (C) for the stream support 1999 Michael Van Canneyt
28
This library is free software; you can redistribute it and/or
29
modify it under the terms of the GNU Library General Public
30
License as published by the Free Software Foundation; either
31
version 2 of the License, or (at your option) any later version.
33
This library is distributed in the hope that it will be useful,
34
but WITHOUT ANY WARRANTY; without even the implied warranty of
35
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36
Library General Public License for more details.
38
You should have received a copy of the GNU Library General Public
39
License along with this library; if not, write to the Free
40
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
45
{ Not nice but fast... }
49
Uses Sysutils,Classes;
55
KEYLEN = (6*ROUNDS+4);
58
TIDEAKey = ARRAY[0..keylen-1] OF Word;
59
TIdeaCryptKey = ARRAY[0..7] OF Word;
60
TIdeaCryptData = ARRAY[0..3] OF Word;
62
{ For backward compatibility }
64
IdeaCryptKey = TIdeaCryptKey;
65
IdeaCryptData = TIdeaCryptData;
67
PROCEDURE EnKeyIdea(UserKey: TIdeacryptkey; VAR z: TIDEAKey);
68
PROCEDURE DeKeyIdea(z: TIDEAKey; VAR dk: TIDEAKey);
69
PROCEDURE CipherIdea(Input: TIDEACryptData; VAR outdata: TIDEACryptData; z: TIDEAKey);
72
EIDEAError = Class(EStreamError);
74
TIDEAStream = Class(TOwnerStream)
77
FData : TIDEACryptData;
81
Constructor Create(AKey : TIDEAKey; Dest: TStream);
82
Property Key : TIDEAKey Read FKey;
85
TIDEAEncryptStream = Class(TIDEAStream)
87
Destructor Destroy; override;
88
function Read(var Buffer; Count: Longint): Longint; override;
89
function Write(const Buffer; Count: Longint): Longint; override;
90
function Seek(Offset: Longint; Origin: Word): Longint; override;
94
TIDEADeCryptStream = Class(TIDEAStream)
96
function Read(var Buffer; Count: Longint): Longint; override;
97
function Write(const Buffer; Count: Longint): Longint; override;
98
function Seek(Offset: Longint; Origin: Word): Longint; override;
104
SNoSeekAllowed = 'Seek not allowed on encryption streams';
105
SNoReadAllowed = 'Reading from encryption stream not allowed';
106
SNoWriteAllowed = 'Writing to decryption stream not allowed';
108
PROCEDURE mul(VAR a:Word; b: Word);
111
IF (a <> 0) THEN BEGIN
112
IF (b <> 0) THEN BEGIN
116
IF (b < a) THEN a := b - a + 1
122
FUNCTION inv(x: word): Word;
151
PROCEDURE EnKeyIdea(userkey: ideacryptkey; VAR z: ideakey);
154
FOR j := 0 TO 7 DO z[j] := userkey[j];
157
FOR j := 8 TO keylen-1 DO BEGIN
159
z[zi+i+7] := (z[zi+(i AND 7)] SHL 9) OR (z[zi+((i+1) AND 7)] SHR 7);
160
zi := zi + (i AND 8);
163
FOR i := 0 TO 7 DO userkey[i] := 0;
166
PROCEDURE DeKeyIdea(z: IDEAKey; VAR dk: ideakey);
175
FOR j := 0 TO keylen - 1 DO p[j] := 0;
176
t1 := inv(z[iz]); Inc(iz);
177
t2 := not(z[iz])+1; Inc(iz);
178
t3 := not(z[iz])+1; Inc(iz);
179
Dec(ip); p[ip] := inv(z[iz]); Inc(iz);
180
Dec(ip); p[ip] := t3;
181
Dec(ip); p[ip] := t2;
182
Dec(ip); p[ip] := t1;
183
FOR j := 1 TO rounds-1 DO BEGIN
184
t1 := z[iz]; Inc(iz);
185
Dec(ip); p[ip] := z[iz]; Inc(iz);
186
Dec(ip); p[ip] := t1;
187
t1 := inv(z[iz]); Inc(iz);
188
t2 := Not(z[iz])+1; Inc(iz);
189
t3 := Not(z[iz])+1; Inc(iz);
190
Dec(ip); p[ip] := inv(z[iz]); Inc(iz);
191
Dec(ip); p[ip] := t2;
192
Dec(ip); p[ip] := t3;
193
Dec(ip); p[ip] := t1;
195
t1 := z[iz]; Inc(iz);
196
Dec(ip); p[ip] := z[iz]; Inc(iz);
197
Dec(ip); p[ip] := t1;
198
t1 := inv(z[iz]); Inc(iz);
199
t2 := Not(z[iz])+1; Inc(iz);
200
t3 := Not(z[iz])+1; Inc(iz);
201
Dec(ip); p[ip] := inv(z[iz]);
202
Dec(ip); p[ip] := t3;
203
Dec(ip); p[ip] := t2;
204
Dec(ip); p[ip] := t1;
205
FOR j := 0 TO KeyLen-1 DO BEGIN
209
FOR j := 0 TO 51 DO z[j] := 0;
212
PROCEDURE CipherIdea(input: ideacryptdata; VAR outdata: ideacryptdata; z:IDEAkey);
213
VAR x1, x2, x3, x4, t1, t2: Word;
222
FOR r := 1 TO ROUNDS DO BEGIN
223
mul(x1,z[zi]); Inc(zi);
224
x2 := x2 + z[zi]; Inc(zi);
225
x3 := x3 + z[zi]; Inc(zi);
226
mul(x4, z[zi]); Inc(zi);
228
mul(t2, z[zi]); Inc(zi);
229
t1 := t2 + (x2 XOR x4);
230
mul(t1, z[zi]); Inc(zi);
238
mul(x1, z[zi]); Inc(zi);
240
outdata[1] := x3 + z[zi]; Inc(zi);
241
outdata[2] := x2 + z[zi]; Inc(zi);
244
FOR r := 0 TO 3 DO input[r] := 0;
245
FOR r := 0 TO 51 DO z[r] := 0;
248
{ ---------------------------------------------------------------------
250
---------------------------------------------------------------------}
253
Constructor TIDEAStream.Create(AKey : ideakey; Dest: TStream);
256
inherited Create(Dest);
262
{ ---------------------------------------------------------------------
264
---------------------------------------------------------------------}
266
Destructor TIDEAEncryptStream.Destroy;
274
Procedure TIDEAEncryptStream.Flush;
277
OutData : IdeaCryptData;
283
FillChar(PChar(@FData)[FBufPos],SizeOf(FData)-FBufPos,#0);
284
CipherIdea(Fdata,OutData,FKey);
285
Source.Write(OutData,SizeOf(OutData));
286
// fixed: Manual flush and then free will now work
291
function TIDEAEncryptStream.Read(var Buffer; Count: Longint): Longint;
294
Raise EIDEAError.Create(SNoReadAllowed);
297
function TIDEAEncryptStream.Write(const Buffer; Count: Longint): Longint;
301
OutData : IDEAcryptdata;
308
If Mvsize>SizeOf(Fdata)-FBufPos then
309
mvsize:=SizeOf(FData)-FBufPos;
310
Move(PChar(@Buffer)[Result],PChar(@FData)[FBufPos],MVSize);
311
If FBufPos+mvSize=Sizeof(FData) then
314
CipherIdea(Fdata,OutData,FKey);
315
// this will raise an exception if needed.
316
Source.Writebuffer(OutData,SizeOf(OutData));
328
function TIDEAEncryptStream.Seek(Offset: Longint; Origin: Word): Longint;
331
if (Offset = 0) and (Origin = soFromCurrent) then
334
Raise EIDEAError.Create(SNoSeekAllowed);
338
{ ---------------------------------------------------------------------
340
---------------------------------------------------------------------}
343
function TIDEADeCryptStream.Read(var Buffer; Count: Longint): Longint;
347
InData : IDEAcryptdata;
353
// Empty existing buffer.
359
Move(PChar(@FData)[0],PChar(@Buffer)[Result],MVSize);
360
If ((Sizeof(FData)-MvSize)>0) then
361
Move(PChar(@FData)[mvSize],PChar(@FData)[0],Sizeof(FData)-MvSize);
364
FBufPos:=FBufPos-MvSize;
366
// Fill buffer again if needed.
369
mvsize:=Source.Read(InData,SizeOf(InData));
372
If MvSize<SizeOf(InData) Then
374
FillChar(PChar(@InData)[mvsize],SizeOf(InData)-mvsize,#0);
375
CipherIdea(InData,FData,FKey);
376
FBufPos:=SizeOf(FData);
379
Count:=0; // No more data available from stream; st
385
function TIDEADeCryptStream.Write(const Buffer; Count: Longint): Longint;
387
Raise EIDEAError.Create(SNoWriteAllowed);
390
function TIDEADeCryptStream.Seek(Offset: Longint; Origin: Word): Longint;
392
Var Buffer : Array[0..1023] of byte;
396
// Fake seek if possible by reading and discarding bytes.
397
If ((Offset>=0) and (Origin = soFromCurrent)) or
398
((Offset>FPos) and (Origin = soFromBeginning)) then
400
For I:=1 to (Offset div SizeOf(Buffer)) do
401
ReadBuffer(Buffer,SizeOf(Buffer));
402
ReadBuffer(Buffer,Offset mod SizeOf(Buffer));
406
Raise EIDEAError.Create(SNoSeekAllowed);