gencry.c 24 KB

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