gencry.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. * gencry.c Copyright (C) 1998, A C Norman
  3. *
  4. * This program generates C code for ACNs encryption thing...
  5. * For an explanation see comments further down the code.
  6. */
  7. /* Signature: 0c7d0cd2 05-Nov-1998 */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. /*
  11. * This code is capable of generating members of a family of generators.
  12. * It can cope with 32 or 64-bit arithmetic and with parameterisation
  13. * of the size of the generator.
  14. */
  15. #ifndef WORD_LENGTH
  16. /*
  17. * This may be 32 or 64, depending on the characteristics of the
  18. * target computer
  19. */
  20. # define WORD_LENGTH 32
  21. #endif
  22. #ifndef UNSIGNED_TYPE
  23. /*
  24. * This must be a C type that will hold an unsigned integer of size
  25. * as given by WORD_LENGTH. For 64-bits it may sometimes be
  26. * "unsigned long" but it may "unsigned long long" when using GCC on
  27. * 32-bit computers. Note that the quotes are needed around the type
  28. * description.
  29. */
  30. # define UNSIGNED_TYPE "unsigned int"
  31. #endif
  32. #ifndef CRYPT_BLOCK_SIZE
  33. /*
  34. * The code will generate this many bytes of data for each call. Must be
  35. * a multiple of the number of bytes in a word.
  36. */
  37. # define CRYPT_BLOCK_SIZE 128
  38. #endif
  39. #ifndef SHIFT_REGISTER_LENGTH
  40. /*
  41. * length on underlying shift register, and must be large enough to cope
  42. * with the CRYPT_BLOCK_SIZE above. This is tested for during code creation.
  43. * Rounded up to the next size for a primitive polynomial.
  44. */
  45. # define SHIFT_REGISTER_LENGTH 65
  46. #endif
  47. #ifndef SHUFFLE_BUFFER_SIZE
  48. /*
  49. * A larger shuffle-buffer causes worse cache misses, but would enhance
  50. * security. Rounded to a power of 2.
  51. */
  52. # define SHUFFLE_BUFFER_SIZE 4096
  53. #endif
  54. /*
  55. * This generator starts by using a 55/24 (or other) Lagged Fibonacci
  56. * generator, except that at each stage I sometimes use XOR, sometimes "+"
  57. * and sometimes "-". Each of these are much like simple XOR and specifically
  58. * do just that on the least significant bit (so we still have a period
  59. * of 2^k-1 there) but they make propagation into higher parts of the
  60. * word non-linear. I selected the mix of operators based on digits from
  61. * pi in the expectation that that leaves few systematic patterns.
  62. * The period of the whole register is clearly some multiple of (2^k-1).
  63. * It will not be 2^32 as big, but experiments with short registers
  64. * suggests that it will be an long enough, say over 2^16 times as long. If
  65. * I take k=65 then this ought to be sufficient.
  66. *
  67. * I collect a block of k words from that, and then form output words
  68. * by combining items from there in various shifted manners so that what
  69. * comes out mixes bits from high and low in the basic register with the
  70. * result that that knowledge of one output word does not reveal a single
  71. * clear value in the shift register. Again I use "^", "+" and "-" for
  72. * the combining and a manner mixed up using pi. The selection of which
  73. * of the registers words are combined is also derived from digits of pi
  74. * rather than being simply sequential. In particular the bottom bit of
  75. * an word in the shift register is only used after being XORed with a value
  76. * from 18 bits higher by where the perios ought to be long enough
  77. * and the mixing sufficient to obscure them. The high order bits (which
  78. * one might attack since they are used to control the shuffling) are mixed
  79. * with data from 13 bits lower, and also benefit (sometimes) from carries and
  80. * borrows in the combining. In a sixty-four bit register a large number
  81. * of bits in the middle of the word get formed by combining bits of three
  82. * raw words. For 32-bit working it is roughly the case that the bottom
  83. * section of an output word comes from one pair (A,B) say while the top
  84. * comes from a different pair (A,C).
  85. *
  86. * Finally I shuffle in a N (= 4096 perhaps) entry buffer so that answers
  87. * do not get issued in (easily) predictable order. Each cycling of the
  88. * generator produces k words in this manner, but I then only keep 32 of
  89. * these. Discarding the rest corresponds to throwing away a tolerably
  90. * confusing subset of the original shift-register output, as well as
  91. * arranging that output data is out of order.
  92. *
  93. * To start things I initially just fill the LFSR with data based upon
  94. * multiple copies of the key. I then cycle things. After a bit I
  95. * propagate information from the top half of each word to the bottom,
  96. * considering that without that the low order bits will not gain information
  97. * from enough of the key. I also force a low order bit to be "1" at
  98. * various stages (despite the bias!) to guarantee that my shift register
  99. * is not stuck in a zero cycle. I extract values form the generator to fill
  100. * up the shuffling buffer. Once crudely initialised I cycle the generator
  101. * enough times to refresh most of the values in the shuffle buffer several
  102. * times. This all makes key establishment pretty slow, but I view that
  103. * as almost desirable. It would of couse also be possible to fill both
  104. * shift register and buffer with values derived from the key using
  105. * a secure hash function.
  106. *
  107. * The arrangements here guarantee that the least significant bit of the
  108. * word-stream that is generated is of period 2^k-1. Each subsequent bit
  109. * counts as a further maximal-period shift register of length k that is
  110. * being driven by data injected via the carry chain from less significant
  111. * bits. I can not prove that there is no bias here, nor that the
  112. * resulting overall system has a period as long as one would hope for from
  113. * 32*k bits of state. One notes the analysis of the lagged-fibonacci
  114. * generator where Knuth reports on ways of distinguishing its output
  115. * from real randomness. These concerns are why I discard quite a large
  116. * proportion of the bits that I generate, and why I shuffle the output.
  117. *
  118. * We all know that shift-registers when used simply are weak. The
  119. * steps taken here to improve matters are
  120. * (a) using mixtures or +, - and ^ for the combining functions;
  121. * (b) shuffling the output, after the style of Knuth's "Algorithm B";
  122. * (c) discarding a proportion of the bits generated by the raw shift
  123. * register;
  124. * (d) make each output depend on a combination of several words from
  125. * the shift register, with not all words used.
  126. *
  127. * A lagged fibonacci generator would give more "1" bits than "0" in
  128. * various lengths of initial sub-sequence. I complement every other
  129. * output from the raw generator to mess this up a bit. The shuffling
  130. * then has to conceal whether I had odd or even items.
  131. *
  132. * Lagged fibonacci has trouble with a birthday spacings test, and shuffling
  133. * would not cure that, but throwing away some of my generated values will
  134. * help to a significant extent, as will the fact that I output words that
  135. * are generated as combinations of three items from the register.
  136. * A number of adjustments to the algorithm as shown here would be
  137. * obvious and easy to arrange:
  138. * (a) use a larger shuffle-buffer. At present I use 4096 words, but
  139. * increasing it would hardly change the code and would tend to
  140. * improve security but at the cost of memory requirement. Once
  141. * can redefine a macro here to organise this;
  142. * (b) use SHA-1 or some other secure hash to initialise both the shift
  143. * register and the shuffle buffer from the original key. This
  144. * would probably be a good thing to do. I use the scheme itself here
  145. * to make this code more self-contained;
  146. * (c) use a longer shift-register than the 55- or 65-entry one used here,
  147. * but still only keep 32 words of output from each full cycle through
  148. * it. That would slow things down in direct proportion to the
  149. * length of the register, but would enhance security by making more
  150. * information discarded as well as by increasing the period. The code
  151. * here has a varienty of options that could be enabled;
  152. * (d) use 64-bit arithmetic but essentially unaltered code to get
  153. * 32 64-bit words out in the amount of time that this code yields
  154. * 32 32-bit words. The code makes provision for this;
  155. * (e) Base the design on a shift register with more taps, with a view
  156. * that very few taps (as used here) are a source of weakness. Cost
  157. * will grow proportional to the number of taps used.
  158. *
  159. * For (c) and (e) suitable tap positions so that the least significant bits
  160. * still have maximal cycle lengths would be needed.
  161. *
  162. * Performance (65/4096) at 32 bits is around
  163. * 1 millisecond to set up a new key
  164. * 100 Mbytes per second generation of guff
  165. * (this is on a Pentium II at 400 Mhz)
  166. * and a crude test suggests that the scheme here fills a 128-byte buffer
  167. * roughly three times as fast as RC4 does (?).
  168. */
  169. int taps[][2] =
  170. {
  171. /*
  172. * A pair of numbers {k, t} here represents a primitive polynomial
  173. * x^k + x^t + 1
  174. * mod 2, which should generate sequences of length 2^k-1. I include lots
  175. * of very small polynomials here since they may be useful when testing this
  176. * scheme, but at present I default to k=65.
  177. */
  178. {2, 1},
  179. {3, 1},
  180. {4, 1},
  181. {5, 2},
  182. {6, 1},
  183. {7, 3},
  184. {9, 4},
  185. {10, 3},
  186. {11, 2},
  187. {15, 1},
  188. {17, 6},
  189. {18, 7},
  190. {20, 3},
  191. {21,2},
  192. {22, 1},
  193. {23, 5},
  194. {25, 3},
  195. {28, 3},
  196. {29, 2},
  197. {31, 6},
  198. {33, 13},
  199. {35, 2},
  200. {36, 11},
  201. {39, 4},
  202. {41, 3},
  203. {47, 5},
  204. {49, 9},
  205. {52, 3},
  206. {55, 24},
  207. {57, 7},
  208. {58, 19},
  209. {60, 1},
  210. {63, 1},
  211. {65, 18},
  212. {68, 9},
  213. {71, 6},
  214. {73, 25},
  215. {79, 9},
  216. {81, 4},
  217. {84, 13},
  218. {0, 0}
  219. };
  220. /*
  221. * I provide enought digits of pi for all the shift register configurations
  222. * listed above.
  223. */
  224. static char *pi =
  225. "3141592653589793238462643383279502884197169399375105820974944592"
  226. "3078164062862089986280348253421170679821480865132823066470938446"
  227. "0955058223172535940812848111745028410270193852110555964462294895"
  228. "4930381964428810975665933446128475648233786783165271201909145648"
  229. "5669234603486104543266482133936072602491412737245870066063155881"
  230. "7488152092096282925409171536436789259036001133053054882046652138"
  231. "4146951941511609433057270365759591953092186117381932611793105118"
  232. "5480744623799627495673518857527248912279381830119491298336733624"
  233. "4065664308602139494639522473719070217986094370277053921717629317"
  234. "6752384674818467669405132000568127145263560827785771342757789609"
  235. "1736371787214684409012249534301465495853710507922796892589235420"
  236. "1995611212902196086403441815981362977477130996051870721134999999"
  237. "8372978049951059731732816096318595024459455346908302642522308253"
  238. "3446850352619311881710100031378387528865875332083814206171776691"
  239. "4730359825349042875546873115956286388235378759375195778185778053"
  240. "2171226806613001927876611195909216420198938095257201065485863278";
  241. static char *pip;
  242. /*
  243. * The next procedure returns "^", "+" or "-", and the selection made
  244. * depends on digits from pi (as tabulated above). I discard '9' digits
  245. * and use '0' to '8' to give a pair of three-way choices. The use of pi
  246. * here is not because it has special magic properties. It is more the
  247. * opposite: people will not suspect me of having chosen mixes of the
  248. * operations in any awkward way if I use a natural constant in the choice.
  249. */
  250. static next_op = -1;
  251. char *op()
  252. {
  253. int w;
  254. if (next_op >= 0)
  255. { w = next_op;
  256. next_op = -1;
  257. }
  258. else
  259. { do
  260. { if ((w = *pip++) == 0)
  261. { printf("I ran out of pi digits\n");
  262. exit(1);
  263. }
  264. w -= '0';
  265. } while (w == 9);
  266. next_op = w % 3;
  267. w = w / 3;
  268. }
  269. switch (w)
  270. {
  271. default: return "^";
  272. case 1: return "+";
  273. case 2: return "-";
  274. }
  275. }
  276. /*
  277. * return a value in the range 0 ... n-1 based on digits from pi.
  278. */
  279. int pirand(int n)
  280. {
  281. int c, w, t;
  282. for (;;)
  283. { w = 0;
  284. t = 1;
  285. while (w < n)
  286. { if ((c = *pip++) == 0)
  287. { printf("I ran out of pi digits\n");
  288. exit(1);
  289. }
  290. w = 10*w + c - '0';
  291. t = 10*t;
  292. }
  293. c = (t/n)*n;
  294. if (w < c) return w % n;
  295. /*
  296. * I sample again if the value pulled from pi is outside a range that is
  297. * an exact multiple of n.
  298. */
  299. }
  300. }
  301. #define BYTES_PER_WORD (WORD_LENGTH/8)
  302. int main(int argc, char *argv[])
  303. {
  304. int len, tap, shift, shuffle, i, w;
  305. int perm1[SHIFT_REGISTER_LENGTH+20],
  306. perm2[SHIFT_REGISTER_LENGTH+20],
  307. perm3[SHIFT_REGISTER_LENGTH+20];
  308. /*
  309. * First I find a primitive polynomial that will support a shift register of
  310. * the desired length. I allow myself to round the length up by up to 20.
  311. */
  312. for (i=0;;i++)
  313. { if (taps[i][0] == 0)
  314. { printf("Shift register taps not found\n");
  315. exit(1);
  316. }
  317. else if (taps[i][0] >= SHIFT_REGISTER_LENGTH &&
  318. taps[i][0] < SHIFT_REGISTER_LENGTH+20) break;
  319. }
  320. len = taps[i][0];
  321. tap = taps[i][1];
  322. /*
  323. * next I ensure that the shuffle buffer will have a size that is a power of
  324. * 2, and I calculate the logarithm of its size.
  325. */
  326. i = SHUFFLE_BUFFER_SIZE;
  327. shift = 0;
  328. while (i > 1)
  329. { shift++;
  330. i = i >> 1;
  331. }
  332. shuffle = 1 << shift;
  333. /*
  334. * Establish three mildly chaotic permutations that will help me use values
  335. * from the shift register in unhelpful orderings.
  336. */
  337. for (i=0; i<len; i++)
  338. perm1[i] = perm2[i] = perm3[i] = i;
  339. pip = pi;
  340. for (i=0; i<len; i++)
  341. { int p = pirand(len-i);
  342. w = perm1[i]; perm1[i] = perm1[i+p]; perm1[i+p] = w;
  343. p = pirand(len-i);
  344. w = perm2[i]; perm2[i] = perm2[i+p]; perm2[i+p] = w;
  345. p = pirand(len-i);
  346. w = perm3[i]; perm3[i] = perm3[i+p]; perm3[i+p] = w;
  347. }
  348. printf("\n/*\n");
  349. printf(" * word length = %d\n", WORD_LENGTH);
  350. printf(" * shift register length = %d\n", len);
  351. printf(" * tap at position %d\n", tap);
  352. printf(" * shuffle-buffer size = %d\n", shuffle);
  353. printf(" */\n\n");
  354. printf("#ifdef TIME_TEST\n\n");
  355. printf("#include <stdio.h>\n");
  356. printf("#include <time.h>\n\n");
  357. printf("#define N 10000000 /* parameters for time test */\n");
  358. printf("#define NSTARTS 4000\n");
  359. printf("#define NTINY 50000000\n");
  360. printf("#define KEY \"Arthurs's sample key\"\n\n");
  361. printf("typedef %s unsigned%d;\n\n", UNSIGNED_TYPE, WORD_LENGTH);
  362. printf("#endif /* TIME_TEST */\n\n");
  363. printf("static unsigned%d lf[%d], mix[%d];\n\n", WORD_LENGTH, len, shuffle);
  364. printf("#define R(x) ((x) >> %d)\n", WORD_LENGTH-shift);
  365. printf("#define S(x) ((x) >> 18)\n");
  366. printf("#define T(x) ((x) << 13)\n\n");
  367. printf("static unsigned char byte_order_test[] =\n");
  368. printf("{1, 0, 0, 0, 0, 0, 0, 0};\n\n");
  369. printf("#define CRYPT_BLOCK_SIZE %d\n\n", CRYPT_BLOCK_SIZE);
  370. printf("void crypt_get_block(unsigned char block[CRYPT_BLOCK_SIZE])\n{\n");
  371. printf(" unsigned%d *b = (unsigned%d *)block;\n",
  372. WORD_LENGTH, WORD_LENGTH);
  373. printf(" int n;\n");
  374. for (i=0; i<len; i++)
  375. { int j = (i + tap) % len;
  376. printf(" lf[%d] %s= lf[%d];", i, op(), j);
  377. if ((i % 2) == 1) printf("\n");
  378. else if (i < 10 && j < 10) printf(" ");
  379. else if (i < 10 || j < 10) printf(" ");
  380. }
  381. if ((len % 2) == 1) printf("\n");
  382. w = -1;
  383. for (i=0; i<len/4; i++)
  384. { char *op1, *op2;
  385. printf(" n = R(lf[%d]);", 4*i);
  386. if (++w < CRYPT_BLOCK_SIZE/BYTES_PER_WORD)
  387. printf(" b[%d] = mix[n];", w);
  388. op1 = op(); op2 = op();
  389. printf(" mix[n] = %s(lf[%d] %s S(lf[%d])) %s T(lf[%d]);\n",
  390. (w&1) ? "~" : "", perm1[4*i], op1, perm2[4*i], op2, perm3[4*i]);
  391. printf(" n = R(lf[%d]);", 4*i+1);
  392. if (++w < CRYPT_BLOCK_SIZE/BYTES_PER_WORD)
  393. printf(" b[%d] = mix[n];", w);
  394. op1 = op(); op2 = op();
  395. printf(" mix[n] = %s(lf[%d] %s S(lf[%d])) %s T(lf[%d]);\n",
  396. (w&1) ? "~" : "", perm1[4*i+1], op1,
  397. perm2[4*i+1], op2, perm3[4*i+1]);
  398. printf(" n = R(lf[%d]);", 4*i+2);
  399. if (++w < CRYPT_BLOCK_SIZE/BYTES_PER_WORD)
  400. printf(" b[%d] = mix[n];", w);
  401. op1 = op(); op2 = op();
  402. printf(" mix[n] = %s(lf[%d] %s S(lf[%d])) %s T(lf[%d]);\n",
  403. (w&1) ? "~" : "", perm1[4*i+2], op1,
  404. perm2[4*i+2], op2, perm3[4*i+2]);
  405. }
  406. if (w < CRYPT_BLOCK_SIZE/BYTES_PER_WORD)
  407. { printf("*** SHIFT_REGISTER_LENGTH (=%d) is too short ***\n",
  408. SHIFT_REGISTER_LENGTH);
  409. printf("*** given CRYPT_BLOCK_SIZE = %d ***\n", CRYPT_BLOCK_SIZE);
  410. exit(1);
  411. }
  412. printf("/* The test this way around favours Intel etc byte order */\n");
  413. printf(" if (((unsigned int *)byte_order_test)[0] != 1)\n");
  414. printf(" { int i;\n");
  415. printf(" for (i=0; i<%d; i++)\n", CRYPT_BLOCK_SIZE/BYTES_PER_WORD);
  416. printf(" { unsigned%d w = b[i];\n", WORD_LENGTH);
  417. printf(" unsigned%d b0, b1, b2, b3;\n", WORD_LENGTH);
  418. if (WORD_LENGTH == 64)
  419. printf(" unsigned%d b4, b5, b6, b7;\n", WORD_LENGTH);
  420. if (WORD_LENGTH == 32)
  421. { printf(" b0 = (w >> 24) & 0xffU;\n");
  422. printf(" b1 = (w >> 8) & 0xff00U;\n");
  423. printf(" b2 = (w << 8) & 0xff0000U;\n");
  424. printf(" b3 = (w << 24) & 0xff000000U;\n");
  425. printf(" b[i] = b0 | b1 | b2 | b3;\n");
  426. }
  427. else
  428. { char *suffix = "LU";
  429. /*
  430. * The following line is a messy cop-out, but is mainly here as a WARNING
  431. * that to support 64-bit arithmetic MIGHT sometimes need non-standard
  432. * code.
  433. */
  434. if (strcmp(UNSIGNED_TYPE, "unsigned long long int") == 0)
  435. suffix = "LLU";
  436. printf(" b0 = (w >> 56) & 0xff%s;\n", suffix);
  437. printf(" b1 = (w >> 40) & 0xff00%s;\n", suffix);
  438. printf(" b2 = (w >> 24) & 0xff0000%s;\n", suffix);
  439. printf(" b3 = (w >> 8) & 0xff000000%s;\n", suffix);
  440. printf(" b4 = (w << 8) & 0xff00000000%s;\n", suffix);
  441. printf(" b5 = (w << 24) & 0xff0000000000%s;\n", suffix);
  442. printf(" b6 = (w << 40) & 0xff000000000000%s;\n", suffix);
  443. printf(" b7 = (w << 56) & 0xff00000000000000%s;\n", suffix);
  444. printf(" b[i] = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7;\n");
  445. }
  446. printf(" }\n");
  447. printf(" }\n");
  448. printf(" return;\n}\n\n");
  449. printf("void crypt_init(char *key)\n{\n");
  450. printf(" char *pk = key;\n");
  451. printf(" unsigned char junk[CRYPT_BLOCK_SIZE];\n");
  452. printf(" int i, j;\n");
  453. printf(" unsigned%d w = 0;\n", WORD_LENGTH);
  454. printf(" for (i=0; i<%d; i++)\n", BYTES_PER_WORD*len);
  455. printf(" { int k = *pk++;\n");
  456. printf(" if (k == 0) pk = key;");
  457. printf(" /* Cycle key (inc. terminating 0) */\n");
  458. printf(" w = (w << 8) | (k & 0xff);\n");
  459. printf(" if ((i %% %d) == %d) lf[i/%d] = w;\n",
  460. BYTES_PER_WORD, BYTES_PER_WORD-1, BYTES_PER_WORD);
  461. printf(" }\n");
  462. printf(" for (i=0; i<%d; i++) mix[i] = 0;\n", shuffle);
  463. printf(" for (i=0; i<8; i++)\n");
  464. printf(" { for (j=0; j<%d; j++)\n", len);
  465. printf(" lf[j] = (lf[j] << 10) | (lf[j] >> %d);\n",
  466. WORD_LENGTH-10);
  467. printf(" lf[0] |= 1;\n");
  468. printf(" for (j=0; j<64; j++)\n");
  469. printf(" crypt_get_block(junk);\n");
  470. printf(" }\n");
  471. printf(" for (i=0; i<%d;)\n", shuffle);
  472. printf(" { int j;\n");
  473. printf(" crypt_get_block(junk);\n");
  474. printf(" for (j=0; j<%d; j++)\n", CRYPT_BLOCK_SIZE/BYTES_PER_WORD);
  475. printf(" { unsigned%d r = junk[%d*j];\n", WORD_LENGTH, BYTES_PER_WORD);
  476. printf(" r = (r << 8) | junk[%d*j+1];\n", BYTES_PER_WORD);
  477. printf(" r = (r << 8) | junk[%d*j+2];\n", BYTES_PER_WORD);
  478. printf(" r = (r << 8) | junk[%d*j+3];\n", BYTES_PER_WORD);
  479. if (WORD_LENGTH == 64)
  480. { printf(" r = (r << 8) | junk[%d*j+4];\n", BYTES_PER_WORD);
  481. printf(" r = (r << 8) | junk[%d*j+5];\n", BYTES_PER_WORD);
  482. printf(" r = (r << 8) | junk[%d*j+6];\n", BYTES_PER_WORD);
  483. printf(" r = (r << 8) | junk[%d*j+7];\n", BYTES_PER_WORD);
  484. }
  485. printf(" if (r == 0) continue;\n");
  486. printf(" mix[i++] ^= junk[j];\n");
  487. printf(" if (i == %d) break;\n", shuffle);
  488. printf(" }\n");
  489. printf(" }\n");
  490. printf(" for (i=0; i<%d; i++)\n",
  491. (3*BYTES_PER_WORD*shuffle)/(2*CRYPT_BLOCK_SIZE));
  492. printf(" crypt_get_block(junk);\n");
  493. printf(" return;\n");
  494. printf("}\n\n");
  495. printf("#ifdef TIME_TEST\n");
  496. printf("/*\n");
  497. printf(" * The main program here does not do anything of real interest. It\n");
  498. printf(" * runs both the key-setup and the main loop lots of times and reports\n");
  499. printf(" * how long it all takes.\n");
  500. printf(" *\n");
  501. #if SHIFT_REGISTER_LENGTH==65 && SHUFFLE_BUFFER_SIZE==4096 && WORD_LENGTH==32
  502. printf(" * Here is some sample output from a Pentium-II 400Mhz system\n");
  503. printf(" *\n");
  504. printf(" * [02faf080] 7.60 nanoseconds to do tiny loop\n");
  505. printf(" * 1.25 milliseconds to startup\n");
  506. printf(" * rate = 104.86 megabytes per second\n");
  507. printf(" * 79 a7 e1 52 2e 84 09 ce d0 3d 45 b2 52 2d b6 c7\n");
  508. printf(" * 9b ee 57 25 68 58 b7 44 42 51 1c c7 de 69 0f 89\n");
  509. printf(" * 98 6c cd 45 e0 a1 d4 04 a3 be 3d 5f 93 64 c9 d9\n");
  510. printf(" * b9 47 28 59 d0 99 5a 35 56 fd 89 e6 48 4f a4 88\n");
  511. printf(" * 7e dd 31 76 2b 8e 96 fa d0 6f d7 30 9c 3c 01 97\n");
  512. printf(" * 8a 54 93 c0 02 1d 26 df 31 2b 7b 92 56 51 fa 47\n");
  513. printf(" * 92 13 39 47 45 d2 b5 33 2b f6 cc 62 ec 73 00 40\n");
  514. printf(" * 66 ab 37 f5 1d 21 3a a9 b8 da 35 ac 04 f1 3b 53\n");
  515. printf(" *\n");
  516. #endif
  517. printf(" */\n");
  518. printf("\n");
  519. printf("int main(int argc, char *argv[])\n");
  520. printf("{\n");
  521. printf(" clock_t c0, c1;\n");
  522. printf(" unsigned char r[CRYPT_BLOCK_SIZE];\n");
  523. printf(" int i, j = 0;\n");
  524. printf(" double rate;\n");
  525. printf(" c0 = clock();\n");
  526. printf(" for (i=0; i<(NTINY+1); i++) j ^= i;\n");
  527. printf(" c1 = clock();\n");
  528. printf(" printf(\"[%%.8x] %%.2f nanoseconds to do tiny loop\\n\", j,\n");
  529. printf(" 1.0e9*(double)(c1-c0)/((double)CLOCKS_PER_SEC*(double)(NTINY+1)));\n");
  530. printf(" c0 = clock();\n");
  531. printf(" for (i=0; i<NSTARTS; i++) crypt_init(KEY);\n");
  532. printf(" c1 = clock();\n");
  533. printf(" printf(\"%%.2f milliseconds to startup\\n\",\n");
  534. printf(" 1000.0*(double)(c1-c0)/((double)CLOCKS_PER_SEC*(double)NSTARTS));\n");
  535. printf(" c0 = clock();\n");
  536. printf(" for (i=0; i<N; i++) crypt_get_block(r);\n");
  537. printf(" c1 = clock();\n");
  538. printf(" rate = (double)N*(double)CRYPT_BLOCK_SIZE*(double)CLOCKS_PER_SEC/\n");
  539. printf(" ((double)(c1-c0)*1.0e6);\n");
  540. printf(" printf(\"rate = %%.2f megabytes per second\\n\", rate);\n");
  541. printf(" for (i=0; i<128; i++)\n");
  542. printf(" { printf(\"%%.2x \", r[i]);\n");
  543. printf(" if ((i %% 16) == 15) printf(\"\\n\");\n");
  544. printf(" }\n");
  545. printf(" return 0;\n");
  546. printf("}\n\n");
  547. printf("#endif /* TIME_TEST */\n\n");
  548. printf("#undef R\n");
  549. printf("#undef S\n");
  550. printf("#undef T\n\n");
  551. return 0;
  552. }
  553. /* end of gencry.c */