CryptoAES.Mod 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. MODULE CryptoAES; (** AES (Rijndael) de/encryption *)
  2. (* 2002.07.22 g.f. *)
  3. IMPORT S := SYSTEM, Ciphers := CryptoCiphers, U := CryptoUtils;
  4. CONST
  5. MaxR = 14;
  6. ECB = Ciphers.ECB; CBC = Ciphers.CBC; CTR = Ciphers.CTR;
  7. b0 = S.VAL( SET, 0FFH ); b1 = S.VAL( SET, 0FF00H );
  8. b2 = S.VAL( SET, 0FF0000H ); b3 = S.VAL( SET, 0FF000000H );
  9. TYPE
  10. RTable = ARRAY 256 OF SET;
  11. VAR
  12. e0, e1, e2, e3, e4: RTable;
  13. d0, d1, d2, d3, d4: RTable;
  14. rcon: ARRAY 10 OF SET; (* for 128-bit blocks, Rijndael never uses more than 10 rcon values *)
  15. TYPE
  16. Cipher* = OBJECT (Ciphers.Cipher)
  17. TYPE
  18. RKeys = ARRAY 4*(MaxR + 1) OF SET;
  19. Block = ARRAY 4 OF SET;
  20. Ind4 = RECORD a, b, c, d: LONGINT END;
  21. VAR
  22. rounds: SHORTINT;
  23. ekeys, dkeys: RKeys;
  24. iv: Block;
  25. PROCEDURE InitKey*( CONST src: ARRAY OF CHAR; keybits: LONGINT );
  26. BEGIN
  27. InitKey^( src, keybits );
  28. IF keybits = 128 THEN rounds := Init128( ekeys, src )
  29. ELSIF keybits = 192 THEN rounds := Init192( ekeys, src )
  30. ELSE rounds := Init256( ekeys, src )
  31. END;
  32. dkeys := ekeys; Invert( dkeys, rounds )
  33. END InitKey;
  34. PROCEDURE SetIV*( CONST src: ARRAY OF CHAR; mode: SHORTINT );
  35. BEGIN
  36. SetIV^( src, mode ); (* set mode *)
  37. U.BufferToBlockBE( src, 0, iv );
  38. END SetIV;
  39. PROCEDURE IncIV;
  40. VAR i, x: LONGINT;
  41. BEGIN
  42. i := 4;
  43. REPEAT
  44. DEC( i );
  45. x := S.VAL( LONGINT, iv[i] ) + 1; iv[i] := S.VAL( SET, x )
  46. UNTIL (x # 0) OR (i = 0)
  47. END IncIV;
  48. PROCEDURE Encrypt*( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  49. VAR i, j: LONGINT; x, y: Block;
  50. BEGIN
  51. ASSERT( isKeyInitialized );
  52. ASSERT( len MOD blockSize = 0 ); (* padding must have been added *)
  53. i := 0;
  54. WHILE i < len DO
  55. U.BufferToBlockBE( buf, ofs + i, x );
  56. CASE mode OF
  57. | ECB:
  58. FOR j := 0 TO 3 DO x[j] := x[j] / ekeys[j] END;
  59. RoundE( ekeys, x, rounds );
  60. | CBC:
  61. FOR j := 0 TO 3 DO x[j] := x[j] / ekeys[j] / iv[j] END;
  62. RoundE( ekeys, x, rounds );
  63. iv := x;
  64. | CTR:
  65. FOR j := 0 TO 3 DO y[j] := iv[j] / ekeys[j] END;
  66. RoundE( ekeys, y, rounds );
  67. FOR j := 0 TO 3 DO x[j] := x[j] / y[j] END;
  68. IncIV
  69. END;
  70. U.BlockToBufferBE( x, buf, ofs + i );
  71. INC( i, blockSize )
  72. END
  73. END Encrypt;
  74. PROCEDURE Decrypt*( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  75. VAR x0, x, y: Block; i, j: LONGINT;
  76. BEGIN
  77. ASSERT( isKeyInitialized );
  78. ASSERT( len MOD blockSize = 0 ); (* padding must have been added *)
  79. i := 0;
  80. WHILE i < len DO
  81. U.BufferToBlockBE( buf, ofs + i, x0 );
  82. CASE mode OF
  83. | ECB:
  84. FOR j := 0 TO 3 DO x[j] := x0[j] / dkeys[j] END;
  85. RoundD( dkeys, x, rounds );
  86. | CBC:
  87. FOR j := 0 TO 3 DO x[j] := x0[j] / dkeys[j] END;
  88. RoundD( dkeys, x, rounds );
  89. FOR j := 0 TO 3 DO x[j] := x[j] / iv[j] END;
  90. iv := x0;
  91. | CTR:
  92. FOR j := 0 TO 3 DO y[j] := iv[j] / ekeys[j] END;
  93. RoundE( ekeys, y, rounds );
  94. FOR j := 0 TO 3 DO x[j] := x0[j] / y[j] END;
  95. IncIV
  96. END;
  97. U.BlockToBufferBE( x, buf, ofs + i );
  98. INC( i, blockSize )
  99. END
  100. END Decrypt;
  101. PROCEDURE RoundE( CONST rk: RKeys; VAR b: Block; rounds: SHORTINT );
  102. VAR p, r: LONGINT; t0, t1, t2, t3, s0, s1, s2, s3: Ind4;
  103. BEGIN
  104. split( b[0], s0 ); split( b[1], s1 ); split( b[2], s2 ); split( b[3], s3 );
  105. r := rounds DIV 2; p := 0;
  106. LOOP
  107. split( e0[s0.d]/e1[s1.c]/e2[s2.b]/e3[s3.a]/rk[p + 4], t0 );
  108. split( e0[s1.d]/e1[s2.c]/e2[s3.b]/e3[s0.a]/rk[p + 5], t1 );
  109. split( e0[s2.d]/e1[s3.c]/e2[s0.b]/e3[s1.a]/rk[p + 6], t2 );
  110. split( e0[s3.d]/e1[s0.c]/e2[s1.b]/e3[s2.a]/rk[p + 7], t3 );
  111. INC( p, 8 ); DEC( r );
  112. IF r = 0 THEN EXIT END;
  113. split( e0[t0.d]/e1[t1.c]/e2[t2.b]/e3[t3.a]/rk[p + 0], s0 );
  114. split( e0[t1.d]/e1[t2.c]/e2[t3.b]/e3[t0.a]/rk[p + 1], s1 );
  115. split( e0[t2.d]/e1[t3.c]/e2[t0.b]/e3[t1.a]/rk[p + 2], s2 );
  116. split( e0[t3.d]/e1[t0.c]/e2[t1.b]/e3[t2.a]/rk[p + 3], s3 );
  117. END;
  118. b[0] := (e4[t0.d]*b3)/(e4[t1.c]*b2)/(e4[t2.b]*b1)/(e4[t3.a]*b0)/rk[p + 0];
  119. b[1] := (e4[t1.d]*b3)/(e4[t2.c]*b2)/(e4[t3.b]*b1)/(e4[t0.a]*b0)/rk[p + 1];
  120. b[2] := (e4[t2.d]*b3)/(e4[t3.c]*b2)/(e4[t0.b]*b1)/(e4[t1.a]*b0)/rk[p + 2];
  121. b[3] := (e4[t3.d]*b3)/(e4[t0.c]*b2)/(e4[t1.b]*b1)/(e4[t2.a]*b0)/rk[p + 3];
  122. END RoundE;
  123. PROCEDURE RoundD( CONST rk: RKeys; VAR b: Block; rounds: SHORTINT );
  124. VAR p, r: LONGINT; t0, t1, t2, t3, s0, s1, s2, s3: Ind4;
  125. BEGIN
  126. split( b[0], s0 ); split( b[1], s1 ); split( b[2], s2 ); split( b[3], s3 );
  127. r := rounds DIV 2; p := 0;
  128. LOOP
  129. split( d0[s0.d]/d1[s3.c]/d2[s2.b]/d3[s1.a]/rk[p + 4], t0 );
  130. split( d0[s1.d]/d1[s0.c]/d2[s3.b]/d3[s2.a]/rk[p + 5], t1 );
  131. split( d0[s2.d]/d1[s1.c]/d2[s0.b]/d3[s3.a]/rk[p + 6], t2 );
  132. split( d0[s3.d]/d1[s2.c]/d2[s1.b]/d3[s0.a]/rk[p + 7], t3 );
  133. INC( p, 8 ); DEC( r );
  134. IF r = 0 THEN EXIT END;
  135. split( d0[t0.d]/d1[t3.c]/d2[t2.b]/d3[t1.a]/rk[p + 0], s0 );
  136. split( d0[t1.d]/d1[t0.c]/d2[t3.b]/d3[t2.a]/rk[p + 1], s1 );
  137. split( d0[t2.d]/d1[t1.c]/d2[t0.b]/d3[t3.a]/rk[p + 2], s2 );
  138. split( d0[t3.d]/d1[t2.c]/d2[t1.b]/d3[t0.a]/rk[p + 3], s3 );
  139. END;
  140. b[0] := (d4[t0.d]*b3)/(d4[t3.c]*b2)/(d4[t2.b]*b1)/(d4[t1.a]*b0)/rk[p + 0];
  141. b[1] := (d4[t1.d]*b3)/(d4[t0.c]*b2)/(d4[t3.b]*b1)/(d4[t2.a]*b0)/rk[p + 1];
  142. b[2] := (d4[t2.d]*b3)/(d4[t1.c]*b2)/(d4[t0.b]*b1)/(d4[t3.a]*b0)/rk[p + 2];
  143. b[3] := (d4[t3.d]*b3)/(d4[t2.c]*b2)/(d4[t1.b]*b1)/(d4[t0.a]*b0)/rk[p + 3];
  144. END RoundD;
  145. PROCEDURE -split( s: SET; VAR b: Ind4 ); (* split set into 4 indexes *)
  146. BEGIN
  147. b.a := S.VAL( LONGINT, s ) MOD 100H;
  148. b.b := S.VAL( LONGINT, s ) DIV 100H MOD 100H;
  149. b.c := S.VAL( LONGINT, s ) DIV 10000H MOD 100H;
  150. b.d := S.VAL( LONGINT, s ) DIV 1000000H MOD 100H;
  151. END split;
  152. PROCEDURE Init128( VAR rk: RKeys; CONST src: ARRAY OF CHAR ): SHORTINT;
  153. VAR i, p: LONGINT; ib: Ind4;
  154. BEGIN
  155. FOR i := 0 TO 3 DO rk[i] := U.SetFromBufferBE( src, 4*i ) END;
  156. p := 0; i := 0;
  157. LOOP
  158. split( rk[p + 3], ib );
  159. rk[p + 4] := rk[p] / (e4[ib.c]*b3) / (e4[ib.b]*b2) / (e4[ib.a]*b1) / (e4[ib.d]*b0) / rcon[i];
  160. rk[p + 5] := rk[p + 1] / rk[p + 4];
  161. rk[p + 6] := rk[p + 2] / rk[p + 5];
  162. rk[p + 7] := rk[p + 3] / rk[p + 6];
  163. INC( i );
  164. IF i = 10 THEN EXIT END;
  165. INC( p, 4 );
  166. END;
  167. RETURN 10
  168. END Init128;
  169. PROCEDURE Init192( VAR rk: RKeys; CONST src: ARRAY OF CHAR ): SHORTINT;
  170. VAR i, p: LONGINT; ib: Ind4;
  171. BEGIN
  172. FOR i := 0 TO 5 DO rk[i] := U.SetFromBufferBE( src, 4*i ) END;
  173. p := 0; i := 0;
  174. LOOP
  175. split( rk[p + 5], ib );
  176. rk[p + 6] := rk[p] / (e4[ib.c]*b3) / (e4[ib.b]*b2) / (e4[ib.a]*b1) / (e4[ib.d]*b0) / rcon[i];
  177. rk[p + 7] := rk[p + 1] / rk[p + 6];
  178. rk[p + 8] := rk[p + 2] / rk[p + 7];
  179. rk[p + 9] := rk[p + 3] / rk[p + 8];
  180. INC( i );
  181. IF i = 8 THEN EXIT END;
  182. rk[p + 10] := rk[p + 4] / rk[p + 9];
  183. rk[p + 11] := rk[p + 5] / rk[p + 10];
  184. INC( p, 6 );
  185. END;
  186. RETURN 12
  187. END Init192;
  188. PROCEDURE Init256( VAR rk: RKeys; CONST src: ARRAY OF CHAR ): SHORTINT;
  189. VAR i, p: LONGINT; ib: Ind4;
  190. BEGIN
  191. FOR i := 0 TO 7 DO rk[i] := U.SetFromBufferBE( src, 4*i ) END;
  192. p := 0; i := 0;
  193. LOOP
  194. split( rk[p + 7], ib );
  195. rk[p + 8] := rk[p] / (e4[ib.c]*b3) / (e4[ib.b]*b2) / (e4[ib.a]*b1) / (e4[ib.d]*b0) / rcon[i];
  196. rk[p + 9] := rk[p + 1] / rk[p + 8];
  197. rk[p + 10] := rk[p + 2] / rk[p + 9];
  198. rk[p + 11] := rk[p + 3] / rk[p + 10];
  199. INC( i );
  200. IF i = 7 THEN EXIT END;
  201. split( rk[p + 11], ib );
  202. rk[p + 12] := rk[p + 4] / (e4[ib.d]*b3) / (e4[ib.c]*b2) / (e4[ib.b]*b1) / (e4[ib.a]*b0);
  203. rk[p + 13] := rk[p + 5] / rk[p + 12];
  204. rk[p + 14] := rk[p + 6] / rk[p + 13];
  205. rk[p + 15] := rk[p + 7] / rk[p + 14];
  206. INC( p, 8 );
  207. END;
  208. RETURN 14
  209. END Init256;
  210. PROCEDURE Invert( VAR rk: RKeys; rounds: SHORTINT );
  211. VAR i, j, k, p: LONGINT; t: SET; ib: Ind4;
  212. PROCEDURE ind( s: SET ): LONGINT; (* extract index byte 0 *)
  213. BEGIN
  214. RETURN S.VAL( LONGINT, s ) MOD 100H
  215. END ind;
  216. BEGIN
  217. (* invert the order of the round keys: *)
  218. i := 0; j := 4*rounds;
  219. WHILE i < j DO
  220. FOR k := 0 TO 3 DO t := rk[i + k]; rk[i + k] := rk[j + k]; rk[j + k] := t END;
  221. INC( i, 4 ); DEC( j, 4 );
  222. END;
  223. (* apply the inverse MixColumn transform to all round keys but the first and the last: *)
  224. FOR i := 1 TO rounds - 1 DO
  225. FOR j := 0 TO 3 DO
  226. p := 4*i + j;
  227. split( rk[p], ib );
  228. rk[p] := d0[ind( e4[ib.d] )] / d1[ind( e4[ib.c] )] / d2[ind( e4[ib.b] )] / d3[ind( e4[ib.a] )];
  229. END
  230. END;
  231. END Invert;
  232. PROCEDURE & Init*;
  233. BEGIN
  234. SetNameAndBlocksize( "aes", 16 )
  235. END Init;
  236. END Cipher;
  237. PROCEDURE NewCipher*(): Ciphers.Cipher;
  238. VAR cipher: Cipher;
  239. BEGIN
  240. NEW( cipher ); RETURN cipher
  241. END NewCipher;
  242. (*-------------------------------------------------------------------------------*)
  243. TYPE
  244. ConstBuffer = OBJECT
  245. VAR
  246. buf: ARRAY 2048 OF CHAR; ib: LONGINT;
  247. PROCEDURE & Initialize;
  248. BEGIN
  249. ib := 0;
  250. END Initialize;
  251. PROCEDURE Append( CONST str: ARRAY OF CHAR );
  252. VAR i: LONGINT; c: CHAR;
  253. BEGIN
  254. i := 0;
  255. REPEAT c := str[i]; buf[ib] := c; INC( i ); INC( ib ) UNTIL c = 0X;
  256. buf[ib - 1] := ' '
  257. END Append;
  258. PROCEDURE GetInt( ): LONGINT;
  259. VAR x: LONGINT; c: CHAR;
  260. BEGIN
  261. WHILE buf[ib] <= ' ' DO INC( ib ) END;
  262. x := 0; c := buf[ib]; INC( ib );
  263. WHILE c > ' ' DO x := 10*x + (ORD( c ) - 48); c := buf[ib]; INC( ib ) END;
  264. RETURN x
  265. END GetInt;
  266. END ConstBuffer;
  267. PROCEDURE Initialize;
  268. VAR i, v1, i2, i4, i8, i9, ib, id, ie, v2, v3, t: LONGINT;
  269. buffer: ConstBuffer;
  270. PROCEDURE xor( a, b: LONGINT ): LONGINT;
  271. BEGIN
  272. RETURN S.VAL( LONGINT, S.VAL( SET, a ) / S.VAL( SET, b ) )
  273. END xor;
  274. PROCEDURE f1( x: LONGINT ): LONGINT;
  275. VAR y: LONGINT;
  276. BEGIN
  277. y := 2*x;
  278. IF y < 256 THEN RETURN y ELSE RETURN xor( y, 11BH ) END
  279. END f1;
  280. BEGIN
  281. NEW( buffer );
  282. buffer.Append( " 99 124 119 123 242 107 111 197 48 1 103 43 254 215 171 118 " );
  283. buffer.Append( "202 130 201 125 250 89 71 240 173 212 162 175 156 164 114 192 " );
  284. buffer.Append( "183 253 147 38 54 63 247 204 52 165 229 241 113 216 49 21 " );
  285. buffer.Append( " 4 199 35 195 24 150 5 154 7 18 128 226 235 39 178 117 " );
  286. buffer.Append( " 9 131 44 26 27 110 90 160 82 59 214 179 41 227 47 132 " );
  287. buffer.Append( " 83 209 0 237 32 252 177 91 106 203 190 57 74 76 88 207 " );
  288. buffer.Append( "208 239 170 251 67 77 51 133 69 249 2 127 80 60 159 168 " );
  289. buffer.Append( " 81 163 64 143 146 157 56 245 188 182 218 33 16 255 243 210 " );
  290. buffer.Append( "205 12 19 236 95 151 68 23 196 167 126 61 100 93 25 115 " );
  291. buffer.Append( " 96 129 79 220 34 42 144 136 70 238 184 20 222 94 11 219 " );
  292. buffer.Append( "224 50 58 10 73 6 36 92 194 211 172 98 145 149 228 121 " );
  293. buffer.Append( "231 200 55 109 141 213 78 169 108 86 244 234 101 122 174 8 " );
  294. buffer.Append( "186 120 37 46 28 166 180 198 232 221 116 31 75 189 139 138 " );
  295. buffer.Append( "112 62 181 102 72 3 246 14 97 53 87 185 134 193 29 158 " );
  296. buffer.Append( "225 248 152 17 105 217 142 148 155 30 135 233 206 85 40 223 " );
  297. buffer.Append( "140 161 137 13 191 230 66 104 65 153 45 15 176 84 187 22 " );
  298. buffer.Initialize;
  299. FOR i := 0 TO 255 DO
  300. v1 := buffer.GetInt(); v2 := f1( v1 ); v3 := xor( v2, v1);
  301. i2 := f1( i ); i4 := f1( i2 ); i8 := f1( i4 ); i9 := xor( i8, i);
  302. ib := xor( i9, i2 ); id := xor( i9, i4 ); ie := xor( i8, xor( i4, i2 ) );
  303. e0[i] := S.VAL( SET, ASH( v2, 24 ) + ASH( v1, 16 ) + ASH( v1, 8 ) + v3 );
  304. e1[i] := S.VAL( SET, ASH( v3, 24 ) + ASH( v2, 16 ) + ASH( v1, 8 ) + v1 );
  305. e2[i] := S.VAL( SET, ASH( v1, 24 ) + ASH( v3, 16 ) + ASH( v2, 8 ) + v1 );
  306. e3[i] := S.VAL( SET, ASH( v1, 24 ) + ASH( v1, 16 ) + ASH( v3, 8 ) + v2 );
  307. e4[i] := S.VAL( SET, ASH( v1, 24 ) + ASH( v1, 16 ) + ASH( v1, 8 ) + v1 );
  308. d0[v1] := S.VAL( SET, ASH( ie, 24 ) + ASH( i9, 16 ) + ASH( id, 8 ) + ib );
  309. d1[v1] := S.VAL( SET, ASH( ib, 24 ) + ASH( ie, 16 ) + ASH( i9, 8 ) + id );
  310. d2[v1] := S.VAL( SET, ASH( id, 24 ) + ASH( ib, 16 ) + ASH( ie, 8 ) + i9 );
  311. d3[v1] := S.VAL( SET, ASH( i9, 24 ) + ASH( id, 16 ) + ASH( ib, 8 ) + ie );
  312. d4[v1] := S.VAL( SET, ASH( i, 24 ) + ASH( i, 16 ) + ASH( i, 8 ) + i );
  313. END;
  314. t := 1;
  315. FOR i := 0 TO 9 DO
  316. rcon[i] := S.VAL( SET, ASH( t, 24 ) );
  317. t := f1( t );
  318. END;
  319. END Initialize;
  320. BEGIN
  321. Initialize;
  322. END CryptoAES.