-- Copyright (C) 1983 by Xerox Corporation. All rights reserved. -- DESTesterOthello.mesa, HGM, 22-Dec-83 0:39:00 DIRECTORY Format USING [], Process USING [Detach, GetPriority, Priority, SetPriority, Yield], ProcessPriorities USING [priorityClientLow], Put USING [Char, CR, Line, Text], String USING [AppendLongDecimal, AppendNumber], System USING [GetClockPulses, Pulses, PulsesToMicroseconds], Window USING [Handle], OthelloDefs USING [ CommandProcessor, IndexTooLarge, MyNameIs, ReadChar, RegisterCommandProc], DESFace USING [ Block, Blocks, CBCDecrypt, CBCEncrypt, DecryptBlock, ECBDecrypt, ECBEncrypt, EncryptBlock, GetRandomIV, GetRandomKey, IV, Key]; DESTesterOthello: PROGRAM IMPORTS Process, Put, String, System, OthelloDefs, DESFace = BEGIN log: Window.Handle ← NIL; password: LONG STRING ← NIL; key: DESFace.Key ← DESFace.GetRandomKey[]; seed: DESFace.IV ← [123, 456, 789, 43321]; -- Test data that exercises every S-Box Entry -- Source: Federal Register, XXX -- Values in Hex -- (Key) (Data) (Cipher) -- 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B -- 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 -- 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A -- 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A -- 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 -- 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B -- 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 -- 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A -- 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F -- 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 -- 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 -- 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A -- 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 -- 025816164629B007 480D39006EE762F2 A1F9915541020B56 -- 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 -- 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC -- 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A -- 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 -- 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 -- 0101010101010101 AAAAAAAAAAAAAAAA 3AE716954DC04E25 -- 0101010101010101 0000000000000000 8CA64DE9C1B123A7 keySequence: ARRAY [0..21) OF DESFace.Block ← [ DESFace.Block[76241B, 10105B, 45032B, 67127B], DESFace.Block[461B, 154541B, 116701B, 33556B], DESFace.Block[3641B, 11476B, 45013B, 23206B], DESFace.Block[34111B, 63514B, 23002B, 30636B], DESFace.Block[2271B, 12672B, 41776B, 132666B], DESFace.Block[423B, 134560B, 176464B, 171316B], DESFace.Block[560B, 170565B, 43217B, 132746B], DESFace.Block[41451B, 77655B, 34343B, 71776B], DESFace.Block[3647B, 11560B, 42732B, 25026B], DESFace.Block[2150B, 110404B, 141375B, 35457B], DESFace.Block[33720B, 65665B, 13313B, 72506B], DESFace.Block[17410B, 23015B, 15302B, 43136B], DESFace.Block[54100B, 21544B, 15272B, 60566B], DESFace.Block[1130B, 13026B, 43051B, 130007B], DESFace.Block[44571B, 37274B, 74663B, 22617B], DESFace.Block[47660B, 57025B, 12653B, 71647B], DESFace.Block[44751B, 56555B, 46242B, 24677B], DESFace.Block[603B, 10334B, 40233B, 23326B], DESFace.Block[16130B, 77434B, 11622B, 47757B], DESFace.Block[401B, 401B, 401B, 401B], DESFace.Block[401B, 401B, 401B, 401B] ]; dataSequence: ARRAY [0..21) OF DESFace.Block ← [ DESFace.Block[641B, 153320B, 34567B, 63502B], DESFace.Block[56325B, 46250B, 36757B, 53732B], DESFace.Block[1110B, 152070B, 3366B, 70562B], DESFace.Block[50505B, 45530B, 26737B, 42012B], DESFace.Block[41375B, 42060B, 54527B, 77642B], DESFace.Block[2633B, 57010B, 50717B, 12072B], DESFace.Block[3526B, 154340B, 73507B, 60722B], DESFace.Block[73045B, 12270B, 24677B, 44152B], DESFace.Block[35735B, 10620B, 44467B, 24002B], DESFace.Block[23225B, 57550B, 32657B, 60232B], DESFace.Block[13115B, 57100B, 47447B, 51062B], DESFace.Block[65405B, 67030B, 72637B, 56312B], DESFace.Block[113B, 153357B, 4427B, 60142B], DESFace.Block[44015B, 34400B, 67347B, 61362B], DESFace.Block[41565B, 40310B, 64617B, 36372B], DESFace.Block[3455B, 41640B, 73407B, 51222B], DESFace.Block[1376B, 52567B, 100427B, 170452B], DESFace.Block[16635B, 56120B, 14367B, 24302B], DESFace.Block[30125B, 31050B, 66557B, 24532B], DESFace.Block[125252B, 125252B, 125252B, 125252B], DESFace.Block[0B, 0B, 0B, 0B] ]; cipherSequence: ARRAY [0..21) OF DESFace.Block ← [ DESFace.Block[64417B, 55415B, 115046B, 111633B], DESFace.Block[75070B, 116420B, 32513B, 151161B], DESFace.Block[103216B, 135521B, 145264B, 54632B], DESFace.Block[70570B, 103556B, 761B, 115452B], DESFace.Block[127467B, 175502B, 17614B, 40225B], DESFace.Block[103245B, 60361B, 7306B, 154133B], DESFace.Block[6323B, 155002B, 41B, 156011B], DESFace.Block[165147B, 65454B, 133733B, 25572B], DESFace.Block[157726B, 45201B, 56257B, 15017B], DESFace.Block[56121B, 36234B, 44206B, 140210B], DESFace.Block[5052B, 167256B, 37764B, 125567B], DESFace.Block[167433B, 170076B, 56772B, 53532B], DESFace.Block[104277B, 6666B, 153415B, 167126B], DESFace.Block[120771B, 110525B, 40402B, 5526B], DESFace.Block[67677B, 16257B, 147775B, 2526B], DESFace.Block[27442B, 162233B, 125574B, 120654B], DESFace.Block[55153B, 60454B, 141154B, 147112B], DESFace.Block[57514B, 1616B, 150453B, 27101B], DESFace.Block[61772B, 140320B, 32331B, 173623B], DESFace.Block[35347B, 13225B, 46700B, 47045B], DESFace.Block[106246B, 46751B, 140661B, 21647B] ]; RandomKey: PROCEDURE = BEGIN Put.Line[log, "Making Random key..."L]; key ← DESFace.GetRandomKey[]; PutKey[@key]; Put.CR[log]; END; RandomSeed: PROCEDURE = BEGIN Put.Line[log, "Making Random seed..."L]; seed ← DESFace.GetRandomIV[]; PutIV[@seed]; Put.CR[log]; END; FixedPatternTests: PROCEDURE = BEGIN error: BOOLEAN ← FALSE; block: DESFace.Block; Put.Line[log, "Fixed pattern tests..."L]; FOR i: CARDINAL IN [0..21) DO DESFace.EncryptBlock[LOOPHOLE[keySequence[i], DESFace.Key], @dataSequence[i], @block]; IF block # cipherSequence[i] THEN BEGIN Put.Text[log, "Encryption # "L]; PutDecimal[i]; Put.Line[log, " wrong."L]; error ← TRUE END; DESFace.DecryptBlock[LOOPHOLE[keySequence[i], DESFace.Key], @cipherSequence[i], @block]; IF block # dataSequence[i] THEN BEGIN Put.Text[log, "Decryption # "L]; PutDecimal[i]; Put.Line[log, " wrong."L]; error ← TRUE END; ENDLOOP; IF NOT error THEN Put.Line[log, "No errors."L]; Put.CR[log]; END; ECB1: PROCEDURE = BEGIN a, b, c: ARRAY [0..1) OF DESFace.Block ← [dataSequence[0]]; aa: DESFace.Blocks = @a; bb: DESFace.Blocks = @b; cc: DESFace.Blocks = @c; Put.Line[log, "Electronic Code Book, 1 block..."L]; PutKey[@key]; PutBlocks["in: "L, aa, 1]; DESFace.ECBEncrypt[key, 1, aa, bb]; PutBlocks["en: "L, bb, 1]; DESFace.ECBDecrypt[key, 1, bb, cc]; PutBlocks["de: "L, cc, 1]; IF a # c THEN Put.Line[log, "Didn't get the right answer. ←←←←←←←←"L]; Put.CR[log]; END; ECB4: PROCEDURE = BEGIN a, b, c: ARRAY [0..4) OF DESFace.Block ← [dataSequence[0], dataSequence[1], dataSequence[2], dataSequence[3]]; aa: DESFace.Blocks = @a; bb: DESFace.Blocks = @b; cc: DESFace.Blocks = @c; Put.Line[log, "Electronic Code Book, 4 blocks..."L]; PutKey[@key]; PutBlocks["in: "L, aa, 4]; DESFace.ECBEncrypt[key, 4, aa, bb]; PutBlocks["en: "L, bb, 4]; DESFace.ECBDecrypt[key, 4, bb, cc]; PutBlocks["de: "L, cc, 4]; IF a # c THEN Put.Line[log, "Didn't get the right answer. ←←←←←←←←"L]; Put.CR[log]; END; CBC1: PROCEDURE = BEGIN a, b, c: ARRAY [0..1) OF DESFace.Block ← [dataSequence[0]]; aa: DESFace.Blocks = @a; bb: DESFace.Blocks = @b; cc: DESFace.Blocks = @c; Put.Line[log, "Cipher Block Chaining, 1 block..."L]; PutKey[@key]; PutIV[@seed]; PutBlocks["in: "L, aa, 1]; DESFace.CBCEncrypt[key, 1, aa, bb, seed]; PutBlocks["en: "L, bb, 1]; DESFace.CBCDecrypt[key, 1, bb, cc, seed]; PutBlocks["de: "L, cc, 1]; IF a # c THEN Put.Line[log, "Didn't get the right answer. ←←←←←←←←"L]; Put.CR[log]; END; CBC4: PROCEDURE = BEGIN a, b, c: ARRAY [0..4) OF DESFace.Block ← [dataSequence[0], dataSequence[1], dataSequence[2], dataSequence[3]]; aa: DESFace.Blocks = @a; bb: DESFace.Blocks = @b; cc: DESFace.Blocks = @c; Put.Line[log, "Cipher Block Chaining, 4 blocks..."L]; PutKey[@key]; PutIV[@seed]; PutBlocks["in: "L, aa, 4]; DESFace.CBCEncrypt[key, 4, aa, bb, seed]; PutBlocks["en: "L, bb, 4]; DESFace.CBCDecrypt[key, 4, bb, cc, seed]; PutBlocks["de: "L, cc, 4]; IF a # c THEN Put.Line[log, "Didn't get the right answer. ←←←←←←←←"L]; Put.CR[log]; END; Loop: PROCEDURE [mode: {ecb, cbc}] = BEGIN old: Process.Priority ← Process.GetPriority[]; start, stop, p1, p65: System.Pulses ← [0]; good, bad, since: CARDINAL ← 0; t1, t65: LONG CARDINAL ← 0; setupTime, blockTime: LONG CARDINAL; clumps: LONG CARDINAL ← 0; error: BOOLEAN ← FALSE; input: ARRAY [0..65) OF DESFace.Block; encrypted: ARRAY [0..65) OF DESFace.Block; decrypted: ARRAY [0..65) OF DESFace.Block; in: DESFace.Blocks = LOOPHOLE[LONG[@input]]; en: DESFace.Blocks = LOOPHOLE[LONG[@encrypted]]; de: DESFace.Blocks = LOOPHOLE[LONG[@decrypted]]; pleaseStop: BOOLEAN ← FALSE; Watch: PROCEDURE = BEGIN [] ← OthelloDefs.ReadChar[ ! ABORTED => CONTINUE]; pleaseStop ← TRUE; END; FOR i: CARDINAL IN [0..65) DO input[i] ← dataSequence[i MOD 21]; ENDLOOP; SELECT mode FROM ecb => Put.Line[log, "Looping (ECB mode) ..."L]; cbc => Put.Line[log, "Looping (CBC mode) ..."L]; ENDCASE => ERROR; Process.Detach[FORK Watch[]]; UNTIL pleaseStop DO ok: BOOLEAN ← TRUE; Process.SetPriority[7]; start ← System.GetClockPulses[]; SELECT mode FROM ecb => BEGIN DESFace.ECBEncrypt[key, 1, in, en]; DESFace.ECBDecrypt[key, 1, en, de]; END; cbc => BEGIN DESFace.CBCEncrypt[key, 1, in, en, seed]; DESFace.CBCDecrypt[key, 1, en, de, seed]; END; ENDCASE => ERROR; stop ← System.GetClockPulses[]; Process.SetPriority[ProcessPriorities.priorityClientLow]; p1 ← [p1 + stop - start]; IF input[0] # decrypted[0] THEN BEGIN ok ← FALSE; Put.Char[log, '~]; END; Process.SetPriority[7]; start ← System.GetClockPulses[]; SELECT mode FROM ecb => BEGIN DESFace.ECBEncrypt[key, 65, in, en]; DESFace.ECBDecrypt[key, 65, en, de]; END; cbc => BEGIN DESFace.CBCEncrypt[key, 65, in, en, seed]; DESFace.CBCDecrypt[key, 65, en, de, seed]; END; ENDCASE => ERROR; stop ← System.GetClockPulses[]; Process.SetPriority[ProcessPriorities.priorityClientLow]; p65 ← [p65 + stop - start]; IF input # decrypted THEN BEGIN ok ← FALSE; Put.Char[log, '#]; END; clumps ← clumps + 1; IF ok THEN BEGIN good ← good + 1; since ← since + 1; IF since = 100 THEN BEGIN Put.Char[log, '!]; since ← 0; END; END ELSE bad ← bad + 1; ENDLOOP; t1 ← System.PulsesToMicroseconds[[p1]]; t65 ← System.PulsesToMicroseconds[[p65]]; Put.CR[log]; Process.SetPriority[old]; IF bad # 0 THEN BEGIN PutLongDecimal[bad]; Put.Text[log, " bad clumps. "L]; END; PutLongDecimal[good]; Put.Line[log, " good clumps."L]; Put.Text[log, "It took "L]; PutLongDecimal[t1/clumps]; Put.Line[log, " microseconds to encrypt and decrypt a 1 block clump."L]; Put.Text[log, "It took "L]; PutLongDecimal[t65/clumps]; Put.Line[log, " microseconds to encrypt and decrypt a 65 block clump."L]; blockTime ← (t65-t1)/(65-1)/clumps/2; setupTime ← (t1 - 1*blockTime)/clumps/2; Put.Text[log, "That's "L]; PutLongDecimal[setupTime]; Put.Text[log, " microseconds of setup and "L]; PutLongDecimal[blockTime]; Put.Text[log, " microseconds/block, or "L]; PutLongDecimal[64000000/blockTime]; Put.Line[log, " bits/second."L]; Put.CR[log]; END; Flap: PROCEDURE = BEGIN good, bad: LONG CARDINAL ← 0; data: ARRAY [0..21) OF DESFace.Block ← dataSequence; encrypted: ARRAY [0..21) OF DESFace.Block; decrypted: ARRAY [0..21) OF DESFace.Block; in: DESFace.Blocks = LOOPHOLE[LONG[@data]]; en: DESFace.Blocks = LOOPHOLE[LONG[@encrypted]]; de: DESFace.Blocks = LOOPHOLE[LONG[@decrypted]]; pleaseStop: BOOLEAN ← FALSE; Watch: PROCEDURE = BEGIN [] ← OthelloDefs.ReadChar[ ! ABORTED => CONTINUE]; pleaseStop ← TRUE; END; Put.Line[log, "Flapping DES signals (21 blocks of CBC)..."L]; Process.Detach[FORK Watch[]]; UNTIL pleaseStop DO DESFace.CBCEncrypt[key, 21, in, en, seed]; DESFace.CBCDecrypt[key, 21, en, de, seed]; IF data = decrypted THEN good ← good + 1 ELSE bad ← bad + 1; Process.Yield[]; ENDLOOP; Put.Text[log, "There were "L]; PutLongDecimal[good]; Put.Text[log, " good and "L]; PutLongDecimal[bad]; Put.Line[log, " bad clumps."L]; Put.CR[log]; END; PutIV: PROCEDURE [p: LONG POINTER TO DESFace.IV] = BEGIN PutClump["iv: "L, p, SIZE[DESFace.IV]]; END; PutKey: PROCEDURE [p: LONG POINTER TO DESFace.Key] = BEGIN PutClump["key: "L, p, SIZE[DESFace.Key]]; END; PutBlocks: PROCEDURE [id: LONG STRING, p: DESFace.Blocks, n: CARDINAL] = BEGIN PutClump[id, p, n*SIZE[DESFace.Block]]; END; PutClump: PROCEDURE [id: LONG STRING, p: LONG POINTER, n: CARDINAL] = BEGIN Put.Text[log, id]; FOR i: CARDINAL IN [0..n) DO temp: STRING = [20]; IF i # 0 AND (i MOD 8) = 0 THEN BEGIN Put.CR[log]; Put.Text[log, " "L]; END; String.AppendNumber[temp, (p+i)↑, 16]; THROUGH [temp.length..5) DO Put.Char[log, ' ]; ENDLOOP; Put.Text[log, temp]; ENDLOOP; Put.CR[log]; END; PutDecimal: PROCEDURE [n: CARDINAL] = INLINE BEGIN PutLongDecimal[n]; END; PutLongDecimal: PROCEDURE [n: LONG CARDINAL] = BEGIN temp: STRING = [20]; String.AppendLongDecimal[temp, n]; Put.Text[log, temp]; END; commandProcessor: OthelloDefs.CommandProcessor ← [Commands]; Commands: PROCEDURE [index: CARDINAL] = BEGIN SELECT index FROM 0 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES RandomKey"L, myHelpIs: "Make Random Key for DES Testing"L]; RandomKey[]; END; 1 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES RandomSeed"L, myHelpIs: "Make Random Seed for DES Testing in CBC mode"L]; RandomSeed[]; END; 2 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES Fixed Pattern Tests"L, myHelpIs: "Run magic patterns to test all bits in DES chip"L]; FixedPatternTests[]; END; 3 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES ECB1"L, myHelpIs: "Feed 1 block to DES in ECB mode"L]; ECB1[]; END; 4 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES ECB4"L, myHelpIs: "Feed 4 blocks to DES in ECB mode"L]; ECB4[]; END; 5 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES CBC1"L, myHelpIs: "Feed 1 block to DES in CBC mode"L]; CBC1[]; END; 6 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES CBC4"L, myHelpIs: "Feed 4 blocks to DES in CBC mode"L]; CBC4[]; END; 7 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES Loop ECB"L, myHelpIs: "Loop running DES chip in ECB mode"L]; Loop[ecb]; END; 8 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES Loop CBC"L, myHelpIs: "Loop running DES chip in CBC mode"L]; Loop[cbc]; END; 9 => BEGIN OthelloDefs.MyNameIs[ myNameIs: "DES Flap"L, myHelpIs: "Loop flapping DES signals (no printout)"L]; Flap[]; END; ENDCASE => OthelloDefs.IndexTooLarge; END; -- Main Body OthelloDefs.RegisterCommandProc[@commandProcessor]; END.