<> <> <> <> <> <<>> DIRECTORY BasicTime USING [ GetClockPulses ], DESFace, Basics USING [ BITXOR ]; DESDummy: MONITOR IMPORTS Basics, BasicTime EXPORTS DESFace SHARES DESFace = { OPEN DESFace; Words4: TYPE = MACHINE DEPENDENT RECORD[w1, w2, w3, w4: WORD]; XOR64: PROC[a, b, out: LONG POINTER] = INLINE { OPEN aLP: LOOPHOLE[a, LONG POINTER TO Words4], bLP: LOOPHOLE[b, LONG POINTER TO Words4], outP: LOOPHOLE[out, LONG POINTER TO Words4]; outP.w1 _ Basics.BITXOR[aLP.w1, bLP.w1]; outP.w2 _ Basics.BITXOR[aLP.w2, bLP.w2]; outP.w3 _ Basics.BITXOR[aLP.w3, bLP.w3]; outP.w4 _ Basics.BITXOR[aLP.w4, bLP.w4]; }; Words2: TYPE = MACHINE DEPENDENT RECORD[w1, w2: WORD]; XOR32: PROC[a, b: LONG UNSPECIFIED, out: POINTER] = INLINE { OPEN aP: LOOPHOLE[a, Words2], bP: LOOPHOLE[b, Words2], outP: LOOPHOLE[out, POINTER TO Words2]; outP.w1 _ Basics.BITXOR[aP.w1, bP.w1]; outP.w2 _ Basics.BITXOR[aP.w2, bP.w2]; }; cachedKey: Key; noKeyCached: BOOLEAN _ TRUE; BadKey: PUBLIC ERROR = CODE; checkingForParity: BOOL _ TRUE; <> InternalizeKey: ENTRY PROC [keyP: POINTER TO Key] = { IF noKeyCached OR cachedKey # keyP^ THEN { IF checkingForParity THEN FOR i: CARDINAL IN [0..7] DO IF keyP[i].p # parityTable[keyP[i].b] THEN RETURN WITH ERROR BadKey; ENDLOOP; cachedKey _ keyP^; noKeyCached _ FALSE; }; }; NotImplemented: ERROR = CODE; CryptData: PUBLIC PROC [keyP: POINTER TO Key, nBlks: CARDINAL, from, to: Blocks, direction: Direction, mode: Mode, seedP: LONG POINTER TO IV _ NIL] = { newSeed: IV; IF mode = checksum THEN ERROR NotImplemented; IF mode = cbcCheck AND direction = encrypt AND nBlks > 0 THEN FOR blk: CARDINAL IN [0..nBlks-1) DO XOR64[@from[nBlks-1], @from[blk], @from[nBlks-1]]; ENDLOOP; 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 { FOR blk: CARDINAL IN [0..nBlks-1) DO XOR64[@to[nBlks-1], @to[blk], @to[nBlks-1]]; ENDLOOP; } }; randomSeed: Block _ [1,2,3,4]; GetRandomIV: PUBLIC PROC RETURNS [iv: IV] = { <> 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]; }; GetRandomKey: PUBLIC PROC RETURNS [k: Key] = { k _ LOOPHOLE[GetRandomIV[]]; CorrectParity[@k]; }; MakeKey: PUBLIC PROC [source: LONG STRING] RETURNS [key: Key] = { <> <<"key" is an array that holds the 64 bit key.>> <> key _ nullKey; FOR i: CARDINAL IN [0..source.length) DO j: CARDINAL = i MOD 8; c: CHARACTER = IF source[i] IN ['A..'Z] THEN 'a + (source[i]-'A) ELSE source[i]; key[j].b _ Basics.BITXOR[LOOPHOLE[c, [0 .. 127]], key[j].b]; ENDLOOP; CorrectParity[@key]; }; 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 ]; CorrectParity: PUBLIC PROC[keyP: LONG POINTER TO Key] = { FOR i: CARDINAL IN [0 .. 7] DO keyP[i].p _ parityTable[keyP[i].b]; ENDLOOP; }; [] _ GetRandomKey[]; }. <<>>