CryptoDES.Mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. MODULE CryptoDES; (** AUTHOR "G.F."; PUROSE "DES Cipher"; *)
  2. (* based on POLARSSL des.c *)
  3. IMPORT S := SYSTEM, U := CryptoUtils, Ciphers := CryptoCiphers;
  4. CONST
  5. Mask01 = S.VAL( SET32, 0AAAAAAAAH );
  6. Mask02 = S.VAL( SET32, 33333333H );
  7. Mask04 = S.VAL( SET32, 0F0F0F0FH );
  8. Mask08 = S.VAL( SET32, 00FF00FFH );
  9. Mask16 = S.VAL( SET32, 0000FFFFH );
  10. TYPE
  11. Sandbox = ARRAY 64 OF SET32;
  12. BitSwap = ARRAY 16 OF SET32;
  13. Ind4* = RECORD a-, b-, c-, d-: LONGINT END;
  14. VAR
  15. sb1-, sb2-, sb3-, sb4-, sb5-, sb6-, sb7-, sb8-: Sandbox;
  16. LHs, RHs: BitSwap;
  17. TYPE
  18. Cipher* = OBJECT (Ciphers.Cipher)
  19. VAR
  20. ske, skd: ARRAY 32 OF SET32; ki: LONGINT;
  21. ivx, ivy: SET32;
  22. PROCEDURE InitKey*( CONST src: ARRAY OF CHAR; keybits: LONGINT );
  23. VAR X, Y: SET32; i: LONGINT;
  24. BEGIN
  25. ASSERT( keybits = 64 );
  26. InitKey^( src, keybits );
  27. X := U.SetFromBufferBE( src, 0 ); Y := U.SetFromBufferBE( src, 4 );
  28. ComputeSubkeys( X, Y, ske, 0 );
  29. FOR i := 0 TO 31 BY 2 DO
  30. skd[i] := ske[30 - i];
  31. skd[i + 1] := ske[31 - i]
  32. END;
  33. END InitKey;
  34. PROCEDURE SetIV*( CONST src: ARRAY OF CHAR; mode: SHORTINT );
  35. BEGIN
  36. SetIV^( src, mode ); (* set mode *)
  37. ivx := U.SetFromBufferBE( src, 0 ); ivy := U.SetFromBufferBE( src, 4 )
  38. END SetIV;
  39. PROCEDURE Encrypt* ( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  40. VAR i, r: LONGINT; X, Y: SET32;
  41. BEGIN
  42. ASSERT( isKeyInitialized & (mode IN {Ciphers.ECB, Ciphers.CBC}) );
  43. ASSERT( len MOD blockSize = 0 ); (* padding must have been added *)
  44. i := 0;
  45. WHILE i < len DO
  46. X := U.SetFromBufferBE( buf, ofs + i ); Y := U.SetFromBufferBE( buf, ofs + i + 4 );
  47. IF mode = Ciphers.CBC THEN X := X / ivx; Y := Y / ivy END;
  48. IP( X, Y );
  49. ki := 0;
  50. FOR r := 0 TO 7 DO
  51. RoundE( Y, X ); RoundE( X, Y );
  52. END;
  53. FP( Y, X );
  54. U.SetToBufferBE( Y, buf, ofs + i ); U.SetToBufferBE( X, buf, ofs + i + 4);
  55. IF mode = Ciphers.CBC THEN ivx := Y; ivy := X END;
  56. INC( i, blockSize )
  57. END
  58. END Encrypt;
  59. PROCEDURE Decrypt* ( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  60. VAR i, r: LONGINT; X, Y: SET32; X0, Y0: SET32;
  61. BEGIN
  62. ASSERT( isKeyInitialized );
  63. ASSERT( len MOD blockSize = 0 ); (* padding must have been added *)
  64. i := 0;
  65. WHILE i < len DO
  66. X := U.SetFromBufferBE( buf, ofs + i ); Y := U.SetFromBufferBE( buf, ofs + i + 4 );
  67. IF mode = Ciphers.CBC THEN X0 := X; Y0 := Y END;
  68. IP( X, Y );
  69. ki := 0;
  70. FOR r := 0 TO 7 DO
  71. RoundD( Y, X ); RoundD( X, Y );
  72. END;
  73. FP( Y, X );
  74. IF mode = Ciphers.CBC THEN
  75. Y := Y / ivx; X := X / ivy ;
  76. ivx := X0; ivy := Y0
  77. END;
  78. U.SetToBufferBE( Y, buf, ofs + i ); U.SetToBufferBE( X, buf, ofs + i + 4);
  79. INC( i, blockSize )
  80. END
  81. END Decrypt;
  82. PROCEDURE RoundE*( VAR x, y: SET32 );
  83. VAR i: Ind4;
  84. BEGIN
  85. Split( ske[ki] / x, i ); INC( ki );
  86. y := y / sb8[i.a] / sb6[i.b] / sb4[i.c] / sb2[i.d];
  87. Split( ske[ki] / ROT( x, -4 ), i ); INC( ki );
  88. y := y / sb7[i.a] / sb5[i.b] / sb3[i.c] / sb1[i.d]
  89. END RoundE;
  90. PROCEDURE RoundD*( VAR x, y: SET32 );
  91. VAR i: Ind4;
  92. BEGIN
  93. Split( skd[ki] / x, i ); INC( ki );
  94. y := y / sb8[i.a] / sb6[i.b] / sb4[i.c] / sb2[i.d];
  95. Split( skd[ki] / ROT( x, -4 ), i ); INC( ki );
  96. y := y / sb7[i.a] / sb5[i.b] / sb3[i.c] / sb1[i.d]
  97. END RoundD;
  98. PROCEDURE & Init*;
  99. BEGIN
  100. SetNameAndBlocksize( "des", 8 );
  101. END Init;
  102. END Cipher;
  103. (* temporarily disabled the inlining -- the compiler inliner still provides problems with the scope symbols *)
  104. PROCEDURE Split*( x: SET32; VAR i4: Ind4 );
  105. BEGIN
  106. i4.a := S.VAL( LONGINT, x ) MOD 40H;
  107. i4.b := S.VAL( LONGINT, x ) DIV 100H MOD 40H;
  108. i4.c := S.VAL( LONGINT, x ) DIV 10000H MOD 40H;
  109. i4.d := S.VAL( LONGINT, x ) DIV 1000000H MOD 40H
  110. END Split;
  111. PROCEDURE NewCipher*( ): Ciphers.Cipher;
  112. VAR cipher: Cipher;
  113. BEGIN
  114. NEW( cipher ); RETURN cipher
  115. END NewCipher;
  116. PROCEDURE IP*( VAR x, y: SET32 ); (* initial permutation *)
  117. VAR t: SET32;
  118. BEGIN
  119. t := (LSH( x, -4 ) / y) * Mask04; y := y / t; x := x / LSH( t, 4 );
  120. t := (LSH( x, -16 ) / y) * Mask16; y := y / t; x := x / LSH( t, 16 );
  121. t := (LSH( y, -2 ) / x) * Mask02; x := x / t; y := y / LSH( t, 2 );
  122. t := (LSH( y, -8 ) / x) * Mask08; x := x / t; y := y / LSH( t, 8 );
  123. y := ROT( y, 1 );
  124. t := (x / y) * Mask01; y := y / t; x := x / t;
  125. x := ROT( x, 1 );
  126. END IP;
  127. PROCEDURE FP*( VAR x, y: SET32 ); (* final permutation *)
  128. VAR t: SET32;
  129. BEGIN
  130. x := ROT( x, -1 );
  131. t := (x / y) * Mask01; x := x / t; y := y / t;
  132. y := ROT( y, -1 );
  133. t := (LSH( y, -8 ) / x) * Mask08; x := x / t; y := y / LSH( t, 8 );
  134. t := (LSH( y, -2 ) / x) * Mask02; x := x / t; y := y / LSH( t, 2 );
  135. t := (LSH( x, -16 ) / y) * Mask16; y := y / t; x := x / LSH( t, 16 );
  136. t := (LSH( x, -4 ) / y) * Mask04; y := y / t; x := x / LSH( t, 4 );
  137. END FP;
  138. PROCEDURE ComputeSubkeys*( x, y: SET32; VAR sk: ARRAY OF SET32; ofs: LONGINT );
  139. VAR t: SET32; i: LONGINT;
  140. PROCEDURE sms( CONST LRHs: BitSwap; x: SET32; rs, ls: LONGINT ): SET32;
  141. VAR i: LONGINT;
  142. BEGIN
  143. i := S.VAL( LONGINT, LSH( x, -rs ) ) MOD 16;
  144. RETURN LSH( LRHs[i], ls )
  145. END sms;
  146. PROCEDURE sm( b: SET32; shift, mask: LONGINT ): SET32;
  147. BEGIN
  148. RETURN LSH( b, shift ) * S.VAL( SET32, mask )
  149. END sm;
  150. BEGIN
  151. t := (LSH( y, -4 ) / x) * S.VAL( SET32, 0F0F0F0FH ); x := x / t; y := y / LSH( t, 4 );
  152. t := (y / x) * S.VAL( SET32, 10101010H ); x := x / t; y := y / t;
  153. x :=
  154. sms( LHs, x, 0, 3 ) + sms( LHs, x, 8, 2 ) + sms( LHs, x, 16, 1 ) + sms( LHs, x, 24, 0 ) +
  155. sms( LHs, x, 5, 7 ) + sms( LHs, x, 13, 6 ) + sms( LHs, x, 21, 5 ) + sms( LHs, x, 29, 4 );
  156. y :=
  157. sms( RHs, y, 1, 3 ) + sms( RHs, y, 9, 2 ) + sms( RHs, y, 17, 1 ) + sms( RHs, y, 25, 0 ) +
  158. sms( RHs, y, 4, 7 ) + sms( RHs, y, 12, 6 ) + sms( RHs, y, 20, 5 ) + sms( RHs, y, 28, 4 );
  159. FOR i := 0 TO 15 DO
  160. IF i IN {0, 1, 8, 15} THEN
  161. x := LSH( x, 1 ) + LSH( x, -27 ); y := LSH( y, 1 ) + LSH( y, -27 )
  162. ELSE
  163. x := LSH( x, 2 ) + LSH( x, -26 ); y := LSH( y, 2 ) + LSH( y, -26 )
  164. END;
  165. sk[ofs + 2*i] :=
  166. sm( x, 4, 24000000H ) + sm( x, 28, 10000000H ) +
  167. sm( x, 14, 08000000H ) + sm( x, 18, 02080000H ) +
  168. sm( x, 6, 01000000H ) + sm( x, 9, 00200000H ) +
  169. sm( x, -1, 00100000H ) + sm( x, 10, 00040000H ) +
  170. sm( x, 2, 00020000H ) + sm( x, -10, 00010000H ) +
  171. sm( y,-13, 00002000H ) + sm( y, -4, 00001000H ) +
  172. sm( y, 6, 00000800H ) + sm( y, -1, 00000400H ) +
  173. sm( y, -14, 00000200H ) + sm( y, 0, 00000100H ) +
  174. sm( y, -5, 00000020H ) + sm( y, -10, 00000010H ) +
  175. sm( y, -3, 00000008H ) + sm( y, -18, 00000004H ) +
  176. sm( y, -26, 00000002H ) + sm( y, -24, 00000001H );
  177. sk[ofs + 2*i + 1] :=
  178. sm( x, 15, 20000000H ) + sm( x, 17, 10000000H ) +
  179. sm( x, 10, 08000000H ) + sm( x, 22, 04000000H ) +
  180. sm( x, -2, 02000000H ) + sm( x, 1, 01000000H ) +
  181. sm( x, 16, 00200000H ) + sm( x, 11, 00100000H ) +
  182. sm( x, 3, 00080000H ) + sm( x, -6, 00040000H ) +
  183. sm( x, 15, 00020000H ) + sm( x, -4, 00010000H ) +
  184. sm( y, -2, 00002000H ) + sm( y, 8, 00001000H ) +
  185. sm( y, -14, 00000808H ) + sm( y, -9, 00000400H ) +
  186. sm( y, 0, 00000200H ) + sm( y, 7, 00000100H ) +
  187. sm( y, -7, 00000020H ) + sm( y, -3, 00000011H ) +
  188. sm( y, 2, 00000004H ) + sm( y, -21, 00000002H );
  189. END
  190. END ComputeSubkeys;
  191. PROCEDURE InitializeSandboxes;
  192. VAR
  193. buf: U.InitBuffer;
  194. PROCEDURE InitTable( VAR tab: ARRAY OF SET32 );
  195. VAR i: LONGINT;
  196. BEGIN
  197. FOR i := 0 TO LEN( tab ) - 1 DO tab[i] := buf.GetSet( ) END
  198. END InitTable;
  199. BEGIN
  200. NEW( buf, 1024 );
  201. buf.Add( "01010400 00000000 00010000 01010404 01010004 00010404 00000004 00010000 " );
  202. buf.Add( "00000400 01010400 01010404 00000400 01000404 01010004 01000000 00000004 " );
  203. buf.Add( "00000404 01000400 01000400 00010400 00010400 01010000 01010000 01000404 " );
  204. buf.Add( "00010004 01000004 01000004 00010004 00000000 00000404 00010404 01000000 " );
  205. buf.Add( "00010000 01010404 00000004 01010000 01010400 01000000 01000000 00000400 " );
  206. buf.Add( "01010004 00010000 00010400 01000004 00000400 00000004 01000404 00010404 " );
  207. buf.Add( "01010404 00010004 01010000 01000404 01000004 00000404 00010404 01010400 " );
  208. buf.Add( "00000404 01000400 01000400 00000000 00010004 00010400 00000000 01010004 " );
  209. InitTable( sb1 );
  210. buf.Init( 1024 );
  211. buf.Add( "80108020 80008000 00008000 00108020 00100000 00000020 80100020 80008020 " );
  212. buf.Add( "80000020 80108020 80108000 80000000 80008000 00100000 00000020 80100020 " );
  213. buf.Add( "00108000 00100020 80008020 00000000 80000000 00008000 00108020 80100000 " );
  214. buf.Add( "00100020 80000020 00000000 00108000 00008020 80108000 80100000 00008020 " );
  215. buf.Add( "00000000 00108020 80100020 00100000 80008020 80100000 80108000 00008000 " );
  216. buf.Add( "80100000 80008000 00000020 80108020 00108020 00000020 00008000 80000000 " );
  217. buf.Add( "00008020 80108000 00100000 80000020 00100020 80008020 80000020 00100020 " );
  218. buf.Add( "00108000 00000000 80008000 00008020 80000000 80100020 80108020 00108000 " );
  219. InitTable( sb2 );
  220. buf.Init( 1024 );
  221. buf.Add( "00000208 08020200 00000000 08020008 08000200 00000000 00020208 08000200 " );
  222. buf.Add( "00020008 08000008 08000008 00020000 08020208 00020008 08020000 00000208 " );
  223. buf.Add( "08000000 00000008 08020200 00000200 00020200 08020000 08020008 00020208 " );
  224. buf.Add( "08000208 00020200 00020000 08000208 00000008 08020208 00000200 08000000 " );
  225. buf.Add( "08020200 08000000 00020008 00000208 00020000 08020200 08000200 00000000 " );
  226. buf.Add( "00000200 00020008 08020208 08000200 08000008 00000200 00000000 08020008 " );
  227. buf.Add( "08000208 00020000 08000000 08020208 00000008 00020208 00020200 08000008 " );
  228. buf.Add( "08020000 08000208 00000208 08020000 00020208 00000008 08020008 00020200 " );
  229. InitTable( sb3 );
  230. buf.Init( 1024 );
  231. buf.Add( "00802001 00002081 00002081 00000080 00802080 00800081 00800001 00002001 " );
  232. buf.Add( "00000000 00802000 00802000 00802081 00000081 00000000 00800080 00800001 " );
  233. buf.Add( "00000001 00002000 00800000 00802001 00000080 00800000 00002001 00002080 " );
  234. buf.Add( "00800081 00000001 00002080 00800080 00002000 00802080 00802081 00000081 " );
  235. buf.Add( "00800080 00800001 00802000 00802081 00000081 00000000 00000000 00802000 " );
  236. buf.Add( "00002080 00800080 00800081 00000001 00802001 00002081 00002081 00000080 " );
  237. buf.Add( "00802081 00000081 00000001 00002000 00800001 00002001 00802080 00800081 " );
  238. buf.Add( "00002001 00002080 00800000 00802001 00000080 00800000 00002000 00802080 " );
  239. InitTable( sb4 );
  240. buf.Init( 1024 );
  241. buf.Add( "00000100 02080100 02080000 42000100 00080000 00000100 40000000 02080000 " );
  242. buf.Add( "40080100 00080000 02000100 40080100 42000100 42080000 00080100 40000000 " );
  243. buf.Add( "02000000 40080000 40080000 00000000 40000100 42080100 42080100 02000100 " );
  244. buf.Add( "42080000 40000100 00000000 42000000 02080100 02000000 42000000 00080100 " );
  245. buf.Add( "00080000 42000100 00000100 02000000 40000000 02080000 42000100 40080100 " );
  246. buf.Add( "02000100 40000000 42080000 02080100 40080100 00000100 02000000 42080000 " );
  247. buf.Add( "42080100 00080100 42000000 42080100 02080000 00000000 40080000 42000000 " );
  248. buf.Add( "00080100 02000100 40000100 00080000 00000000 40080000 02080100 40000100 " );
  249. InitTable( sb5 );
  250. buf.Init( 1024 );
  251. buf.Add( "20000010 20400000 00004000 20404010 20400000 00000010 20404010 00400000 " );
  252. buf.Add( "20004000 00404010 00400000 20000010 00400010 20004000 20000000 00004010 " );
  253. buf.Add( "00000000 00400010 20004010 00004000 00404000 20004010 00000010 20400010 " );
  254. buf.Add( "20400010 00000000 00404010 20404000 00004010 00404000 20404000 20000000 " );
  255. buf.Add( "20004000 00000010 20400010 00404000 20404010 00400000 00004010 20000010 " );
  256. buf.Add( "00400000 20004000 20000000 00004010 20000010 20404010 00404000 20400000 " );
  257. buf.Add( "00404010 20404000 00000000 20400010 00000010 00004000 20400000 00404010 " );
  258. buf.Add( "00004000 00400010 20004010 00000000 20404000 20000000 00400010 20004010 " );
  259. InitTable( sb6 );
  260. buf.Init( 1024 );
  261. buf.Add( "00200000 04200002 04000802 00000000 00000800 04000802 00200802 04200800 " );
  262. buf.Add( "04200802 00200000 00000000 04000002 00000002 04000000 04200002 00000802 " );
  263. buf.Add( "04000800 00200802 00200002 04000800 04000002 04200000 04200800 00200002 " );
  264. buf.Add( "04200000 00000800 00000802 04200802 00200800 00000002 04000000 00200800 " );
  265. buf.Add( "04000000 00200800 00200000 04000802 04000802 04200002 04200002 00000002 " );
  266. buf.Add( "00200002 04000000 04000800 00200000 04200800 00000802 00200802 04200800 " );
  267. buf.Add( "00000802 04000002 04200802 04200000 00200800 00000000 00000002 04200802 " );
  268. buf.Add( "00000000 00200802 04200000 00000800 04000002 04000800 00000800 00200002 " );
  269. InitTable( sb7 );
  270. buf.Init( 1024 );
  271. buf.Add( "10001040 00001000 00040000 10041040 10000000 10001040 00000040 10000000 " );
  272. buf.Add( "00040040 10040000 10041040 00041000 10041000 00041040 00001000 00000040 " );
  273. buf.Add( "10040000 10000040 10001000 00001040 00041000 00040040 10040040 10041000 " );
  274. buf.Add( "00001040 00000000 00000000 10040040 10000040 10001000 00041040 00040000 " );
  275. buf.Add( "00041040 00040000 10041000 00001000 00000040 10040040 00001000 00041040 " );
  276. buf.Add( "10001000 00000040 10000040 10040000 10040040 10000000 00040000 10001040 " );
  277. buf.Add( "00000000 10041040 00040040 10000040 10040000 10001000 10001040 00000000 " );
  278. buf.Add( "10041040 00041000 00041000 00001040 00001040 00040040 10000000 10041000 " );
  279. InitTable( sb8 );
  280. buf.Init( 512 );
  281. buf.Add( "00000000 00000001 00000100 00000101 00010000 00010001 00010100 00010101 " );
  282. buf.Add( "01000000 01000001 01000100 01000101 01010000 01010001 01010100 01010101 " );
  283. InitTable( LHs );
  284. buf.Init( 512 );
  285. buf.Add( "00000000 01000000 00010000 01010000 00000100 01000100 00010100 01010100 " );
  286. buf.Add( "00000001 01000001 00010001 01010001 00000101 01000101 00010101 01010101 " );
  287. InitTable( RHs );
  288. END InitializeSandboxes;
  289. BEGIN
  290. InitializeSandboxes
  291. END CryptoDES.
  292. System.Free CryptoTestCiphers CryptoDES ~