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

CA认证

开发平台:

C/C++

  1. /*
  2.  * bn16.c - the high-level bignum interface
  3.  *
  4.  * Like lbn16.c, this reserves the string "16" for textual replacement.
  5.  * The string must not appear anywhere unless it is intended to be replaced
  6.  * to generate other bignum interface functions.
  7.  *
  8.  * Copyright (c) 1995  Colin Plumb.  All rights reserved.
  9.  * For licensing and other legal details, see the file legal.c.
  10.  */
  11. #if HAVE_CONFIG_H
  12. #include "config.h"
  13. #endif
  14. #if !NO_ASSERT_H
  15. #include <assert.h>
  16. #else
  17. #define assert(x) (void)0
  18. #endif
  19. #if !NO_STRING_H
  20. #include <string.h> /* for memmove() in bnMakeOdd */
  21. #elif HAVE_STRINGS_H
  22. #include <strings.h>
  23. #endif
  24. /*
  25.  * This was useful during debugging, so it's left in here.
  26.  * You can ignore it.  DBMALLOC is generally undefined.
  27.  */
  28. #if DBMALLOC
  29. #include "../dbmalloc/malloc.h"
  30. #define MALLOCDB malloc_chain_check(1)
  31. #else
  32. #define MALLOCDB (void)0
  33. #endif
  34. #include "lbn.h"
  35. #include "lbn16.h"
  36. #include "lbnmem.h"
  37. #include "bn16.h"
  38. #include "bn.h"
  39. #include "kludge.h" /* For memmove() */
  40. /* Functions */
  41. void
  42. bnInit_16(void)
  43. {
  44. bnEnd = bnEnd_16;
  45. bnPrealloc = bnPrealloc_16;
  46. bnCopy = bnCopy_16;
  47. bnNorm = bnNorm_16;
  48. bnExtractBigBytes = bnExtractBigBytes_16;
  49. bnInsertBigBytes = bnInsertBigBytes_16;
  50. bnExtractLittleBytes = bnExtractLittleBytes_16;
  51. bnInsertLittleBytes = bnInsertLittleBytes_16;
  52. bnLSWord = bnLSWord_16;
  53. bnBits = bnBits_16;
  54. bnAdd = bnAdd_16;
  55. bnSub = bnSub_16;
  56. bnSetQ = bnSetQ_16;
  57. bnAddQ = bnAddQ_16;
  58. bnSubQ = bnSubQ_16;
  59. bnCmp = bnCmp_16;
  60. bnSquare = bnSquare_16;
  61. bnMul = bnMul_16;
  62. bnMulQ = bnMulQ_16;
  63. bnDivMod = bnDivMod_16;
  64. bnMod = bnMod_16;
  65. bnModQ = bnModQ_16;
  66. bnExpMod = bnExpMod_16;
  67. bnDoubleExpMod = bnDoubleExpMod_16;
  68. bnTwoExpMod = bnTwoExpMod_16;
  69. bnGcd = bnGcd_16;
  70. bnInv = bnInv_16;
  71. bnLShift = bnLShift_16;
  72. bnRShift = bnRShift_16;
  73. bnMakeOdd = bnMakeOdd_16;
  74. }
  75. void
  76. bnEnd_16(struct BigNum *bn)
  77. {
  78. if (bn->ptr) {
  79. LBNFREE((BNWORD16 *)bn->ptr, bn->allocated);
  80. bn->ptr = 0;
  81. }
  82. bn->size = 0;
  83. bn->allocated = 0;
  84. MALLOCDB;
  85. }
  86. /* Internal function.  It operates in words. */
  87. static int
  88. bnResize_16(struct BigNum *bn, unsigned len)
  89. {
  90. void *p;
  91. /* Round size up: most mallocs impose 8-byte granularity anyway */
  92. len = (len + (8/sizeof(BNWORD16) - 1)) & ~(8/sizeof(BNWORD16) - 1);
  93. p = LBNREALLOC((BNWORD16 *)bn->ptr, bn->allocated, len);
  94. if (!p)
  95. return -1;
  96. bn->ptr = p;
  97. bn->allocated = len;
  98. MALLOCDB;
  99. return 0;
  100. }
  101. #define bnSizeCheck(bn, size) 
  102. if (bn->allocated < size && bnResize_16(bn, size) < 0) 
  103. return -1
  104. int
  105. bnPrealloc_16(struct BigNum *bn, unsigned bits)
  106. {
  107. bits = (bits + 16-1)/16;
  108. bnSizeCheck(bn, bits);
  109. MALLOCDB;
  110. return 0;
  111. }
  112. int
  113. bnCopy_16(struct BigNum *dest, struct BigNum const *src)
  114. {
  115. bnSizeCheck(dest, src->size);
  116. dest->size = src->size;
  117. lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, src->size);
  118. MALLOCDB;
  119. return 0;
  120. }
  121. void
  122. bnNorm_16(struct BigNum *bn)
  123. {
  124. bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, bn->size);
  125. }
  126. /*
  127.  * Convert a bignum to big-endian bytes.  Returns, in big-endian form, a
  128.  * substring of the bignum starting from lsbyte and "len" bytes long.
  129.  * Unused high-order (leading) bytes are filled with 0.
  130.  */
  131. void
  132. bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest,
  133.                   unsigned lsbyte, unsigned len)
  134. {
  135. unsigned s = bn->size * (16 / 8);
  136. /* Fill unused leading bytes with 0 */
  137. while (s < lsbyte+len) {
  138. *dest++ = 0;
  139. len--;
  140. }
  141. if (len)
  142. lbnExtractBigBytes_16((BNWORD16 *)bn->ptr, dest, lsbyte, len);
  143. MALLOCDB;
  144. }
  145. int
  146. bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src,
  147.                  unsigned lsbyte, unsigned len)
  148. {
  149. unsigned s = bn->size;
  150. unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16);
  151. /* Pad with zeros as required */
  152. bnSizeCheck(bn, words);
  153. if (s < words) {
  154. lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s);
  155. s = words;
  156. }
  157. lbnInsertBigBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len);
  158. bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s);
  159. MALLOCDB;
  160. return 0;
  161. }
  162. /*
  163.  * Convert a bignum to little-endian bytes.  Returns, in little-endian form, a
  164.  * substring of the bignum starting from lsbyte and "len" bytes long.
  165.  * Unused high-order (trailing) bytes are filled with 0.
  166.  */
  167. void
  168. bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest,
  169.                   unsigned lsbyte, unsigned len)
  170. {
  171. unsigned s = bn->size * (16 / 8);
  172. /* Fill unused leading bytes with 0 */
  173. while (s < lsbyte+len)
  174. dest[--len] = 0;
  175. if (len)
  176. lbnExtractLittleBytes_16((BNWORD16 *)bn->ptr, dest,
  177.                          lsbyte, len);
  178. MALLOCDB;
  179. }
  180. int
  181. bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src,
  182.                        unsigned lsbyte, unsigned len)
  183. {
  184. unsigned s = bn->size;
  185. unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16);
  186. /* Pad with zeros as required */
  187. bnSizeCheck(bn, words);
  188. if (s < words) {
  189. lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s);
  190. s = words;
  191. }
  192. lbnInsertLittleBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len);
  193. bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s);
  194. MALLOCDB;
  195. return 0;
  196. }
  197. /* Return the least-significant word of the input. */
  198. unsigned
  199. bnLSWord_16(struct BigNum const *src)
  200. {
  201. return src->size ? (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)]: 0;
  202. }
  203. unsigned
  204. bnBits_16(struct BigNum const *src)
  205. {
  206. return lbnBits_16((BNWORD16 *)src->ptr, src->size);
  207. }
  208. int
  209. bnAdd_16(struct BigNum *dest, struct BigNum const *src)
  210. {
  211. unsigned s = src->size, d = dest->size;
  212. BNWORD16 t;
  213. if (!s)
  214. return 0;
  215. bnSizeCheck(dest, s);
  216. if (d < s) {
  217. lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d);
  218. dest->size = d = s;
  219. MALLOCDB;
  220. }
  221. t = lbnAddN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
  222. MALLOCDB;
  223. if (t) {
  224. if (d > s) {
  225. t = lbnAdd1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s),
  226.                d-s, t);
  227. MALLOCDB;
  228. }
  229. if (t) {
  230. bnSizeCheck(dest, d+1);
  231. ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
  232. dest->size = d+1;
  233. }
  234. }
  235. return 0;
  236. }
  237. /*
  238.  * dest -= src.
  239.  * If dest goes negative, this produces the absolute value of
  240.  * the difference (the negative of the true value) and returns 1.
  241.  * Otherwise, it returls 0.
  242.  */
  243. int
  244. bnSub_16(struct BigNum *dest, struct BigNum const *src)
  245. {
  246. unsigned s = src->size, d = dest->size;
  247. BNWORD16 t;
  248. if (d < s  &&  d < (s = lbnNorm_16((BNWORD16 *)src->ptr, s))) {
  249. bnSizeCheck(dest, s);
  250. lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d);
  251. dest->size = d = s;
  252. MALLOCDB;
  253. }
  254. if (!s)
  255. return 0;
  256. t = lbnSubN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
  257. MALLOCDB;
  258. if (t) {
  259. if (d > s) {
  260. t = lbnSub1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s),
  261.                d-s, t);
  262. MALLOCDB;
  263. }
  264. if (t) {
  265. lbnNeg_16((BNWORD16 *)dest->ptr, d);
  266. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr,
  267.                         dest->size);
  268. MALLOCDB;
  269. return 1;
  270. }
  271. }
  272. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size);
  273. return 0;
  274. }
  275. int
  276. bnSetQ_16(struct BigNum *dest, unsigned src)
  277. {
  278. if (src) {
  279. bnSizeCheck(dest, 1);
  280. ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD16)src;
  281. dest->size = 1;
  282. } else {
  283. dest->size = 0;
  284. }
  285. return 0;
  286. }
  287. int
  288. bnAddQ_16(struct BigNum *dest, unsigned src)
  289. {
  290. BNWORD16 t;
  291. if (!dest->size)
  292. return bnSetQ(dest, src);
  293. t = lbnAdd1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src);
  294. MALLOCDB;
  295. if (t) {
  296. src = dest->size;
  297. bnSizeCheck(dest, src+1);
  298. ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
  299. dest->size = src+1;
  300. }
  301. return 0;
  302. }
  303. /*
  304.  * Return value as for bnSub: 1 if subtract underflowed, in which
  305.  * case the return is the negative of the computed value.
  306.  */
  307. int
  308. bnSubQ_16(struct BigNum *dest, unsigned src)
  309. {
  310. BNWORD16 t;
  311. if (!dest->size)
  312. return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
  313. t = lbnSub1_16((BNWORD16 *)dest->ptr, dest->size, src);
  314. MALLOCDB;
  315. if (t) {
  316. /* Underflow. <= 1 word, so do it simply. */
  317. lbnNeg_16((BNWORD16 *)dest->ptr, 1);
  318. dest->size = 1;
  319. return 1;
  320. }
  321. /* Try to normalize?  Needing this is going to be pretty damn rare. */
  322. /* dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); */
  323. return 0;
  324. }
  325. /*
  326.  * Compare two BigNums.  Returns -1. 0 or 1 if a<b, a == b or a>b.
  327.  * a <=> b --> bnCmp(a,b) <=> 0
  328.  */
  329. int
  330. bnCmp_16(struct BigNum const *a, struct BigNum const *b)
  331. {
  332. unsigned s, t;
  333. s = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
  334. t = lbnNorm_16((BNWORD16 *)b->ptr, b->size);
  335. if (s != t)
  336. return s > t ? 1 : -1;
  337. return lbnCmp_16((BNWORD16 *)a->ptr, (BNWORD16 *)b->ptr, s);
  338. }
  339. int
  340. bnSquare_16(struct BigNum *dest, struct BigNum const *src)
  341. {
  342. unsigned s;
  343. BNWORD16 *srcbuf;
  344. s = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
  345. if (!s) {
  346. dest->size = 0;
  347. return 0;
  348. }
  349. bnSizeCheck(dest, 2*s);
  350. if (src == dest) {
  351. LBNALLOC(srcbuf, s);
  352. if (!srcbuf)
  353. return -1;
  354. lbnCopy_16(srcbuf, (BNWORD16 *)src->ptr, s);
  355. lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)srcbuf, s);
  356. LBNFREE(srcbuf, s);
  357. } else {
  358. lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
  359. }
  360. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, 2*s);
  361. MALLOCDB;
  362. return 0;
  363. }
  364. int
  365. bnMul_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
  366. {
  367. unsigned s, t;
  368. BNWORD16 *srcbuf;
  369. s = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
  370. t = lbnNorm_16((BNWORD16 *)b->ptr, b->size);
  371. if (!s || !t) {
  372. dest->size = 0;
  373. return 0;
  374. }
  375. if (a == b)
  376. return bnSquare_16(dest, a);
  377. bnSizeCheck(dest, s+t);
  378. if (dest == a) {
  379. LBNALLOC(srcbuf, s);
  380. if (!srcbuf)
  381. return -1;
  382. lbnCopy_16(srcbuf, (BNWORD16 *)a->ptr, s);
  383. lbnMul_16((BNWORD16 *)dest->ptr, srcbuf, s,
  384.                                  (BNWORD16 *)b->ptr, t);
  385. LBNFREE(srcbuf, s);
  386. } else if (dest == b) {
  387. LBNALLOC(srcbuf, t);
  388. if (!srcbuf)
  389. return -1;
  390. lbnCopy_16(srcbuf, (BNWORD16 *)b->ptr, t);
  391. lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s,
  392.                                  srcbuf, t);
  393. LBNFREE(srcbuf, t);
  394. } else {
  395. lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s,
  396.                                  (BNWORD16 *)b->ptr, t);
  397. }
  398. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+t);
  399. MALLOCDB;
  400. return 0;
  401. }
  402. int
  403. bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b)
  404. {
  405. unsigned s;
  406. s = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
  407. if (!s || !b) {
  408. dest->size = 0;
  409. return 0;
  410. }
  411. if (b == 1)
  412. return bnCopy_16(dest, a);
  413. bnSizeCheck(dest, s+1);
  414. lbnMulN1_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, b);
  415. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+1);
  416. MALLOCDB;
  417. return 0;
  418. }
  419. int
  420. bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
  421.             struct BigNum const *d)
  422. {
  423. unsigned dsize, nsize;
  424. BNWORD16 qhigh;
  425. dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size);
  426. nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size);
  427. if (nsize < dsize) {
  428. q->size = 0; /* No quotient */
  429. r->size = nsize;
  430. return 0; /* Success */
  431. }
  432. bnSizeCheck(q, nsize-dsize);
  433. if (r != n) { /* You are allowed to reduce in place */
  434. bnSizeCheck(r, nsize);
  435. lbnCopy_16((BNWORD16 *)r->ptr, (BNWORD16 *)n->ptr, nsize);
  436. }
  437. qhigh = lbnDiv_16((BNWORD16 *)q->ptr, (BNWORD16 *)r->ptr, nsize,
  438.                   (BNWORD16 *)d->ptr, dsize);
  439. nsize -= dsize;
  440. if (qhigh) {
  441. bnSizeCheck(q, nsize+1);
  442. *((BNWORD16 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
  443. q->size = nsize+1;
  444. } else {
  445. q->size = lbnNorm_16((BNWORD16 *)q->ptr, nsize);
  446. }
  447. r->size = lbnNorm_16((BNWORD16 *)r->ptr, dsize);
  448. MALLOCDB;
  449. return 0;
  450. }
  451. int
  452. bnMod_16(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d)
  453. {
  454. unsigned dsize, nsize;
  455. nsize = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
  456. dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size);
  457. if (dest != src) {
  458. bnSizeCheck(dest, nsize);
  459. lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, nsize);
  460. }
  461. if (nsize < dsize) {
  462. dest->size = nsize; /* No quotient */
  463. return 0;
  464. }
  465. (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-dsize,+dsize),
  466.                 (BNWORD16 *)dest->ptr, nsize,
  467.                 (BNWORD16 *)d->ptr, dsize);
  468. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dsize);
  469. MALLOCDB;
  470. return 0;
  471. }
  472. unsigned
  473. bnModQ_16(struct BigNum const *src, unsigned d)
  474. {
  475. unsigned s;
  476. s = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
  477. if (!s)
  478. return 0;
  479. return lbnModQ_16((BNWORD16 *)src->ptr, s, d);
  480. }
  481. int
  482. bnExpMod_16(struct BigNum *dest, struct BigNum const *n,
  483. struct BigNum const *exp, struct BigNum const *mod)
  484. {
  485. unsigned nsize, esize, msize;
  486. nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size);
  487. esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size);
  488. msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
  489. if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
  490. return -1; /* Illegal modulus! */
  491. bnSizeCheck(dest, msize);
  492. /* Special-case base of 2 */
  493. if (nsize == 1 && ((BNWORD16 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
  494. if (lbnTwoExpMod_16((BNWORD16 *)dest->ptr,
  495.     (BNWORD16 *)exp->ptr, esize,
  496.     (BNWORD16 *)mod->ptr, msize) < 0)
  497. return -1;
  498. } else {
  499. if (lbnExpMod_16((BNWORD16 *)dest->ptr,
  500.                  (BNWORD16 *)n->ptr, nsize,
  501.  (BNWORD16 *)exp->ptr, esize,
  502.  (BNWORD16 *)mod->ptr, msize) < 0)
  503. return -1;
  504. }
  505. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize);
  506. MALLOCDB;
  507. return 0;
  508. }
  509. int
  510. bnDoubleExpMod_16(struct BigNum *dest,
  511. struct BigNum const *n1, struct BigNum const *e1,
  512. struct BigNum const *n2, struct BigNum const *e2,
  513. struct BigNum const *mod)
  514. {
  515. unsigned n1size, e1size, n2size, e2size, msize;
  516. n1size = lbnNorm_16((BNWORD16 *)n1->ptr, n1->size);
  517. e1size = lbnNorm_16((BNWORD16 *)e1->ptr, e1->size);
  518. n2size = lbnNorm_16((BNWORD16 *)n2->ptr, n2->size);
  519. e2size = lbnNorm_16((BNWORD16 *)e2->ptr, e2->size);
  520. msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
  521. if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
  522. return -1; /* Illegal modulus! */
  523. bnSizeCheck(dest, msize);
  524. if (lbnDoubleExpMod_16((BNWORD16 *)dest->ptr,
  525. (BNWORD16 *)n1->ptr, n1size, (BNWORD16 *)e1->ptr, e1size,
  526. (BNWORD16 *)n2->ptr, n1size, (BNWORD16 *)e2->ptr, e2size,
  527. (BNWORD16 *)mod->ptr, msize) < 0)
  528. return -1;
  529. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize);
  530. MALLOCDB;
  531. return 0;
  532. }
  533. int
  534. bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp,
  535. struct BigNum const *mod)
  536. {
  537. unsigned esize, msize;
  538. esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size);
  539. msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
  540. if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
  541. return -1; /* Illegal modulus! */
  542. bnSizeCheck(n, msize);
  543. if (lbnTwoExpMod_16((BNWORD16 *)n->ptr, (BNWORD16 *)exp->ptr, esize,
  544.                     (BNWORD16 *)mod->ptr, msize) < 0)
  545. return -1;
  546. n->size = lbnNorm_16((BNWORD16 *)n->ptr, msize);
  547. MALLOCDB;
  548. return 0;
  549. }
  550. int
  551. bnGcd_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
  552. {
  553. BNWORD16 *tmp;
  554. unsigned asize, bsize;
  555. int i;
  556. /* Kind of silly, but we might as well permit it... */
  557. if (a == b)
  558. return dest == a ? 0 : bnCopy(dest, a);
  559. /* Ensure a is not the same as "dest" */
  560. if (a == dest) {
  561. a = b;
  562. b = dest;
  563. }
  564. asize = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
  565. bsize = lbnNorm_16((BNWORD16 *)b->ptr, b->size);
  566. bnSizeCheck(dest, bsize+1);
  567. /* Copy a to tmp */
  568. LBNALLOC(tmp, asize+1);
  569. if (!tmp)
  570. return -1;
  571. lbnCopy_16(tmp, (BNWORD16 *)a->ptr, asize);
  572. /* Copy b to dest,if necessary */
  573. if (dest != b)
  574. lbnCopy_16((BNWORD16 *)dest->ptr,
  575.    (BNWORD16 *)b->ptr, bsize);
  576. if (bsize > asize || (bsize == asize &&
  577.         lbnCmp_16((BNWORD16 *)b->ptr, (BNWORD16 *)a->ptr, asize) > 0))
  578. {
  579. i = lbnGcd_16((BNWORD16 *)dest->ptr, bsize, tmp, asize);
  580. if (i >= 0) {
  581. dest->size = (unsigned)i;
  582. } else {
  583. lbnCopy_16((BNWORD16 *)dest->ptr, tmp,
  584.    (unsigned)-i);
  585. dest->size = (unsigned)-i;
  586. }
  587. } else {
  588. i = lbnGcd_16(tmp, asize, (BNWORD16 *)dest->ptr, bsize);
  589. if (i <= 0) {
  590. dest->size = (unsigned)-i;
  591. } else {
  592. lbnCopy_16((BNWORD16 *)dest->ptr, tmp,
  593.    (unsigned)i);
  594. dest->size = (unsigned)i;
  595. }
  596. }
  597. LBNFREE(tmp, asize+1);
  598. MALLOCDB;
  599. return 0;
  600. }
  601. int
  602. bnInv_16(struct BigNum *dest, struct BigNum const *src,
  603.          struct BigNum const *mod)
  604. {
  605. unsigned s, m;
  606. int i;
  607. s = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
  608. m = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
  609. /* lbnInv_16 requires that the input be less than the modulus */
  610. if (m < s ||
  611.     (m==s && lbnCmp_16((BNWORD16 *)src->ptr, (BNWORD16 *)mod->ptr, s)))
  612. {
  613. bnSizeCheck(dest, s + (m==s));
  614. if (dest != src)
  615. lbnCopy_16((BNWORD16 *)dest->ptr,
  616.            (BNWORD16 *)src->ptr, s);
  617. /* Pre-reduce modulo the modulus */
  618. (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-m,+m),
  619.         (BNWORD16 *)dest->ptr, s,
  620.                 (BNWORD16 *)mod->ptr, m);
  621. s = lbnNorm_16((BNWORD16 *)dest->ptr, m);
  622. MALLOCDB;
  623. } else {
  624. bnSizeCheck(dest, m+1);
  625. if (dest != src)
  626. lbnCopy_16((BNWORD16 *)dest->ptr,
  627.            (BNWORD16 *)src->ptr, s);
  628. }
  629. i = lbnInv_16((BNWORD16 *)dest->ptr, s, (BNWORD16 *)mod->ptr, m);
  630. if (i == 0)
  631. dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, m);
  632. MALLOCDB;
  633. return i;
  634. }
  635. /*
  636.  * Shift a bignum left the appropriate number of bits,
  637.  * multiplying by 2^amt.
  638.  */
  639. int 
  640. bnLShift_16(struct BigNum *dest, unsigned amt)
  641. {
  642. unsigned s = dest->size;
  643. BNWORD16 carry;
  644. if (amt % 16) {
  645. carry = lbnLshift_16(dest->ptr, s, amt % 16);
  646. if (carry) {
  647. s++;
  648. bnSizeCheck(dest, s);
  649. ((BNWORD16 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
  650. }
  651. }
  652. amt /= 16;
  653. if (amt) {
  654. bnSizeCheck(dest, s+amt);
  655. memmove((BNWORD16 *)dest->ptr BIGLITTLE(-s-amt, +amt),
  656.         (BNWORD16 *)dest->ptr BIG(-s),
  657. s * sizeof(BNWORD16));
  658. lbnZero_16((BNWORD16 *)dest->ptr, amt);
  659. s += amt;
  660. }
  661. dest->size = s;
  662. MALLOCDB;
  663. return 0;
  664. }
  665. /*
  666.  * Shift a bignum right the appropriate number of bits,
  667.  * dividing by 2^amt.
  668.  */
  669. void bnRShift_16(struct BigNum *dest, unsigned amt)
  670. {
  671. unsigned s = dest->size;
  672. if (amt >= 16) {
  673. memmove(
  674.         (BNWORD16 *)dest->ptr BIG(-s+amt/16),
  675. (BNWORD16 *)dest->ptr BIGLITTLE(-s, +amt/16),
  676. s-amt/16 * sizeof(BNWORD16));
  677. s -= amt/16;
  678. amt %= 16;
  679. }
  680. if (amt)
  681. (void)lbnRshift_16(dest->ptr, s, amt);
  682. dest->size = lbnNorm_16(dest->ptr, s);
  683. MALLOCDB;
  684. }
  685. /*
  686.  * Shift a bignum right until it is odd, and return the number of
  687.  * bits shifted.  n = d * 2^s.  Replaces n with d and returns s.
  688.  * Returns 0 when given 0.  (Another valid answer is infinity.)
  689.  */
  690. unsigned
  691. bnMakeOdd_16(struct BigNum *n)
  692. {
  693. unsigned size;
  694. unsigned s; /* shift amount */
  695. BNWORD16 *p;
  696. BNWORD16 t;
  697. p = (BNWORD16 *)n->ptr;
  698. size = lbnNorm_16(p, n->size);
  699. if (!size)
  700. return 0;
  701. t = BIGLITTLE(p[-1],p[0]);
  702. s = 0;
  703. /* See how many words we have to shift */
  704. if (!t) {
  705. /* Shift by words */
  706. do {
  707. s++;
  708. BIGLITTLE(--p,p++);
  709. } while ((t = BIGLITTLE(p[-1],p[0])) == 0);
  710. size -= s;
  711. s *= 16;
  712. memmove((BNWORD16 *)n->ptr BIG(-size), p BIG(-size),
  713. size * sizeof(BNWORD16));
  714. p = (BNWORD16 *)n->ptr;
  715. MALLOCDB;
  716. }
  717. assert(t);
  718. /* Now count the bits */
  719. while ((t & 1) == 0) {
  720. t >>= 1;
  721. s++;
  722. }
  723. /* Shift the bits */
  724. if (s & (16-1)) {
  725. lbnRshift_16(p, size, s & (16-1));
  726. /* Renormalize */
  727. if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
  728. --size;
  729. }
  730. n->size = size;
  731. MALLOCDB;
  732. return s;
  733. }