-- Dummy implementation of DES -- DESDummy.mesa -- Andrew Birrell DIRECTORY DESFace, Inline USING[ BITXOR ], System USING[ GetClockPulses ]; DESDummy: MONITOR IMPORTS Inline, System EXPORTS DESFace SHARES DESFace = BEGIN OPEN DESFace; Words4: TYPE = MACHINE DEPENDENT RECORD[w1, w2, w3, w4: WORD]; XOR64: PROCEDURE[a, b, out: LONG POINTER] = INLINE BEGIN OPEN aLP: LOOPHOLE[a, LONG POINTER TO Words4], bLP: LOOPHOLE[b, LONG POINTER TO Words4], outP: LOOPHOLE[out, LONG POINTER TO Words4]; outP.w1 ← Inline.BITXOR[aLP.w1, bLP.w1]; outP.w2 ← Inline.BITXOR[aLP.w2, bLP.w2]; outP.w3 ← Inline.BITXOR[aLP.w3, bLP.w3]; outP.w4 ← Inline.BITXOR[aLP.w4, bLP.w4]; END; Words2: TYPE = MACHINE DEPENDENT RECORD[w1, w2: WORD]; XOR32: PROCEDURE[a, b: LONG UNSPECIFIED, out: POINTER] = INLINE BEGIN OPEN aP: LOOPHOLE[a, Words2], bP: LOOPHOLE[b, Words2], outP: LOOPHOLE[out, POINTER TO Words2]; outP.w1 ← Inline.BITXOR[aP.w1, bP.w1]; outP.w2 ← Inline.BITXOR[aP.w2, bP.w2]; END; cachedKey: Key; noKeyCached: BOOLEAN ← TRUE; BadParity: ERROR = CODE; InternalizeKey: ENTRY PROC [keyP: POINTER TO Key] = BEGIN IF noKeyCached OR cachedKey # keyP↑ THEN BEGIN FOR i: CARDINAL IN [0..7] DO IF keyP[i].p # parityTable[keyP[i].b] THEN RETURN WITH ERROR BadParity; ENDLOOP; cachedKey ← keyP↑; noKeyCached ← FALSE; END; END; --InternalizeKey-- NotImplemented: ERROR = CODE; 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-- randomSeed: Block ← [1,2,3,4]; 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↑ + System.GetClockPulses[]; XOR32[pulse2↑, System.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-- GetRandomKey: PUBLIC PROCEDURE RETURNS [k: Key] = BEGIN k ← LOOPHOLE[GetRandomIV[]]; CorrectParity[@k]; END; --GetRandomKey-- MakeKey: PUBLIC PROCEDURE [source: LONG STRING] RETURNS [key: Key] = BEGIN -- User interface routine to construct a 64 bit key from an ASCII string. -- "key" is an array that holds the 64 bit key. -- Note: every eighth bit of "key" is an odd parity bit for the preceeding seven bits. 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 ← Inline.BITXOR[LOOPHOLE[c, [0 .. 127]], key[j].b]; ENDLOOP; CorrectParity[@key]; END; -- MakeKey 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] = BEGIN FOR i: CARDINAL IN [0 .. 7] DO keyP[i].p ← parityTable[keyP[i].b]; ENDLOOP; END; [] ← GetRandomKey[]; END. --DES--