bntest16.c
上传用户:zbbssh
上传日期:2007-01-08
资源大小:196k
文件大小:21k
源码类别:

CA认证

开发平台:

C/C++

  1. /*
  2.  * Test driver for low-level bignum library (16-bit version).
  3.  * This access the low-level library directly.  It is NOT an
  4.  * example of how to program with the library normally!  By
  5.  * accessing the library at a low level, it is possible to
  6.  * exercise the smallest components and thus localize bugs
  7.  * more accurately.  This is especially useful when writing
  8.  * assembly-language primitives.
  9.  *
  10.  * This also does timing tests on modular exponentiation.
  11.  * Modular exponentiation is so computationally expensive that
  12.  * the fact that this code omits one level of interface glue
  13.  * has no perceptible effect on the results.
  14.  */
  15. #if HAVE_CONFIG_H
  16. #include "config.h"
  17. #endif
  18. #include <stdio.h>
  19. #if !NO_STDLIB_H
  20. #include <stdlib.h> /* For strtol */
  21. #endif
  22. #if !NO_STRING_H
  23. #include <string.h>
  24. #elif HAVE_STRINGS_H
  25. #include <strings.h>
  26. #endif
  27. #if NEED_MEMORY_H
  28. #include <memory.h>
  29. #endif
  30. #include "cputime.h"
  31. #include "lbn16.h"
  32. #include "kludge.h"
  33. /* Work with up to 2048-bit numbers */
  34. #define MAXBITS 2048
  35. #define SIZE (MAXBITS/16 + 1)
  36. /* Additive congruential random number generator, x[i] = x[i-24] + x[i-55] */
  37. static BNWORD16 randp[55];
  38. static BNWORD16 *randp1 = randp, *randp2 = randp+24;
  39. static BNWORD16
  40. rand16(void)
  41. {
  42.         if (++randp2 == randp+55) {
  43.                 randp2 = randp;
  44.                 randp1++;
  45.         } else if (++randp1 == randp+55) {
  46.                 randp1 = randp;
  47.         }
  48.         return  *randp1 += *randp2;
  49. }
  50. /*
  51.  * CRC-3_2: x^3_2+x^26+x^23+x^22+x^1_6+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
  52.  *
  53.  * The additive congruential RNG is seeded with a single integer,
  54.  * which is shuffled with a CRC polynomial to generate the initial
  55.  * table values.  The Polynomial is the same size as the words being
  56.  * used.
  57.  *
  58.  * Thus, in the various versions of this library, we actually use this
  59.  * polynomial as-is, this polynomial mod x^17, and this polynomial with
  60.  * the leading coefficient deleted and replaced with x^6_4.  As-is,
  61.  * it's irreducible, so it has a long period.  Modulo x^17, it factors as
  62.  * (x^4+x^3+x^2+x+1) * (x^12+x^11+x^8+x^7+x^6+x^5+x^4+x^3+1),
  63.  * which still has a large enough period (4095) for the use it's put to.
  64.  * With the leading coefficient moved up, it factors as
  65.  * (x^50+x^49+x^48+x^47+x^46+x^43+x^41+x^40+x^38+x^37+x^36+x^35+x^34+x^33+
  66.  *  x^31+x^30+x^29+x^28+x^27+x^25+x^23+x^18+x^1_6+x^15+x^14+x^13+x^11+x^9+
  67.  *  x^8+x^7+x^6+x^5+x^3+x^2+1)*(x^11+x^10+x^9+x^5+x^4+x^3+1)*(x^3+x+1),
  68.  * which definitely has a long enough period to serve for initialization.
  69.  * 
  70.  * The effort put into this PRNG is kind of unwarranted given the trivial
  71.  * use it's being put to, but oh, well.  It does have the nice advantage
  72.  * of producing numbers that are portable between platforms, so if there's
  73.  * a problem with one platform, you can compare all the intermediate
  74.  * results with another platform.
  75.  */
  76. #define POLY (BNWORD16)0x04c11db7
  77. static void
  78. srand16(BNWORD16 seed)
  79. {
  80.         int i, j;
  81.         for (i = 0; i < 55; i++) {
  82.                 for (j = 0; j < 16; j++)
  83.                         if (seed >> (16-1))
  84.                                 seed = (seed << 1) ^ POLY;
  85.                         else
  86.                                 seed <<= 1;
  87.                 randp[i] = seed;
  88.         }
  89.         for (i = 0; i < 3*55; i ++)
  90.                 rand16();
  91. }
  92. static void
  93. randnum(BNWORD16 *num, unsigned len)
  94. {
  95.         while (len--)
  96.                 BIGLITTLE(*--num,*num++) = rand16();
  97. }
  98. static void
  99. bnprint16(BNWORD16 const *num, unsigned len)
  100. {
  101.         BIGLITTLE(num -= len, num += len);
  102.         while (len--)
  103.                 printf("%0*lX", 16/4, (unsigned long)BIGLITTLE(*num++,*--num));
  104. }
  105. static void
  106. bnput16(char const *prompt, BNWORD16 const *num, unsigned len)
  107. {
  108.         fputs(prompt, stdout);
  109.         bnprint16(num, len);
  110.         putchar('n');
  111. }
  112. /*
  113.  * One of our tests uses a known prime.  The following selections were
  114.  * taken from the tables at the end of Hans Reisel's "Prime Numbers and
  115.  * Computer Methods for Factorization", second edition - an excellent book.
  116.  * (ISBN 0-8176-3743-5 ISBN 3-7643-3743-5)
  117.  */
  118. #if 0
  119. /* P31=1839605 17620282 38179967 87333633 from the factors of 3^256+2^256 */
  120. static unsigned char const prime[] = {
  121.         0x17,0x38,0x15,0xBC,0x8B,0xBB,0xE9,0xEF,0x01,0xA9,0xFD,0x3A,0x01
  122. };
  123. #elif 0
  124. /* P48=40554942 04557502 46193993 36199835 4279613_2 73199617 from the same */
  125. static unsigned char const prime[] = {
  126.         0x47,0x09,0x77,0x07,0xCF,0xFD,0xE1,0x54,0x3E,0x24,
  127.         0xF7,0xF1,0x7A,0x3E,0x91,0x51,0xCC,0xC7,0xD4,0x01
  128. };
  129. #elif 0
  130. /*
  131.  * P75 = 450 55287640 97906895 47687014 5808213_2
  132.  *  05219565 99525911 39967964 66003_258 91979521
  133.  * from the factors of 4^128+3+128
  134.  * (The "026" and "062" are to prevent a Bad String from appearing here.)
  135.  */
  136. static unsigned char const prime[] = {
  137. 0xFF,0x00,0xFF,0x00,0xFF,0x01,0x06,0x4F,0xF8,0xED,
  138. 0xA3,0x37,0x23,0x2A,0x04,0xEA,0xF9,0x5F,0x30,0x4C,
  139. 0xAE,0xCD, 026,0x4E, 062,0x10,0x04,0x7D,0x0D,0x79,
  140. 0x01
  141. };
  142. #else
  143. /*
  144.  * P75 = 664 85659796 45277755 9123_2190 67300940
  145.  *  51844953 78793489 59444670 35675855 57440257
  146.  * from the factors of 5^128+4^128
  147.  * (The "026" is to prevent a Bad String from appearing here.)
  148.  */
  149. static unsigned char const prime[] = {
  150. 0x01,0x78,0x4B,0xA5,0xD3,0x30,0x03,0xEB,0x73,0xE6,
  151. 0x0F,0x4E,0x31,0x7D,0xBC,0xE2,0xA0,0xD4, 026,0x3F,
  152. 0x3C,0xEA,0x1B,0x44,0xAD,0x39,0xE7,0xE5,0xAD,0x19,
  153. 0x67,0x01
  154. };
  155. #endif
  156. static int
  157. usage(char const *name)
  158. {
  159.         fprintf(stderr, "Usage: %s [modbits [expbits [expbits2]]n"
  160. "With no arguments, just runs test suite.  If modbits is given, runsn"
  161. "quick validation test, then runs timing tests of modular exponentiation.n"
  162. "If expbits is given, it is used as an exponent size, otherwise it defaultsn"
  163. "to the same as modbits.  If expbits2 is given it is used as the secondn"
  164. "exponent size in the double-exponentiation tests, otherwise it defaultsn"
  165. "to the same as expbits.  All are limited to %u bits.n",
  166.                 name, (unsigned)MAXBITS);
  167.         return 1;
  168. }
  169. int
  170. main(int argc, char **argv)
  171. {
  172. unsigned i, j, k, l, m;
  173. int z;
  174. BNWORD16 t, carry, borrow;
  175. BNWORD16 a[SIZE], b[SIZE], c[SIZE], d[SIZE];
  176. BNWORD16 e[SIZE], f[SIZE];
  177. long modbits = 0, expbits = 0, expbits2 = 0;
  178. char *p;
  179. #define A BIGLITTLE((a+SIZE),a)
  180. #define B BIGLITTLE((b+SIZE),b)
  181. #define C BIGLITTLE((c+SIZE),c)
  182. #define D BIGLITTLE((d+SIZE),d)
  183. #define E BIGLITTLE((e+SIZE),e)
  184. #define F BIGLITTLE((f+SIZE),f)
  185.         static unsigned const smallprimes[] = {
  186.                 2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 29, 31, 37, 41, 43
  187.         };
  188.         srand16(1);
  189.         puts(BIGLITTLE("Big-endian machine","Little-endian machine"));
  190. /*
  191.  * Parse the command line.  The do{} loop is a dummy, to have
  192.  * something to break out of when done with the command line.
  193.  */
  194. do {
  195. if (argc <= 1)
  196. break;
  197.                 modbits = strtol(argv[1], &p, 0);
  198.                 if (modbits < 3 || modbits > MAXBITS || *p) {
  199.                         fprintf(stderr, "Illegal modbits: "%s"n", argv[1]);
  200.                         return usage(argv[0]);
  201.                 }
  202. if (argc <= 2) {
  203. expbits2 = expbits = modbits;
  204. break;
  205. }
  206. expbits = strtol(argv[2], &p, 0);
  207. if (expbits < 3 || expbits > MAXBITS || *p) {
  208. fprintf(stderr, "Illegal expbits: "%s"n", argv[2]);
  209. return usage(argv[0]);
  210. }
  211. if (argc <= 3) {
  212. expbits2 = expbits;
  213. break;
  214. }
  215. expbits2 = strtol(argv[3], &p, 0);
  216. if (expbits2 < 3 || expbits2 > MAXBITS || *p) {
  217. fprintf(stderr, "Illegal expbits2: "%s"n", argv[3]);
  218. return usage(argv[0]);
  219. }
  220. if (argc <= 4)
  221. break;
  222. fprintf(stderr, "Unexpected fourth argument "%s"n",
  223.         argv[4]);
  224. return usage(argv[0]);
  225. } while (0);
  226.         /* B is a nice not-so-little prime */
  227.         lbnInsertBigBytes_16(B, prime, 0, sizeof(prime));
  228.         ((unsigned char *)c)[0] = 0;
  229.         lbnInsertBigBytes_16(B, (unsigned char *)c, sizeof(prime), 1);
  230.         lbnExtractBigBytes_16(B, (unsigned char *)c, 0, sizeof(prime)+1);
  231.         i = (sizeof(prime)-1)/(16/8)+1;        /* Size of array in words */
  232.         if (((unsigned char *)c)[0] ||
  233.             memcmp(prime, (unsigned char *)c+1, sizeof(prime)) != 0)
  234.         {
  235.                 printf("Input != output!:n   ");
  236.                 for (k = 0; k < sizeof(prime); k++)
  237.                         printf("%02X ", prime[k]);
  238.                 putchar('n');
  239.                 for (k = 0; k < sizeof(prime)+1; k++)
  240.                         printf("%02X ", ((unsigned char *)c)[k]);
  241.                 putchar('n');
  242.                 bnput16("p = ", B, i);
  243.         }
  244.         /* Timing test code - only if requested on the command line */
  245. if (modbits) {
  246. #if CLOCK_AVAIL
  247. timetype start, stop;
  248. unsigned long cursec, expsec, twoexpsec, dblexpsec;
  249. unsigned curms, expms, twoexpms, dblexpms;
  250. expsec = twoexpsec = dblexpsec = 0;
  251. expms = twoexpms = dblexpms = 0;
  252. #endif
  253. lbnCopy_16(C,B,i);
  254. lbnSub1_16(C,i,1);        /* C is exponent: p-1 */
  255. puts("Testing modexp with a known prime.  "
  256.      "All results should be 1.");
  257. bnput16("p   = ", B, i);
  258. bnput16("p-1 = ", C, i);
  259. lbnTwoExpMod_16(A, C, i, B, i);
  260. bnput16("2^(p-1) mod p = ", A, i);
  261. for (j = 0; j < 10; j++) {
  262. randnum(A,i);
  263. (void)lbnDiv_16(D,A,i,B,i);
  264. bnput16("a = ", A, i);
  265. lbnExpMod_16(A, A, i, C, i, B, i);
  266. bnput16("a^(p-1) mod p = ", A, i);
  267. }
  268. printf("n"
  269.        "Timing exponentiations modulo a %d-bit modulus, i.e.n"
  270.        "2^<%d> mod <%d> bits, <%d>^<%d> mod <%d> bits andn"
  271.        "<%d>^<%d> * <%d>^<%d> mod <%d> bitsn",
  272.        (int)modbits, (int)expbits, (int)modbits,
  273.        (int)modbits, (int)expbits, (int)modbits,
  274.        (int)modbits, (int)expbits, (int)modbits, (int)expbits2,
  275.        (int)modbits);
  276. i = ((int)modbits-1)/16+1;
  277. k = ((int)expbits-1)/16+1;
  278. l = ((int)expbits2-1)/16+1;
  279. for (j = 0; j < 25; j++) {
  280. randnum(A,i);        /* Base */
  281. randnum(B,k);        /* Exponent */
  282. randnum(C,i);        /* Modulus */
  283. randnum(D,i);        /* Base2 */
  284. randnum(E,l);        /* Exponent */
  285. /* Clip bases and mod to appropriate number of bits */
  286. t = ((BNWORD16)2<<((modbits-1)%16)) - 1;
  287. *(BIGLITTLE(A-i,A+i-1)) &= t;
  288. *(BIGLITTLE(C-i,C+i-1)) &= t;
  289. *(BIGLITTLE(D-i,D+i-1)) &= t;
  290. /* Make modulus large (msbit set) and odd (lsbit set) */
  291. *(BIGLITTLE(C-i,C+i-1)) |= (t >> 1) + 1;
  292. BIGLITTLE(C[-1],C[0]) |= 1;
  293. /* Clip exponent to appropriate number of bits */
  294. t = ((BNWORD16)2<<((expbits-1)%16)) - 1;
  295. *(BIGLITTLE(B-k,B+k-1)) &= t;
  296. /* Make exponent large (msbit set) */
  297. *(BIGLITTLE(B-k,B+k-1)) |= (t >> 1) + 1;
  298. /* The same for exponent 2 */
  299. t = ((BNWORD16)2<<((expbits2-1)%16)) - 1;
  300. *(BIGLITTLE(E-l,E+l-1)) &= t;
  301. *(BIGLITTLE(E-l,E+l-1)) |= (t >> 1) + 1;
  302. m = lbnBits_16(A, i);
  303. if (m > (unsigned)modbits) {
  304. bnput16("a = ", a, i);
  305. printf("%u bits, should be <= %dn",
  306.        m, (int)modbits);
  307. }
  308. m = lbnBits_16(B, k);
  309. if (m != (unsigned)expbits) {
  310. bnput16("b = ", b, i);
  311. printf("%u bits, should be %dn",
  312.        m, (int)expbits);
  313. }
  314. m = lbnBits_16(C, i);
  315. if (m != (unsigned)modbits) {
  316. bnput16("c = ", c, k);
  317. printf("%u bits, should be %dn",
  318.        m, (int)modbits);
  319. }
  320. m = lbnBits_16(D, i);
  321. if (m > (unsigned)modbits) {
  322. bnput16("d = ", d, i);
  323. printf("%u bits, should be <= %dn",
  324.        m, (int)modbits);
  325. }
  326. m = lbnBits_16(E, l);
  327. if (m != (unsigned)expbits2) {
  328. bnput16("e = ", e, i);
  329. printf("%u bits, should be %dn",
  330.        m, (int)expbits2);
  331. }
  332. #if CLOCK_AVAIL
  333. gettime(&start);
  334. #endif
  335. lbnTwoExpMod_16(A, B, k, C, i);
  336. #if CLOCK_AVAIL
  337. gettime(&stop);
  338. subtime(stop, start);
  339. twoexpsec += cursec = sec(stop);
  340. twoexpms += curms = msec(stop);
  341. printf("2^<%d>:%3lu.%03u   ",
  342.        (int)expbits, cursec, curms);
  343. #else
  344. printf("2^<%d>    ", (int)expbits);
  345. #endif
  346. fflush(stdout);
  347. #if CLOCK_AVAIL
  348. gettime(&start);
  349. #endif
  350. lbnExpMod_16(A, A, i, B, k, C, i);
  351. #if CLOCK_AVAIL
  352. gettime(&stop);
  353. subtime(stop, start);
  354. expsec += cursec = sec(stop);
  355. expms += curms = msec(stop);
  356. printf("<%d>^<%d>:%3lu.%03u   ",
  357.        (int)modbits, (int)expbits, cursec, curms);
  358. #else
  359. printf("<%d>^<%d>    ", (int)modbits, (int)expbits);
  360. #endif
  361. fflush(stdout);
  362. #if CLOCK_AVAIL
  363. gettime(&start);
  364. #endif
  365. lbnDoubleExpMod_16(D, A, i, B, k, D, i, E, l, C, i);
  366. #if CLOCK_AVAIL
  367. gettime(&stop);
  368. subtime(stop, start);
  369. dblexpsec += cursec = sec(stop);
  370. dblexpms += curms = msec(stop);
  371. printf("<%d>^<%d>*<%d>^<%d>:%3lu.%03un",
  372.        (int)modbits, (int)expbits,
  373.        (int)modbits, (int)expbits2,
  374.        cursec, curms);
  375. #else
  376. printf("<%d>^<%d>*<%d>^<%d>n",
  377.        (int)modbits, (int)expbits,
  378.        (int)modbits, (int)expbits2);
  379. #endif
  380. }
  381. #if CLOCK_AVAIL
  382. putchar('n');
  383. twoexpms += 1000 * (unsigned)(twoexpsec % j);
  384. while (twoexpms > 1000*j) {
  385. twoexpsec += j;
  386. twoexpms -= 1000*j;
  387. }
  388. printf("2^<%d> mod <%d> bits AVERAGE: %lu.%03u sn",
  389.        (int)expbits, (int)modbits,
  390.        twoexpsec/j, twoexpms/j);
  391. expms += 1000 * (unsigned)(expsec % j);
  392. while (expms > 1000*j) {
  393. expsec += j;
  394. expms -= 1000*j;
  395. }
  396. printf("<%d>^<%d> mod <%d> bits AVERAGE: %lu.%03u sn",
  397.        (int)modbits, (int)expbits, (int)modbits,
  398.        expsec/j, expms/j);
  399. dblexpms += 1000 * (unsigned)(dblexpsec % j);
  400. while (dblexpms > 1000*j) {
  401. dblexpsec += j;
  402. dblexpms -= 1000*j;
  403. }
  404. printf("<%d>^<%d> * <%d>^<%d> mod <%d> bits AVERAGE:"
  405.        " %lu.%03u sn",
  406.        (int)modbits, (int)expbits, (int)modbits, (int)expbits2,
  407.        (int)modbits, dblexpsec/j, dblexpms/j);
  408. #endif
  409. putchar('n');
  410. }
  411.         puts("Beginning 1000 interations of sanity checking.n"
  412.              "Any output indicates a bug.  No output is very strongn"
  413.              "evidence that all the important low-level bignum routinesn"
  414.              "are working properly.n");
  415. /*
  416.  * If you change this loop to have an iteration 0, all results
  417.  * are primted on that iteration.  Useful to see what's going
  418.  * on in case of major wierdness, but it produces a *lot* of
  419.  * output.
  420.  */
  421.         for (j = 1; j <= 1000; j++) {
  422. /* Dop the tests for lots of different number sizes. */
  423. for (i = 1; i <= SIZE/2; i++) {
  424. /* Make a random number i words long */
  425. do {
  426. randnum(A,i);
  427. } while (lbnNorm_16(A,i) < i);
  428. /* Checl lbnCmp - does a == a? */
  429. if (lbnCmp_16(A,A,i) || !j) {
  430. bnput16("a = ", A, i);
  431. printf("(a <=> a) = %dn", lbnCmp_16(A,A,i));
  432. }
  433. memcpy(c, a, sizeof(a));
  434. /* Check that the difference, after copy, is good. */
  435. if (lbnCmp_16(A,C,i) || !j) {
  436. bnput16("a = ", A, i);
  437. bnput16("c = ", C, i);
  438. printf("(a <=> c) = %dn", lbnCmp_16(A,C,i));
  439. }
  440. /* Generate a non-zero random t */
  441. do {
  442. t = rand16();
  443. } while (!t);
  444. /*
  445.  * Add t to A.  Check that:
  446.  * - lbnCmp works in both directions, and
  447.  * - A + t is greater than A.  If there was a carry,
  448.  *   the result, less the carry, should be *less*
  449.  *   than A.
  450.  */
  451. carry = lbnAdd1_16(A,i,t);
  452. if (lbnCmp_16(A,C,i) + lbnCmp_16(C,A,i) != 0 ||
  453.     lbnCmp_16(A,C,i) != (carry ? -1 : 1) || !j)
  454. {
  455. bnput16("c       = ", C, i);
  456. printf("t = %lXn", (unsigned long)t);
  457. bnput16("a = c+t = ", A, i);
  458. printf("carry = %lXn", (unsigned long)carry);
  459. printf("(a <=> c) = %dn", lbnCmp_16(A,C,i));
  460. printf("(c <=> a) = %dn", lbnCmp_16(C,A,i));
  461. }
  462. /* Subtract t again */
  463. memcpy(d, a, sizeof(a));
  464. borrow = lbnSub1_16(A,i,t);
  465. if (carry != borrow || lbnCmp_16(A,C,i) || !j) {
  466. bnput16("a = ", C, i);
  467. printf("t = %lXn", (unsigned long)t);
  468. lbnAdd1_16(A,i,t);
  469. bnput16("a += t = ", A, i);
  470. printf("Carry = %lXn", (unsigned long)carry);
  471. lbnSub1_16(A,i,t);
  472. bnput16("a -= t = ", A, i);
  473. printf("Borrow = %lXn", (unsigned long)borrow);
  474. printf("(a <=> c) = %dn", lbnCmp_16(A,C,i));
  475. }
  476. /* Generate a random B */
  477. do {
  478. randnum(B,i);
  479. } while (lbnNorm_16(B,i) < i);
  480. carry = lbnAddN_16(A,B,i);
  481. memcpy(d, a, sizeof(a));
  482. borrow = lbnSubN_16(A,B,i);
  483. if (carry != borrow || lbnCmp_16(A,C,i) || !j) {
  484. bnput16("a = ", C, i);
  485. bnput16("b = ", B, i);
  486. bnput16("a += b = ", D, i);
  487. printf("Carry = %lXn", (unsigned long)carry);
  488. bnput16("a -= b = ", A, i);
  489. printf("Borrow = %lXn", (unsigned long)borrow);
  490. printf("(a <=> c) = %dn", lbnCmp_16(A,C,i));
  491. }
  492. /* D = B * t */
  493. lbnMulN1_16(D, B, i, t);
  494. memcpy(e, d, sizeof(a));
  495. carry = *(BIGLITTLE(D-i-1,D+i));
  496. /* D = A + B * t */
  497. carry = lbnAddN_16(D,A,i);
  498. /* For comparison with the result of lbnMulAdd1_16 */
  499. borrow = carry + *(BIGLITTLE(D-i-1,D+i));
  500. *(BIGLITTLE(A-i-1,A+i)) = 0;
  501. carry = lbnMulAdd1_16(A, B, i, t);
  502. /* Did MulAdd get the same answer as mul then add? */
  503. if (carry != borrow || lbnCmp_16(A, D, i) || !j) {
  504. bnput16("a = ", C, i);
  505. bnput16("b = ", B, i);
  506. printf("t = %lXn", (unsigned long)t);
  507. bnput16("e = b * t = ", E, i+1);
  508. bnput16("a + e = ", D, i);
  509. printf("carry = %lXn", (unsigned long)borrow);
  510. bnput16("a + b * t = ", A, i);
  511. printf("carry = %lXn", (unsigned long)carry);
  512. }
  513. memcpy(d, a, sizeof(a));
  514. borrow = lbnMulSub1_16(A, B, i, t);
  515. /* Did MulSub perform the inverse of MulAdd */
  516. if (carry != borrow || lbnCmp_16(A,C,i) || !j) {
  517. bnput16("a = ", C, i);
  518. bnput16("b = ", B, i);
  519. bnput16("a += b*t = ", D, i+1);
  520. printf("Carry = %lXn", (unsigned long)carry);
  521. bnput16("a -= b*t = ", A, i+1);
  522. printf("Borrow = %lXn", (unsigned long)borrow);
  523. printf("(a <=> c) = %dn", lbnCmp_16(A,C,i));
  524. bnput16("b*t = ", E, i+1);
  525. }
  526. /* At this point we're done with t, so it's scratch */
  527. /* Does Mul work both ways symmetrically */
  528. lbnMul_16(C,A,i,B,i);
  529. lbnMul_16(D,B,i,A,i);
  530. if (lbnCmp_16(C,D,i+i) || !j) {
  531. bnput16("a = ", A, i);
  532. bnput16("b = ", B, i);
  533. bnput16("a * b = ", C, i+i);
  534. bnput16("b * a = ", D, i+i);
  535. printf("(a*b <=> b*a) = %dn",
  536.        lbnCmp_16(C,D,i+i));
  537. }
  538. /* Generate an F less than A and B */
  539. do {
  540. randnum(F,i);
  541. } while (lbnCmp_16(F,A,i) >= 0 ||
  542.          lbnCmp_16(F,B,i) >= 0);
  543. /* Add F to D */
  544. lbnAdd1_16(BIGLITTLE(D-i,D+i), i, lbnAddN_16(D, F, i));
  545. memcpy(c, d, sizeof(d));
  546. /*
  547.  * Divide by A and check that quotient and remainder
  548.  * match
  549.  */
  550. t = lbnDiv_16(E,C,i+i,A,i);
  551. if (t || lbnCmp_16(E,B,i) || lbnCmp_16(C, F, i) || !j) {
  552. bnput16("a = ", A, i);
  553. bnput16("b = ", B, i);
  554. bnput16("f = ", F, i);
  555. bnput16("a * b + f = ", D, i+i);
  556. printf("qhigh = %lXn", (unsigned long)t);
  557. bnput16("(a*b+f) / a = ", E, i);
  558. bnput16("(a*b+f) % a = ", C, i);
  559. }
  560. memcpy(c, d, sizeof(d));
  561. /* Divide by B and check similarly */
  562. t = lbnDiv_16(E,C,i+i,B,i);
  563. if (lbnCmp_16(E,A,i) || lbnCmp_16(C, F, i) || !j) {
  564. bnput16("a = ", A, i);
  565. bnput16("b = ", B, i);
  566. bnput16("f = ", F, i);
  567. bnput16("a * b + f = ", D, i+i);
  568. printf("qhigh = %lXn", (unsigned long)t);
  569. bnput16("(a*b+f) / b = ", E, i);
  570. bnput16("(a*b+f) % b = ", C, i);
  571. }
  572. /* Checl that multiply and square do the same thing */
  573. lbnMul_16(C,A,i,A,i);
  574. lbnSquare_16(D,A,i);
  575. if (lbnCmp_16(C,D,i+i) || !j) {
  576. bnput16("a*a = ", C, i+i);
  577. bnput16("a^2 = ", D, i+i);
  578. printf("(a * a == a^2) = %dn",
  579.        lbnCmp_16(C,D,i+i));
  580. }
  581. /* Compute a GCD */
  582. lbnCopy_16(C,A,i);
  583. lbnCopy_16(D,B,i);
  584. z = lbnGcd_16(C,i,D,i);
  585. /* Approximate check that the GCD came out right */
  586. for (l = 0;
  587.      l < sizeof(smallprimes)/sizeof(*smallprimes);
  588.      l++)
  589. {
  590. t = lbnModQ_16(z > 0 ? C : D,
  591.                (unsigned)(z > 0 ? z : -z),
  592.        smallprimes[l]);
  593. carry = lbnModQ_16(A, i, smallprimes[l]);
  594. borrow = lbnModQ_16(B, i, smallprimes[l]);
  595. if (!t != (!carry && !borrow)) {
  596. bnput16("a = ", A, i);
  597. printf("a mod %u = %lun",
  598.        smallprimes[l],
  599.        (unsigned long)carry);
  600. bnput16("b = ", B, i);
  601. printf("b mod %u = %lun",
  602.        smallprimes[l],
  603.        (unsigned long)borrow);
  604. bnput16("gcd(a,b) = ", z > 0 ? C : D,
  605. (unsigned)(z > 0 ? z : -z));
  606. printf("gcd(a,b) mod %u = %lun",
  607.        smallprimes[l],
  608.        (unsigned long)t);
  609. }
  610. }
  611. /*
  612.  * Do some Montgomery operations
  613.  * Start with A > B, and also place a copy of B
  614.  * into C.
  615.  */
  616. if (lbnCmp_16(A, B, i) < 0) {
  617. memcpy(c, a, sizeof(c));
  618. memcpy(a, b, sizeof(a));
  619. memcpy(b, c, sizeof(b));
  620. } else {
  621. memcpy(c, b, sizeof(c));
  622. }
  623. /* Convert to and from */
  624. BIGLITTLE(A[-1],A[0]) |= 1;
  625. lbnToMont_16(B, i, A, i);
  626. lbnFromMont_16(B, A, i);
  627. if (lbnCmp_16(B, C, i)) {
  628. memcpy(b, c, sizeof(c));
  629. bnput16("mod = ", A, i);
  630. bnput16("input = ", B, i);
  631. lbnToMont_16(B, i, A, i);
  632. bnput16("mont = ", B, i);
  633. lbnFromMont_16(B, A, i);
  634. bnput16("output = ", B, i);
  635. }
  636. /* E = B^5 (mod A), the simple way */
  637. lbnSquare_16(E, B, i);
  638. (void)lbnDiv_16(BIGLITTLE(E-i,E+i),E,i+i,A,i);
  639. lbnSquare_16(D, E, i);
  640. (void)lbnDiv_16(BIGLITTLE(D-i,D+i),D,i+i,A,i);
  641. lbnMul_16(E, D, i, B, i);
  642. (void)lbnDiv_16(BIGLITTLE(E-i,E+i),E,i+i,A,i);
  643. /* D = B^5, using ExpMod */
  644. BIGLITTLE(F[-1],F[0]) = 5;
  645. lbnExpMod_16(D, B, i, F, 1, A, i);
  646. if (lbnCmp_16(D, E, i)  || !j) {
  647. bnput16("mod = ", A, i);
  648. bnput16("input = ", B, i);
  649. bnput16("input^5 = ", E, i);
  650. bnput16("input^5 = ", D, i);
  651. printf("a>b (x <=> y) = %dn",
  652.        lbnCmp_16(D,E,i));
  653. }
  654. /* TODO: Test lbnTwoExpMod, lbnDoubleExpMod */
  655. } /* for (i) */
  656. printf("r%d ", j);
  657. fflush(stdout);
  658.         } /* for (j) */
  659.         printf("%d iterations of up to %d 16-bit words completed.n",
  660.        j-1, i-1);
  661.         return 0;
  662. }