CryptoTwofish.Mod 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. MODULE CryptoTwofish; (** Twofish en/decryption *)
  2. (* Oberon port, based on twofish.c (vers. 1.0, Apr. 1998),
  3. 2002.07.22 g.f.
  4. *)
  5. IMPORT S := SYSTEM, Ciphers := CryptoCiphers, U := CryptoUtils;
  6. CONST
  7. N = 16;
  8. TYPE
  9. Block = ARRAY 4 OF SET32;
  10. SKey = ARRAY 4 OF SET32;
  11. VAR
  12. tab0: ARRAY 256 OF SET32;
  13. tab1: ARRAY 256 OF SET32;
  14. TYPE
  15. Cipher* = OBJECT (Ciphers.Cipher)
  16. VAR keybits: LONGINT;
  17. sbox: ARRAY 4 OF LONGINT;
  18. subkeys: ARRAY 8 + 2*N OF LONGINT;
  19. iv: Block;
  20. PROCEDURE InitKey*( CONST src: ARRAY OF CHAR; keybits: LONGINT );
  21. CONST step = 02020202H; bump = 01010101H;
  22. VAR
  23. i, A, B, m, nsub: LONGINT;
  24. k32e, k32o: ARRAY 4 OF LONGINT; (* even/odd key dwords *)
  25. BEGIN
  26. InitKey^( src, keybits ); SELF.keybits := keybits;
  27. FOR i := 0 TO keybits DIV 32 - 1 DO
  28. IF ODD( i ) THEN k32o[i DIV 2] := U.IntFromBufferLE( src, i*4 )
  29. ELSE k32e[i DIV 2] := U.IntFromBufferLE( src, i*4 )
  30. END
  31. END;
  32. m := keybits DIV 64 - 1;
  33. FOR i := 0 TO m DO
  34. (* compute S-box keys using (12,8) Reed-Solomon code over GF(256) *)
  35. sbox[m - i] := Encode( k32e[i], k32o[i] ); (* reverse order *)
  36. END;
  37. nsub := 8 + N*2;
  38. FOR i := 0 TO nsub DIV 2 - 1 DO
  39. (* compute round subkeys for PHT *)
  40. A := F32( S.VAL( SET32, i*step ), k32e, keybits ); (* A uses even key dwords *)
  41. B := ROT( F32( S.VAL( SET32, i*step + bump ), k32o, keybits ), 8 ); (* B uses odd key dwords *)
  42. subkeys[i*2] := A + B; (* combine with a PHT *)
  43. subkeys[i*2 + 1] := ROT( A + 2*B, 9 );
  44. END
  45. END InitKey;
  46. PROCEDURE SetIV*( CONST src: ARRAY OF CHAR; mode: SHORTINT );
  47. VAR i: INTEGER;
  48. BEGIN
  49. SetIV^( src, mode ); (* set mode *)
  50. FOR i := 0 TO 3 DO iv[i] := U.SetFromBufferLE( src, 4*i ) END;
  51. END SetIV;
  52. PROCEDURE Encrypt*( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  53. VAR i: LONGINT;
  54. BEGIN
  55. ASSERT( isKeyInitialized & (mode IN {Ciphers.ECB, Ciphers.CBC}) );
  56. ASSERT( len MOD blockSize = 0 ); (* padding must have been added *)
  57. i := 0;
  58. WHILE i < len DO EncryptBlock( buf, ofs + i ); INC( i, blockSize ); END
  59. END Encrypt;
  60. PROCEDURE Decrypt*( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  61. VAR i: LONGINT;
  62. BEGIN
  63. ASSERT( isKeyInitialized );
  64. ASSERT( len MOD blockSize = 0 ); (* padding must have been added *)
  65. i := 0;
  66. WHILE i < len DO DecryptBlock( buf, ofs + i ); INC( i, blockSize ); END
  67. END Decrypt;
  68. PROCEDURE EncryptBlock( VAR buf: ARRAY OF CHAR; pos: LONGINT );
  69. VAR x: Block; t0, t1, i, r: LONGINT; s0, s1: SET32;
  70. BEGIN
  71. (* copy in the block, add whitening *)
  72. FOR i := 0 TO 3 DO
  73. x[i] := U.SetFromBufferLE( buf, pos + i*4 ) / S.VAL( SET32, subkeys[i] );
  74. IF mode = Ciphers.CBC THEN x[i] := x[i] / iv[i] END
  75. END;
  76. (* main Twofish encryption loop *)
  77. FOR r := 0 TO N - 1 DO
  78. t0 := F32( x[0], sbox, keybits );
  79. t1 := F32( ROT( x[1], 8 ), sbox, keybits );
  80. x[2] := ROT( x[2] / S.VAL( SET32, t0 + t1 + subkeys[8 + 2*r] ), -1 );
  81. x[3] := ROT( x[3], 1 ) / S.VAL( SET32, t0 + t1*2 + subkeys[8 + 2*r + 1] );
  82. IF r < N - 1 THEN (* unswap, except for last round *)
  83. s0 := x[0]; x[0] := x[2]; x[2] := s0; s1 := x[1]; x[1] := x[3]; x[3] := s1;
  84. END
  85. END;
  86. (* copy out, with whitening *)
  87. FOR i := 0 TO 3 DO
  88. x[i] := x[i] / S.VAL( SET32, subkeys[4 + i] ); U.SetToBufferLE( x[i], buf, pos + i*4 );
  89. IF mode = Ciphers.CBC THEN iv[i] := x[i] END
  90. END;
  91. END EncryptBlock;
  92. PROCEDURE DecryptBlock( VAR buf: ARRAY OF CHAR; pos: LONGINT );
  93. VAR x0, x: Block; t0, t1, i, r: LONGINT; s0, s1: SET32;
  94. BEGIN
  95. (* copy in the block, add whitening *)
  96. FOR i := 0 TO 3 DO
  97. x0[i] := U.SetFromBufferLE( buf, pos + i*4 );
  98. x[i] := x0[i] / S.VAL( SET32, subkeys[4 + i] );
  99. END;
  100. (* main Twofish decryption loop *)
  101. FOR r := N - 1 TO 0 BY -1 DO
  102. t0 := F32( x[0], sbox, keybits );
  103. t1 := F32( ROT( x[1], 8 ), sbox, keybits );
  104. x[2] := ROT( x[2], 1 ); x[2] := x[2] / S.VAL( SET32, t0 + t1 + subkeys[8 + 2*r] );
  105. x[3] := ROT( x[3] / S.VAL( SET32, t0 + t1*2 + subkeys[8 + 2*r + 1] ), -1 );
  106. IF r > 0 THEN (* unswap, except for last round *)
  107. s0 := x[0]; x[0] := x[2]; x[2] := s0;
  108. s1 := x[1]; x[1] := x[3]; x[3] := s1;
  109. END
  110. END;
  111. (* copy out, with whitening *)
  112. FOR i := 0 TO 3 DO
  113. x[i] := x[i] / S.VAL( SET32, subkeys[i] );
  114. IF mode = Ciphers.CBC THEN x[i] := x[i] / iv[i]; iv[i] := x0[i] END;
  115. U.SetToBufferLE( x[i], buf, pos + i*4 );
  116. END;
  117. END DecryptBlock;
  118. PROCEDURE & Init*;
  119. BEGIN
  120. SetNameAndBlocksize( "twofish", 16 )
  121. END Init;
  122. END Cipher;
  123. PROCEDURE NewCipher*(): Ciphers.Cipher;
  124. VAR cipher: Cipher;
  125. BEGIN
  126. NEW( cipher ); RETURN cipher
  127. END NewCipher;
  128. (*-------------------------------------------------------------------------------*)
  129. CONST
  130. FDBK = 169H;
  131. Fdbk2 = S.VAL( SET32, FDBK DIV 2 );
  132. Fdbk4 = S.VAL( SET32, FDBK DIV 4 );
  133. Byte0 = S.VAL( SET32, 0FFH );
  134. S14d = S.VAL( SET32, 14DH );
  135. S0a6 = S.VAL( SET32, 0A6H );
  136. PROCEDURE m1( x: LONGINT ): SET32;
  137. BEGIN
  138. RETURN S.VAL( SET32, x )
  139. END m1;
  140. PROCEDURE mx( x: LONGINT ): SET32;
  141. VAR t: SET32;
  142. BEGIN
  143. t := S.VAL( SET32, x DIV 4 );
  144. IF ODD( x DIV 2 ) THEN t := t / Fdbk2 END;
  145. IF ODD( x ) THEN t := t / Fdbk4 END;
  146. RETURN S.VAL( SET32, x ) / t
  147. END mx;
  148. PROCEDURE my( x: LONGINT ): SET32;
  149. VAR t1, t2: SET32;
  150. BEGIN
  151. t1 := S.VAL( SET32, x DIV 2 ); t2 := S.VAL( SET32, x DIV 4 );
  152. IF ODD( x DIV 2 ) THEN t2 := t2 / Fdbk2 END;
  153. IF ODD( x ) THEN t1 := t1 / Fdbk2; t2 := t2 / Fdbk4 END;
  154. RETURN S.VAL( SET32, x ) / t1 / t2
  155. END my;
  156. PROCEDURE split( x: LONGINT; VAR v: SKey );
  157. BEGIN
  158. v[3] := S.VAL( SET32, x DIV 1000000H MOD 100H );
  159. v[2] := S.VAL( SET32, x DIV 10000H MOD 100H );
  160. v[1] := S.VAL( SET32, x DIV 100H MOD 100H );
  161. v[0] := S.VAL( SET32, x MOD 100H );
  162. END split;
  163. PROCEDURE -Int( x: SET32 ): LONGINT;
  164. BEGIN
  165. RETURN S.VAL( LONGINT, x )
  166. END Int;
  167. PROCEDURE F32( x: SET32; CONST k32: ARRAY OF LONGINT; keybits: LONGINT ): LONGINT;
  168. VAR a, b, c, d, l: LONGINT; k, k1: SKey;
  169. BEGIN
  170. (* Run each byte thru 8x8 S-boxes, xoring with key byte at each stage. *)
  171. (* Note that each byte goes through a different combination of S-boxes.*)
  172. d := Int( x ) DIV 1000000H MOD 100H;
  173. c := Int( x ) DIV 10000H MOD 100H;
  174. b := Int( x ) DIV 100H MOD 100H;
  175. a := Int( x ) MOD 100H;
  176. l := ((keybits + 63) DIV 64) MOD 4;
  177. IF l = 0 THEN (* 256 bits of key *)
  178. split( k32[3], k );
  179. a := Int( tab1[a] / k[0] );
  180. b := Int( tab0[b] / k[1] );
  181. c := Int( tab0[c] / k[2] );
  182. d := Int( tab1[d] / k[3] );
  183. END;
  184. IF l IN {0, 3} THEN (* 192 <= bits of key *)
  185. split( k32[2], k );
  186. a := Int( tab1[a] / k[0] );
  187. b := Int( tab1[b] / k[1] );
  188. c := Int( tab0[c] / k[2] );
  189. d := Int( tab0[d] / k[3] )
  190. END;
  191. (* 128 <= bits of key *)
  192. split( k32[1], k1 ); split( k32[0], k );
  193. a := Int( tab1[Int( tab0[Int( tab0[a] / k1[0] )] / k[0] )] );
  194. b := Int( tab0[Int( tab0[Int( tab1[b] / k1[1] )] / k[1] )] );
  195. c := Int( tab1[Int( tab1[Int( tab0[c] / k1[2] )] / k[2] )] );
  196. d := Int( tab0[Int( tab1[Int( tab1[d] / k1[3] )] / k[3] )] );
  197. (* Now perform the MDS matrix multiply *)
  198. RETURN Int( m1( a ) / my( b ) / mx( c ) / mx( d ) ) +
  199. ASH( Int( mx( a ) / my( b ) / my( c ) / m1( d ) ), 8 ) +
  200. ASH( Int( my( a ) / mx( b ) / m1( c ) / my( d ) ), 16 ) +
  201. ASH( Int( my( a ) / m1( b ) / my( c ) / mx( d ) ), 24 )
  202. END F32;
  203. (* RS_MDS_Encode *)
  204. PROCEDURE Encode( k0, k1: LONGINT ): LONGINT;
  205. VAR i, j, b: LONGINT; r, g2, g2s16, g3, g3s8, g3s24: SET32;
  206. BEGIN
  207. r := S.VAL( SET32, k1 );
  208. FOR i := 0 TO 1 DO
  209. IF i # 0 THEN r := r / S.VAL( SET32, k0 ) END;
  210. FOR j := 0 TO 3 DO
  211. b := S.VAL( LONGINT, LSH( r, -24 ) );
  212. g2 := S.VAL( SET32, b*2 );
  213. IF b > 7FH THEN g2 := (g2 / S14d) * Byte0 END;
  214. g2s16 := LSH( g2, 16 );
  215. g3 := S.VAL( SET32, b DIV 2 ) / g2;
  216. IF ODD( b ) THEN g3 := g3 / S0a6 END;
  217. g3s8 := LSH( g3, 8 );
  218. g3s24 := LSH( g3s8, 16 );
  219. r := LSH( r, 8 ) / g3s24 / g2s16 / g3s8 / S.VAL( SET32, b )
  220. END
  221. END;
  222. RETURN S.VAL( LONGINT, r )
  223. END Encode;
  224. PROCEDURE Init0;
  225. VAR
  226. buf: U.InitBuffer; i: LONGINT;
  227. BEGIN
  228. NEW( buf, 2048 );
  229. buf.Add( "0A9 067 0B3 0E8 004 0FD 0A3 076 09A 092 080 078 0E4 0DD 0D1 038 " );
  230. buf.Add( "00D 0C6 035 098 018 0F7 0EC 06C 043 075 037 026 0FA 013 094 048 " );
  231. buf.Add( "0F2 0D0 08B 030 084 054 0DF 023 019 05B 03D 059 0F3 0AE 0A2 082 " );
  232. buf.Add( "063 001 083 02E 0D9 051 09B 07C 0A6 0EB 0A5 0BE 016 00C 0E3 061 " );
  233. buf.Add( "0C0 08C 03A 0F5 073 02C 025 00B 0BB 04E 089 06B 053 06A 0B4 0F1 " );
  234. buf.Add( "0E1 0E6 0BD 045 0E2 0F4 0B6 066 0CC 095 003 056 0D4 01C 01E 0D7 " );
  235. buf.Add( "0FB 0C3 08E 0B5 0E9 0CF 0BF 0BA 0EA 077 039 0AF 033 0C9 062 071 " );
  236. buf.Add( "081 079 009 0AD 024 0CD 0F9 0D8 0E5 0C5 0B9 04D 044 008 086 0E7 " );
  237. buf.Add( "0A1 01D 0AA 0ED 006 070 0B2 0D2 041 07B 0A0 011 031 0C2 027 090 " );
  238. buf.Add( "020 0F6 060 0FF 096 05C 0B1 0AB 09E 09C 052 01B 05F 093 00A 0EF " );
  239. buf.Add( "091 085 049 0EE 02D 04F 08F 03B 047 087 06D 046 0D6 03E 069 064 " );
  240. buf.Add( "02A 0CE 0CB 02F 0FC 097 005 07A 0AC 07F 0D5 01A 04B 00E 0A7 05A " );
  241. buf.Add( "028 014 03F 029 088 03C 04C 002 0B8 0DA 0B0 017 055 01F 08A 07D " );
  242. buf.Add( "057 0C7 08D 074 0B7 0C4 09F 072 07E 015 022 012 058 007 099 034 " );
  243. buf.Add( "06E 050 0DE 068 065 0BC 0DB 0F8 0C8 0A8 02B 040 0DC 0FE 032 0A4 " );
  244. buf.Add( "0CA 010 021 0F0 0D3 05D 00F 000 06F 09D 036 042 04A 05E 0C1 0E0 " );
  245. FOR i := 0 TO 255 DO tab0[i] := buf.GetSet() END;
  246. buf.Init( 2048 );
  247. buf.Add( "075 0F3 0C6 0F4 0DB 07B 0FB 0C8 04A 0D3 0E6 06B 045 07D 0E8 04B " );
  248. buf.Add( "0D6 032 0D8 0FD 037 071 0F1 0E1 030 00F 0F8 01B 087 0FA 006 03F " );
  249. buf.Add( "05E 0BA 0AE 05B 08A 000 0BC 09D 06D 0C1 0B1 00E 080 05D 0D2 0D5 " );
  250. buf.Add( "0A0 084 007 014 0B5 090 02C 0A3 0B2 073 04C 054 092 074 036 051 " );
  251. buf.Add( "038 0B0 0BD 05A 0FC 060 062 096 06C 042 0F7 010 07C 028 027 08C " );
  252. buf.Add( "013 095 09C 0C7 024 046 03B 070 0CA 0E3 085 0CB 011 0D0 093 0B8 " );
  253. buf.Add( "0A6 083 020 0FF 09F 077 0C3 0CC 003 06F 008 0BF 040 0E7 02B 0E2 " );
  254. buf.Add( "079 00C 0AA 082 041 03A 0EA 0B9 0E4 09A 0A4 097 07E 0DA 07A 017 " );
  255. buf.Add( "066 094 0A1 01D 03D 0F0 0DE 0B3 00B 072 0A7 01C 0EF 0D1 053 03E " );
  256. buf.Add( "08F 033 026 05F 0EC 076 02A 049 081 088 0EE 021 0C4 01A 0EB 0D9 " );
  257. buf.Add( "0C5 039 099 0CD 0AD 031 08B 001 018 023 0DD 01F 04E 02D 0F9 048 " );
  258. buf.Add( "04F 0F2 065 08E 078 05C 058 019 08D 0E5 098 057 067 07F 005 064 " );
  259. buf.Add( "0AF 063 0B6 0FE 0F5 0B7 03C 0A5 0CE 0E9 068 044 0E0 04D 043 069 " );
  260. buf.Add( "029 02E 0AC 015 059 0A8 00A 09E 06E 047 0DF 034 035 06A 0CF 0DC " );
  261. buf.Add( "022 0C9 0C0 09B 089 0D4 0ED 0AB 012 0A2 00D 052 0BB 002 02F 0A9 " );
  262. buf.Add( "0D7 061 01E 0B4 050 004 0F6 0C2 016 025 086 056 055 009 0BE 091 " );
  263. FOR i := 0 TO 255 DO tab1[i] := buf.GetSet() END;
  264. END Init0;
  265. BEGIN
  266. Init0
  267. END CryptoTwofish.