CryptoUtils.Mod 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. MODULE CryptoUtils; (** AUTHOR "GF"; PURPOSE ""; *)
  2. IMPORT S := SYSTEM, Out := KernelLog, Random, Kernel, B := CryptoBigNumbers;
  3. TYPE
  4. InitBuffer* = OBJECT (** buffer supporting initialization of large tables with hex values *)
  5. VAR
  6. buf: POINTER TO ARRAY OF CHAR;
  7. in, out: LONGINT;
  8. PROCEDURE & Init*( size: LONGINT );
  9. BEGIN
  10. NEW( buf, size ); in := 0; out := 0;
  11. END Init;
  12. PROCEDURE Add*( CONST x: ARRAY OF CHAR );
  13. VAR i: LONGINT; c: CHAR;
  14. BEGIN
  15. c := x[0]; i := 1;
  16. WHILE c # 0X DO
  17. buf[in] := c; INC( in ); c := x[i]; INC( i )
  18. END;
  19. buf[in] := ' '; INC( in ); buf[in] := 0X
  20. END Add;
  21. PROCEDURE GetInt*( ): LONGINT;
  22. VAR x: LONGINT; c: CHAR;
  23. BEGIN
  24. WHILE (buf[out] <= ' ') & (buf[out] # 0X) DO INC( out ) END;
  25. c := buf[out]; INC( out ); x := 0;
  26. REPEAT
  27. IF (c >= '0') & (c <= '9') THEN x := 16*x + (ORD( c ) - ORD( '0' ))
  28. ELSIF (c >= 'A') & (c <= 'F') THEN x := 16*x + (ORD( c ) - ORD( 'A' ) + 10)
  29. ELSIF (c >= 'a') & (c <= 'f') THEN x := 16*x + (ORD( c ) - ORD( 'a' ) + 10)
  30. ELSE HALT( 100 )
  31. END;
  32. c := buf[out]; INC( out )
  33. UNTIL c <= ' ';
  34. RETURN x
  35. END GetInt;
  36. PROCEDURE GetSet*(): SET32;
  37. BEGIN
  38. RETURN S.VAL( SET32, GetInt() )
  39. END GetSet;
  40. END InitBuffer
  41. VAR
  42. hexd: ARRAY 17 OF CHAR; (* constant *)
  43. PROCEDURE PrintHex*( CONST buf: ARRAY OF CHAR; p, n: LONGINT );
  44. VAR ch, i: LONGINT;
  45. BEGIN
  46. FOR i := 0 TO n - 1 DO
  47. IF i MOD 4 = 0 THEN
  48. IF i MOD 24 = 0 THEN Out.Ln END;
  49. Out.String( " " )
  50. END;
  51. ch := ORD( buf[p + i] );
  52. Out.Char( hexd[ch DIV 10H] );
  53. Out.Char( hexd[ch MOD 10H] );
  54. END
  55. END PrintHex;
  56. PROCEDURE PrintBufferString*( CONST buf: ARRAY OF CHAR; pos: LONGINT );
  57. VAR i, p, len: LONGINT;
  58. BEGIN
  59. p := pos;
  60. GetLength( buf, p, len );
  61. FOR i := 0 TO len - 1 DO Out.Char( buf[p + i] ) END
  62. END PrintBufferString;
  63. PROCEDURE PrintPackage*( CONST buf: ARRAY OF CHAR; len: LONGINT );
  64. VAR i: LONGINT; c: CHAR;
  65. BEGIN
  66. FOR i := 0 TO len - 1 DO
  67. IF i MOD 24 = 0 THEN Out.Ln END;
  68. IF i MOD 4 = 0 THEN Out.Char( ' ' ) END;
  69. c := buf[i];
  70. Out.Char( hexd[ ORD( c ) DIV 16] );
  71. Out.Char( hexd[ ORD( c ) MOD 16] );
  72. END ;
  73. Out.Ln
  74. END PrintPackage;
  75. (*========== packet buffer <---> program data ===========*)
  76. PROCEDURE PutLength*( VAR buf: ARRAY OF CHAR; VAR pos: LONGINT; len: LONGINT );
  77. VAR i: INTEGER;
  78. BEGIN
  79. FOR i := 3 TO 0 BY -1 DO
  80. buf[pos + i] := CHR( len MOD 256 ); len := len DIV 256
  81. END;
  82. INC( pos, 4 )
  83. END PutLength;
  84. PROCEDURE GetLength*( CONST buf: ARRAY OF CHAR; VAR pos, len: LONGINT );
  85. BEGIN
  86. len := ASH( LONG( ORD( buf[pos] ) ), 24 ) +
  87. ASH( LONG( ORD( buf[pos + 1] ) ), 16 ) +
  88. ASH( LONG( ORD( buf[pos + 2] ) ), 8 ) +
  89. ORD( buf[pos + 3] );
  90. INC( pos, 4 );
  91. END GetLength;
  92. PROCEDURE GetInt*( CONST buf: ARRAY OF CHAR; pos: LONGINT ): LONGINT;
  93. BEGIN
  94. RETURN ASH( LONG( ORD( buf[pos] ) ), 24 ) +
  95. ASH( LONG( ORD( buf[pos + 1] ) ), 16 ) +
  96. ASH( LONG( ORD( buf[pos + 2] ) ), 8 ) +
  97. ORD( buf[pos + 3] );
  98. END GetInt;
  99. PROCEDURE PutChar*( VAR buf: ARRAY OF CHAR; VAR pos: LONGINT; ch: CHAR );
  100. BEGIN
  101. buf[pos] := ch; INC( pos )
  102. END PutChar;
  103. PROCEDURE GetChar*( CONST buf: ARRAY OF CHAR; VAR pos: LONGINT; VAR ch: CHAR );
  104. BEGIN
  105. ch := buf[pos]; INC( pos )
  106. END GetChar;
  107. PROCEDURE PutString*( VAR buf: ARRAY OF CHAR; VAR pos: LONGINT; CONST str: ARRAY OF CHAR );
  108. VAR i, len: LONGINT;
  109. BEGIN
  110. len := 0;
  111. WHILE (len < LEN(str)) & (str[len] # 0X) DO INC( len ) END;
  112. PutLength( buf, pos, len );
  113. FOR i := 0 TO len -1 DO buf[pos] := str[i]; INC( pos ) END ;
  114. END PutString;
  115. PROCEDURE GetString*( CONST buf: ARRAY OF CHAR; VAR pos: LONGINT; VAR str: ARRAY OF CHAR );
  116. VAR i, len: LONGINT;
  117. BEGIN
  118. GetLength( buf, pos, len );
  119. FOR i := 0 TO len -1 DO str[i] := buf[pos]; INC( pos ) END;
  120. str[len] := 0X
  121. END GetString;
  122. PROCEDURE PutArray*( VAR buf: ARRAY OF CHAR; VAR pos: LONGINT;
  123. CONST arr: ARRAY OF CHAR; apos, len: LONGINT );
  124. VAR i: LONGINT;
  125. BEGIN
  126. PutLength( buf, pos, len );
  127. FOR i := 0 TO len -1 DO buf[pos] := arr[apos + i]; INC( pos ) END
  128. END PutArray;
  129. PROCEDURE PutBigNumber*( VAR buf: ARRAY OF CHAR; VAR pos: LONGINT; b: B.BigNumber );
  130. VAR i, j, len: LONGINT; x: UNSIGNED32; tmp: ARRAY 2048 OF CHAR;
  131. BEGIN
  132. len := 0;
  133. FOR i := b.len - 1 TO 0 BY -1 DO
  134. (* store 'digits' in network byte order (big endian) *)
  135. x := b.d[i];
  136. FOR j := 3 TO 0 BY -1 DO
  137. tmp[len + j] := CHR( x MOD 256 ); x := x DIV 256
  138. END;
  139. INC( len, 4 )
  140. END;
  141. j := 0;
  142. WHILE tmp[j] = 0X DO INC( j ); DEC( len ) END;
  143. IF ORD( tmp[j] ) >= 128 THEN PutLength( buf, pos, len + 1 ); buf[pos] := 0X; INC( pos )
  144. ELSE PutLength( buf, pos, len );
  145. END;
  146. FOR i := 0 TO len - 1 DO buf[pos] := tmp[j + i]; INC( pos ) END;
  147. END PutBigNumber;
  148. PROCEDURE GetBigNumber*( CONST buf: ARRAY OF CHAR; VAR pos: LONGINT; VAR b: B.BigNumber );
  149. VAR
  150. len: LONGINT;
  151. BEGIN
  152. GetLength( buf, pos, len );
  153. B.AssignBin( b, buf, pos, len );
  154. INC( pos, len )
  155. END GetBigNumber;
  156. (*---------------- misc -------------------------------*)
  157. (** convert 2*len hex nibbles into len bytes *)
  158. PROCEDURE Hex2Bin*( CONST hex: ARRAY OF CHAR; hp: LONGINT;
  159. VAR bin: ARRAY OF CHAR; bp: LONGINT;
  160. len: LONGINT );
  161. VAR
  162. i: INTEGER; h, b: LONGINT; c: CHAR;
  163. BEGIN
  164. i := 0;
  165. WHILE i < 2*len DO (* parse one nibble at a time *)
  166. c := hex[hp + i];
  167. IF (c >= '0') & (c <= '9') THEN h := ORD( c ) - ORD( '0' );
  168. ELSIF (c >= 'a') & (c <= 'f') THEN h := ORD( c ) - ORD( 'a' ) + 10;
  169. ELSIF (c >= 'A') & (c <= 'F') THEN h := ORD( c ) - ORD( 'A' ) + 10;
  170. ELSIF c = 0X THEN
  171. Out.String( "### error: hex source too short" ); Out.Ln;
  172. HALT( 99 )
  173. ELSE
  174. Out.String( "### format error in hex string" ); Out.Ln;
  175. HALT( 99 )
  176. END;
  177. IF ODD( i ) THEN bin[bp] := CHR( b + h ); INC( bp )
  178. ELSE b := h * 16
  179. END;
  180. INC( i );
  181. END
  182. END Hex2Bin;
  183. (** convert len bytes into 2*len hex nibbles *)
  184. PROCEDURE Bin2Hex*( CONST bin: ARRAY OF CHAR; bp: LONGINT;
  185. VAR hex: ARRAY OF CHAR; hp: LONGINT;
  186. len: LONGINT );
  187. VAR i, c: LONGINT;
  188. BEGIN
  189. FOR i := 0 TO len - 1 DO
  190. c := ORD( bin[ bp + i] );
  191. hex[hp] := hexd[ c DIV 16]; INC( hp );
  192. hex[hp] := hexd[ c MOD 16]; INC( hp );
  193. END
  194. END Bin2Hex;
  195. (** fill len pseudo-random bytes into buf, starting at posistion ofs *)
  196. PROCEDURE RandomBytes*( VAR buf: ARRAY OF CHAR; ofs, len: LONGINT );
  197. VAR
  198. i: LONGINT;
  199. rg: Random.Generator;
  200. BEGIN
  201. NEW( rg );
  202. rg.InitSeed( Kernel.GetTicks() );
  203. FOR i := 0 TO len - 1 DO buf[ ofs + i ] := CHR( ENTIER( rg.Uniform()*256 ) ) END
  204. END RandomBytes;
  205. PROCEDURE XORBlock*( VAR block, iv: ARRAY OF S.BYTE );
  206. VAR a1, a2: ADDRESS; s1, s2: SET32; i: LONGINT;
  207. BEGIN
  208. a1 := ADDRESSOF( block ); a2 := ADDRESSOF( iv );
  209. FOR i := 1 TO LEN( block ) DIV 4 DO
  210. S.GET( a1, s1 ); S.GET( a2, s2 ); S.PUT( a1, s1 / s2 );
  211. INC( a1, 4 ); INC( a2, 4 )
  212. END
  213. END XORBlock;
  214. (* copy char buffer to 32-bit words in block. big endian format *)
  215. PROCEDURE BufferToBlockBE*( CONST buf: ARRAY OF CHAR; pos: LONGINT; VAR block: ARRAY OF S.BYTE );
  216. VAR i: LONGINT; a: ADDRESS;
  217. BEGIN
  218. a := ADDRESSOF( block );
  219. FOR i := 1 TO LEN( block ) DIV 4 DO
  220. S.PUT( a,
  221. ASH( LONG( ORD( buf[pos + 0] ) ), 24 ) +
  222. ASH( LONG( ORD( buf[pos + 1] ) ), 16 ) +
  223. ASH( LONG( ORD( buf[pos + 2] ) ), 8 ) +
  224. ORD( buf[pos + 3] ) );
  225. INC( a, 4 ); INC( pos, 4 )
  226. END
  227. END BufferToBlockBE;
  228. (* copy char buffer to 32-bit words in block. little endian format *)
  229. PROCEDURE BufferToBlockLE*( CONST buf: ARRAY OF CHAR; pos: LONGINT; VAR block: ARRAY OF S.BYTE );
  230. VAR i: LONGINT; a: ADDRESS;
  231. BEGIN
  232. a := ADDRESSOF( block );
  233. FOR i := 1 TO LEN( block ) DIV 4 DO
  234. S.PUT( a,
  235. ASH( LONG( ORD( buf[pos + 3] ) ), 24 ) +
  236. ASH( LONG( ORD( buf[pos + 2] ) ), 16 ) +
  237. ASH( LONG( ORD( buf[pos + 1] ) ), 8 ) +
  238. ORD( buf[pos + 0] ) );
  239. INC( a, 4 ); INC( pos, 4 )
  240. END
  241. END BufferToBlockLE;
  242. (* copy 32bit words in block to char buffer. big endian format *)
  243. PROCEDURE BlockToBufferBE*( CONST block: ARRAY OF S.BYTE; VAR buf: ARRAY OF CHAR; pos: LONGINT );
  244. VAR a: ADDRESS; i, w: LONGINT;
  245. BEGIN
  246. a := ADDRESSOF( block );
  247. FOR i := 1 TO LEN( block ) DIV 4 DO
  248. S.GET( a, w ); INC( a, 4 );
  249. buf[pos + 3] := CHR( w MOD 256 ); w := w DIV 256;
  250. buf[pos + 2] := CHR( w MOD 256 ); w := w DIV 256;
  251. buf[pos + 1] := CHR( w MOD 256 ); w := w DIV 256;
  252. buf[pos + 0] := CHR( w MOD 256 );
  253. INC( pos, 4 )
  254. END
  255. END BlockToBufferBE;
  256. (* copy 32bit words in block to char buffer. little endian format *)
  257. PROCEDURE BlockToBufferLE*( CONST block: ARRAY OF S.BYTE; VAR buf: ARRAY OF CHAR; pos: LONGINT );
  258. VAR a: ADDRESS; i, w: LONGINT;
  259. BEGIN
  260. a := ADDRESSOF( block );
  261. FOR i := 1 TO LEN( block ) DIV 4 DO
  262. S.GET( a, w ); INC( a, 4 );
  263. buf[pos + 0] := CHR( w MOD 100H ); w := w DIV 100H;
  264. buf[pos + 1] := CHR( w MOD 100H ); w := w DIV 100H;
  265. buf[pos + 2] := CHR( w MOD 100H ); w := w DIV 100H;
  266. buf[pos + 3] := CHR( w MOD 100H );
  267. INC( pos, 4 )
  268. END
  269. END BlockToBufferLE;
  270. PROCEDURE SetToBufferBE*( val: SET32; VAR buf: ARRAY OF CHAR; pos: LONGINT );
  271. BEGIN
  272. IntToBufferBE( S.VAL( LONGINT, val ), buf, pos );
  273. END SetToBufferBE;
  274. PROCEDURE IntToBufferBE*( val: LONGINT; VAR buf: ARRAY OF CHAR; pos: LONGINT );
  275. BEGIN
  276. buf[pos + 3] := CHR( val MOD 256 ); val := val DIV 256;
  277. buf[pos + 2] := CHR( val MOD 256 ); val := val DIV 256;
  278. buf[pos + 1] := CHR( val MOD 256 ); val := val DIV 256;
  279. buf[pos + 0] := CHR( val MOD 256 );
  280. END IntToBufferBE;
  281. PROCEDURE SetToBufferLE*( val: SET32; VAR buf: ARRAY OF CHAR; pos: LONGINT );
  282. BEGIN
  283. IntToBufferLE( S.VAL( LONGINT, val ), buf, pos );
  284. END SetToBufferLE;
  285. PROCEDURE IntToBufferLE*( val: LONGINT; VAR buf: ARRAY OF CHAR; pos: LONGINT );
  286. BEGIN
  287. buf[pos + 0] := CHR( val MOD 256 ); val := val DIV 256;
  288. buf[pos + 1] := CHR( val MOD 256 ); val := val DIV 256;
  289. buf[pos + 2] := CHR( val MOD 256 ); val := val DIV 256;
  290. buf[pos + 3] := CHR( val MOD 256 );
  291. END IntToBufferLE;
  292. PROCEDURE SetFromBufferBE*( CONST buf: ARRAY OF CHAR; pos: LONGINT ): SET32;
  293. BEGIN
  294. RETURN S.VAL( SET32, IntFromBufferBE( buf, pos ) )
  295. END SetFromBufferBE;
  296. PROCEDURE IntFromBufferBE*( CONST buf: ARRAY OF CHAR; pos: LONGINT ): LONGINT;
  297. BEGIN
  298. RETURN ASH( LONG( ORD( buf[pos + 0] ) ), 24 ) +
  299. ASH( LONG( ORD( buf[pos + 1] ) ), 16 ) +
  300. ASH( LONG( ORD( buf[pos + 2] ) ), 8 ) +
  301. ORD( buf[pos + 3] );
  302. END IntFromBufferBE;
  303. PROCEDURE SetFromBufferLE*( CONST buf: ARRAY OF CHAR; pos: LONGINT ): SET32;
  304. BEGIN
  305. RETURN S.VAL( SET32, IntFromBufferLE( buf, pos ) )
  306. END SetFromBufferLE;
  307. PROCEDURE IntFromBufferLE*( CONST buf: ARRAY OF CHAR; pos: LONGINT ): LONGINT;
  308. BEGIN
  309. RETURN ASH( LONG( ORD( buf[pos + 3] ) ), 24 ) +
  310. ASH( LONG( ORD( buf[pos + 2] ) ), 16 ) +
  311. ASH( LONG( ORD( buf[pos + 1] ) ), 8 ) +
  312. ORD( buf[pos] );
  313. END IntFromBufferLE;
  314. BEGIN
  315. hexd := "0123456789ABCDEF";
  316. END CryptoUtils.