CryptData:
PUBLIC
PROCEDURE [keyP:
POINTER
TO Key, nBlks:
CARDINAL,
from, to: Blocks, direction: Direction, mode: Mode,
seedP: LONG POINTER TO IV ← NIL] =
BEGIN
newSeed: IV;
IF mode = checksum THEN ERROR NotImplemented;
IF mode = cbcCheck AND direction = encrypt AND nBlks > 0
THEN
BEGIN
FOR blk: CARDINAL IN [0..nBlks-1)
DO XOR64[@from[nBlks-1], @from[blk], @from[nBlks-1]] ENDLOOP;
END;
InternalizeKey[keyP];
FOR blk:
CARDINAL
IN [0 .. nBlks)
DO
IF mode#ecb
THEN
IF direction=encrypt
THEN XOR64[@from[blk], seedP, @from[blk]]
ELSE newSeed ← from[blk];
XOR64[keyP, @from[blk], @to[blk]];
IF mode#ecb
THEN
IF direction=encrypt
THEN seedP ← @to[blk]
ELSE {XOR64[@to[blk], seedP, @to[blk]]; seedP^ ← newSeed};
ENDLOOP;
IF mode = cbcCheck AND direction = decrypt AND nBlks > 0
THEN
BEGIN
FOR blk: CARDINAL IN [0..nBlks-1)
DO XOR64[@to[nBlks-1], @to[blk], @to[nBlks-1]] ENDLOOP;
END
END; --CryptData--
GetRandomIV:
PUBLIC
PROCEDURE
RETURNS [iv:
IV] =
BEGIN
-- Ideally, this should use a true random number generator --
prevSeed: Block ← randomSeed;
pulse1: POINTER TO LONG CARDINAL = LOOPHOLE[@randomSeed[0]];
pulse2: POINTER TO LONG CARDINAL = LOOPHOLE[@randomSeed[2]];
seedKey: POINTER TO Key = LOOPHOLE[@randomSeed];
pulse1^ ← pulse1^ + BasicTime.GetClockPulses[];
XOR32[pulse2^, BasicTime.GetClockPulses[], pulse2];
CorrectParity[seedKey];
CryptData[keyP: seedKey, nBlks: 1,
from: LOOPHOLE[LONG[@prevSeed], Blocks],
to: LOOPHOLE[LONG[@iv], Blocks],
direction: encrypt, mode: ecb, seedP: NIL];
END; --GetRandomIV--
parityTable:
PACKED
ARRAY [0..127]
OF [0..1] ← [
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
];