-- Copyright (C) 1984 by Xerox Corporation. All rights reserved. -- DESDLion.mesa, HGM, 12-Jan-84 22:48:38 DIRECTORY Environment USING [Byte], Inline USING [DBITXOR], Mopcodes USING [zESC], DESFace USING [Block, Blocks, Direction, IV, Key, Mode, parityTable]; DESDLion: MONITOR IMPORTS Inline EXPORTS DESFace SHARES DESFace = BEGIN BadParity: ERROR = CODE; NotImplemented: ERROR = CODE; Register: TYPE = MACHINE DEPENDENT { data(0), command(2), mode(6)}; DESCtl: PROCEDURE [Register] = MACHINE CODE BEGIN Mopcodes.zESC, 0C0H; END; DESMP: PROCEDURE [Environment.Byte] = MACHINE CODE BEGIN Mopcodes.zESC, 0C1H; END; DESSP: PROCEDURE RETURNS [Environment.Byte] = MACHINE CODE BEGIN Mopcodes.zESC, 0C2H; END; DESWriteBlock: PROCEDURE [DESFace.Block] = MACHINE CODE BEGIN Mopcodes.zESC, 0C3H; END; DESReadBlock: PROCEDURE RETURNS [DESFace.Block] = MACHINE CODE BEGIN Mopcodes.zESC, 0C4H; END; DESWritePair: PROCEDURE [LONG CARDINAL] = MACHINE CODE BEGIN Mopcodes.zESC, 0C5H; END; DESReadPair: PROCEDURE RETURNS [LONG CARDINAL] = MACHINE CODE BEGIN Mopcodes.zESC, 0C6H; END; Delay6: PROCEDURE = BEGIN -- Wait (at least) 6 clicks END; ResetTheChip: PROCEDURE = BEGIN DESCtl[command]; DESMP[00H]; Delay6[]; [] ¬ DESSP[]; -- Discard leftover byte, if any (if not causes error, but nobody looks) END; LoadIV: PROCEDURE [ivP: LONG POINTER TO DESFace.IV, direction: DESFace.Direction] = BEGIN iv: LONG POINTER TO DESFace.Block = LOOPHOLE[ivP]; DESCtl[command]; DESMP[IF direction = encrypt THEN 85H ELSE 84H]; Delay6[]; DESCtl[data]; DESWriteBlock[iv­]; END; LoadKey: PROCEDURE [keyP: LONG POINTER TO DESFace.Key, direction: DESFace.Direction] = BEGIN key: LONG POINTER TO DESFace.Block = LOOPHOLE[keyP]; FOR i: CARDINAL IN [0..7] DO IF keyP[i].p # DESFace.parityTable[keyP[i].b] THEN ERROR BadParity; ENDLOOP; DESCtl[command]; DESMP[IF direction = encrypt THEN 11H ELSE 12H]; Delay6[]; DESCtl[data]; DESWriteBlock[key­]; END; SetMode: PROCEDURE [mode: DESFace.Mode, direction: DESFace.Direction] = BEGIN byte: Environment.Byte; SELECT direction FROM encrypt => byte ¬ 14H; decrypt => byte ¬ 00H; ENDCASE => ERROR; SELECT mode FROM ecb => NULL; cbc => byte ¬ byte + 2; cbcCheck => byte ¬ byte + 2; ENDCASE => ERROR; DESCtl[mode]; DESMP[byte]; Delay6[]; END; CrunchBytes: PROCEDURE [from, to: DESFace.Blocks, nBlks: CARDINAL] = BEGIN Bytes: TYPE = LONG POINTER TO PACKED ARRAY [0..8) OF Environment.Byte; DESCtl[command]; DESMP[0C0H]; -- Start DESCtl[data]; FOR i: CARDINAL IN [0..nBlks) DO f: Bytes = LOOPHOLE[@from[i]]; t: Bytes = LOOPHOLE[@to[i]]; FOR i: CARDINAL IN [0..8) DO DESMP[f[i]]; ENDLOOP; Delay6[]; Delay6[]; Delay6[]; FOR i: CARDINAL IN [0..8) DO t[i] ¬ DESSP[]; ENDLOOP; ENDLOOP; END; CrunchSingleBlocks: PROCEDURE [from, to: DESFace.Blocks, nBlks: CARDINAL] = BEGIN f: LONG POINTER TO DESFace.Block ¬ @from[0]; t: LONG POINTER TO DESFace.Block ¬ @to[0]; DESCtl[command]; DESMP[0C0H]; -- Start Delay6[]; DESCtl[data]; FOR i: CARDINAL IN [0..nBlks) DO DESWriteBlock[f­]; Delay6[]; Delay6[]; Delay6[]; Delay6[]; t­ ¬ DESReadBlock[]; f ¬ f + SIZE[DESFace.Block]; t ¬ t + SIZE[DESFace.Block]; ENDLOOP; END; CrunchBlocks: PROCEDURE [from, to: DESFace.Blocks, nBlks: CARDINAL] = BEGIN f: LONG POINTER TO DESFace.Block ¬ @from[0]; t: LONG POINTER TO DESFace.Block ¬ @to[0]; DESCtl[command]; DESMP[0C0H]; -- Start Delay6[]; DESCtl[data]; IF nBlks = 0 THEN RETURN; DESWriteBlock[f­]; Delay6[]; IF nBlks = 1 THEN BEGIN Delay6[]; Delay6[]; END; FOR i: CARDINAL IN [0..nBlks-1) DO f ¬ f + SIZE[DESFace.Block]; DESWriteBlock[f­]; t­ ¬ DESReadBlock[]; t ¬ t + SIZE[DESFace.Block]; ENDLOOP; t­ ¬ DESReadBlock[]; END; Crunch: PROCEDURE [from, to: DESFace.Blocks, nBlks: CARDINAL] = BEGIN TwoPairs: TYPE = RECORD [a, b: LONG CARDINAL]; f: LONG POINTER TO ARRAY [0..9) OF TwoPairs ¬ LOOPHOLE[@from[0]]; t: LONG POINTER TO ARRAY [0..8) OF TwoPairs ¬ LOOPHOLE[@to[0]]; DESCtl[command]; DESMP[0C0H]; -- Start Delay6[]; DESCtl[data]; IF nBlks = 0 THEN RETURN; DESWritePair[f[0].a]; DESWritePair[f[0].b]; f ¬ f + SIZE[DESFace.Block]; nBlks ¬ nBlks - 1; IF nBlks = 0 THEN BEGIN Delay6[]; Delay6[]; END; -- This is the GO FASTER feature -- 4 blocks is as far as RLDILP+WLDILP can reach UNTIL nBlks <= 4 DO DESWritePair[f[0].a]; DESWritePair[f[0].b]; t[0].a ¬ DESReadPair[]; t[0].b ¬ DESReadPair[]; DESWritePair[f[1].a]; DESWritePair[f[1].b]; t[1].a ¬ DESReadPair[]; t[1].b ¬ DESReadPair[]; DESWritePair[f[2].a]; DESWritePair[f[2].b]; t[2].a ¬ DESReadPair[]; t[2].b ¬ DESReadPair[]; DESWritePair[f[3].a]; DESWritePair[f[3].b]; t[3].a ¬ DESReadPair[]; t[3].b ¬ DESReadPair[]; f ¬ f + SIZE[DESFace.Block, 4]; t ¬ t + SIZE[DESFace.Block, 4]; nBlks ¬ nBlks - 4; ENDLOOP; UNTIL nBlks = 0 DO DESWritePair[f[0].a]; DESWritePair[f[0].b]; t[0].a ¬ DESReadPair[]; t[0].b ¬ DESReadPair[]; f ¬ f + SIZE[DESFace.Block]; t ¬ t + SIZE[DESFace.Block]; nBlks ¬ nBlks - 1; ENDLOOP; t[0].a ¬ DESReadPair[]; t[0].b ¬ DESReadPair[]; END; CryptData: PUBLIC ENTRY PROCEDURE [ keyP: POINTER TO DESFace.Key, nBlks: CARDINAL, from, to: DESFace.Blocks, direction: DESFace.Direction, mode: DESFace.Mode, seedP: LONG POINTER TO DESFace.IV ¬ NIL] = BEGIN ENABLE UNWIND => NULL; 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; ResetTheChip[]; SetMode[mode, direction]; LoadKey[keyP, direction]; IF mode = cbc OR mode = cbcCheck THEN LoadIV[seedP, direction]; Crunch[from, to, nBlks]; 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; Words4: TYPE = MACHINE DEPENDENT RECORD [a, b: LONG CARDINAL]; 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.a ¬ Inline.DBITXOR[aLP.a, bLP.a]; outP.b ¬ Inline.DBITXOR[aLP.b, bLP.b]; END; END.