1/* Start: bn_error.c */ 2#include <tommath.h> 3#ifdef BN_ERROR_C 4/* LibTomMath, multiple-precision integer library -- Tom St Denis 5 * 6 * LibTomMath is a library that provides multiple-precision 7 * integer arithmetic as well as number theoretic functionality. 8 * 9 * The library was designed directly after the MPI library by 10 * Michael Fromberger but has been written from scratch with 11 * additional optimizations in place. 12 * 13 * The library is free for all purposes without any express 14 * guarantee it works. 15 * 16 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 17 */ 18 19static const struct { 20 int code; 21 char *msg; 22} msgs[] = { 23 { MP_OKAY, "Successful" }, 24 { MP_MEM, "Out of heap" }, 25 { MP_VAL, "Value out of range" } 26}; 27 28/* return a char * string for a given code */ 29char *mp_error_to_string(int code) 30{ 31 int x; 32 33 /* scan the lookup table for the given message */ 34 for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { 35 if (msgs[x].code == code) { 36 return msgs[x].msg; 37 } 38 } 39 40 /* generic reply for invalid code */ 41 return "Invalid error code"; 42} 43 44#endif 45 46/* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */ 47/* $Revision: 1.3 $ */ 48/* $Date: 2006/03/31 14:18:44 $ */ 49 50/* End: bn_error.c */ 51 52/* Start: bn_fast_mp_invmod.c */ 53#include <tommath.h> 54#ifdef BN_FAST_MP_INVMOD_C 55/* LibTomMath, multiple-precision integer library -- Tom St Denis 56 * 57 * LibTomMath is a library that provides multiple-precision 58 * integer arithmetic as well as number theoretic functionality. 59 * 60 * The library was designed directly after the MPI library by 61 * Michael Fromberger but has been written from scratch with 62 * additional optimizations in place. 63 * 64 * The library is free for all purposes without any express 65 * guarantee it works. 66 * 67 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 68 */ 69 70/* computes the modular inverse via binary extended euclidean algorithm, 71 * that is c = 1/a mod b 72 * 73 * Based on slow invmod except this is optimized for the case where b is 74 * odd as per HAC Note 14.64 on pp. 610 75 */ 76int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) 77{ 78 mp_int x, y, u, v, B, D; 79 int res, neg; 80 81 /* 2. [modified] b must be odd */ 82 if (mp_iseven (b) == 1) { 83 return MP_VAL; 84 } 85 86 /* init all our temps */ 87 if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { 88 return res; 89 } 90 91 /* x == modulus, y == value to invert */ 92 if ((res = mp_copy (b, &x)) != MP_OKAY) { 93 goto LBL_ERR; 94 } 95 96 /* we need y = |a| */ 97 if ((res = mp_mod (a, b, &y)) != MP_OKAY) { 98 goto LBL_ERR; 99 } 100 101 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ 102 if ((res = mp_copy (&x, &u)) != MP_OKAY) { 103 goto LBL_ERR; 104 } 105 if ((res = mp_copy (&y, &v)) != MP_OKAY) { 106 goto LBL_ERR; 107 } 108 mp_set (&D, 1); 109 110top: 111 /* 4. while u is even do */ 112 while (mp_iseven (&u) == 1) { 113 /* 4.1 u = u/2 */ 114 if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { 115 goto LBL_ERR; 116 } 117 /* 4.2 if B is odd then */ 118 if (mp_isodd (&B) == 1) { 119 if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { 120 goto LBL_ERR; 121 } 122 } 123 /* B = B/2 */ 124 if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { 125 goto LBL_ERR; 126 } 127 } 128 129 /* 5. while v is even do */ 130 while (mp_iseven (&v) == 1) { 131 /* 5.1 v = v/2 */ 132 if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { 133 goto LBL_ERR; 134 } 135 /* 5.2 if D is odd then */ 136 if (mp_isodd (&D) == 1) { 137 /* D = (D-x)/2 */ 138 if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { 139 goto LBL_ERR; 140 } 141 } 142 /* D = D/2 */ 143 if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { 144 goto LBL_ERR; 145 } 146 } 147 148 /* 6. if u >= v then */ 149 if (mp_cmp (&u, &v) != MP_LT) { 150 /* u = u - v, B = B - D */ 151 if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { 152 goto LBL_ERR; 153 } 154 155 if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { 156 goto LBL_ERR; 157 } 158 } else { 159 /* v - v - u, D = D - B */ 160 if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { 161 goto LBL_ERR; 162 } 163 164 if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { 165 goto LBL_ERR; 166 } 167 } 168 169 /* if not zero goto step 4 */ 170 if (mp_iszero (&u) == 0) { 171 goto top; 172 } 173 174 /* now a = C, b = D, gcd == g*v */ 175 176 /* if v != 1 then there is no inverse */ 177 if (mp_cmp_d (&v, 1) != MP_EQ) { 178 res = MP_VAL; 179 goto LBL_ERR; 180 } 181 182 /* b is now the inverse */ 183 neg = a->sign; 184 while (D.sign == MP_NEG) { 185 if ((res = mp_add (&D, b, &D)) != MP_OKAY) { 186 goto LBL_ERR; 187 } 188 } 189 mp_exch (&D, c); 190 c->sign = neg; 191 res = MP_OKAY; 192 193LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); 194 return res; 195} 196#endif 197 198/* $Source: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */ 199/* $Revision: 1.3 $ */ 200/* $Date: 2006/03/31 14:18:44 $ */ 201 202/* End: bn_fast_mp_invmod.c */ 203 204/* Start: bn_fast_mp_montgomery_reduce.c */ 205#include <tommath.h> 206#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C 207/* LibTomMath, multiple-precision integer library -- Tom St Denis 208 * 209 * LibTomMath is a library that provides multiple-precision 210 * integer arithmetic as well as number theoretic functionality. 211 * 212 * The library was designed directly after the MPI library by 213 * Michael Fromberger but has been written from scratch with 214 * additional optimizations in place. 215 * 216 * The library is free for all purposes without any express 217 * guarantee it works. 218 * 219 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 220 */ 221 222/* computes xR**-1 == x (mod N) via Montgomery Reduction 223 * 224 * This is an optimized implementation of montgomery_reduce 225 * which uses the comba method to quickly calculate the columns of the 226 * reduction. 227 * 228 * Based on Algorithm 14.32 on pp.601 of HAC. 229*/ 230int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) 231{ 232 int ix, res, olduse; 233 mp_word W[MP_WARRAY]; 234 235 /* get old used count */ 236 olduse = x->used; 237 238 /* grow a as required */ 239 if (x->alloc < n->used + 1) { 240 if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { 241 return res; 242 } 243 } 244 245 /* first we have to get the digits of the input into 246 * an array of double precision words W[...] 247 */ 248 { 249 register mp_word *_W; 250 register mp_digit *tmpx; 251 252 /* alias for the W[] array */ 253 _W = W; 254 255 /* alias for the digits of x*/ 256 tmpx = x->dp; 257 258 /* copy the digits of a into W[0..a->used-1] */ 259 for (ix = 0; ix < x->used; ix++) { 260 *_W++ = *tmpx++; 261 } 262 263 /* zero the high words of W[a->used..m->used*2] */ 264 for (; ix < n->used * 2 + 1; ix++) { 265 *_W++ = 0; 266 } 267 } 268 269 /* now we proceed to zero successive digits 270 * from the least significant upwards 271 */ 272 for (ix = 0; ix < n->used; ix++) { 273 /* mu = ai * m' mod b 274 * 275 * We avoid a double precision multiplication (which isn't required) 276 * by casting the value down to a mp_digit. Note this requires 277 * that W[ix-1] have the carry cleared (see after the inner loop) 278 */ 279 register mp_digit mu; 280 mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); 281 282 /* a = a + mu * m * b**i 283 * 284 * This is computed in place and on the fly. The multiplication 285 * by b**i is handled by offseting which columns the results 286 * are added to. 287 * 288 * Note the comba method normally doesn't handle carries in the 289 * inner loop In this case we fix the carry from the previous 290 * column since the Montgomery reduction requires digits of the 291 * result (so far) [see above] to work. This is 292 * handled by fixing up one carry after the inner loop. The 293 * carry fixups are done in order so after these loops the 294 * first m->used words of W[] have the carries fixed 295 */ 296 { 297 register int iy; 298 register mp_digit *tmpn; 299 register mp_word *_W; 300 301 /* alias for the digits of the modulus */ 302 tmpn = n->dp; 303 304 /* Alias for the columns set by an offset of ix */ 305 _W = W + ix; 306 307 /* inner loop */ 308 for (iy = 0; iy < n->used; iy++) { 309 *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); 310 } 311 } 312 313 /* now fix carry for next digit, W[ix+1] */ 314 W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); 315 } 316 317 /* now we have to propagate the carries and 318 * shift the words downward [all those least 319 * significant digits we zeroed]. 320 */ 321 { 322 register mp_digit *tmpx; 323 register mp_word *_W, *_W1; 324 325 /* nox fix rest of carries */ 326 327 /* alias for current word */ 328 _W1 = W + ix; 329 330 /* alias for next word, where the carry goes */ 331 _W = W + ++ix; 332 333 for (; ix <= n->used * 2 + 1; ix++) { 334 *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); 335 } 336 337 /* copy out, A = A/b**n 338 * 339 * The result is A/b**n but instead of converting from an 340 * array of mp_word to mp_digit than calling mp_rshd 341 * we just copy them in the right order 342 */ 343 344 /* alias for destination word */ 345 tmpx = x->dp; 346 347 /* alias for shifted double precision result */ 348 _W = W + n->used; 349 350 for (ix = 0; ix < n->used + 1; ix++) { 351 *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); 352 } 353 354 /* zero oldused digits, if the input a was larger than 355 * m->used+1 we'll have to clear the digits 356 */ 357 for (; ix < olduse; ix++) { 358 *tmpx++ = 0; 359 } 360 } 361 362 /* set the max used and clamp */ 363 x->used = n->used + 1; 364 mp_clamp (x); 365 366 /* if A >= m then A = A - m */ 367 if (mp_cmp_mag (x, n) != MP_LT) { 368 return s_mp_sub (x, n, x); 369 } 370 return MP_OKAY; 371} 372#endif 373 374/* $Source: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */ 375/* $Revision: 1.3 $ */ 376/* $Date: 2006/03/31 14:18:44 $ */ 377 378/* End: bn_fast_mp_montgomery_reduce.c */ 379 380/* Start: bn_fast_s_mp_mul_digs.c */ 381#include <tommath.h> 382#ifdef BN_FAST_S_MP_MUL_DIGS_C 383/* LibTomMath, multiple-precision integer library -- Tom St Denis 384 * 385 * LibTomMath is a library that provides multiple-precision 386 * integer arithmetic as well as number theoretic functionality. 387 * 388 * The library was designed directly after the MPI library by 389 * Michael Fromberger but has been written from scratch with 390 * additional optimizations in place. 391 * 392 * The library is free for all purposes without any express 393 * guarantee it works. 394 * 395 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 396 */ 397 398/* Fast (comba) multiplier 399 * 400 * This is the fast column-array [comba] multiplier. It is 401 * designed to compute the columns of the product first 402 * then handle the carries afterwards. This has the effect 403 * of making the nested loops that compute the columns very 404 * simple and schedulable on super-scalar processors. 405 * 406 * This has been modified to produce a variable number of 407 * digits of output so if say only a half-product is required 408 * you don't have to compute the upper half (a feature 409 * required for fast Barrett reduction). 410 * 411 * Based on Algorithm 14.12 on pp.595 of HAC. 412 * 413 */ 414int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) 415{ 416 int olduse, res, pa, ix, iz; 417 mp_digit W[MP_WARRAY]; 418 register mp_word _W; 419 420 /* grow the destination as required */ 421 if (c->alloc < digs) { 422 if ((res = mp_grow (c, digs)) != MP_OKAY) { 423 return res; 424 } 425 } 426 427 /* number of output digits to produce */ 428 pa = MIN(digs, a->used + b->used); 429 430 /* clear the carry */ 431 _W = 0; 432 for (ix = 0; ix < pa; ix++) { 433 int tx, ty; 434 int iy; 435 mp_digit *tmpx, *tmpy; 436 437 /* get offsets into the two bignums */ 438 ty = MIN(b->used-1, ix); 439 tx = ix - ty; 440 441 /* setup temp aliases */ 442 tmpx = a->dp + tx; 443 tmpy = b->dp + ty; 444 445 /* this is the number of times the loop will iterrate, essentially 446 while (tx++ < a->used && ty-- >= 0) { ... } 447 */ 448 iy = MIN(a->used-tx, ty+1); 449 450 /* execute loop */ 451 for (iz = 0; iz < iy; ++iz) { 452 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); 453 454 } 455 456 /* store term */ 457 W[ix] = ((mp_digit)_W) & MP_MASK; 458 459 /* make next carry */ 460 _W = _W >> ((mp_word)DIGIT_BIT); 461 } 462 463 /* setup dest */ 464 olduse = c->used; 465 c->used = pa; 466 467 { 468 register mp_digit *tmpc; 469 tmpc = c->dp; 470 for (ix = 0; ix < pa+1; ix++) { 471 /* now extract the previous digit [below the carry] */ 472 *tmpc++ = W[ix]; 473 } 474 475 /* clear unused digits [that existed in the old copy of c] */ 476 for (; ix < olduse; ix++) { 477 *tmpc++ = 0; 478 } 479 } 480 mp_clamp (c); 481 return MP_OKAY; 482} 483#endif 484 485/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */ 486/* $Revision: 1.7 $ */ 487/* $Date: 2006/03/31 14:18:44 $ */ 488 489/* End: bn_fast_s_mp_mul_digs.c */ 490 491/* Start: bn_fast_s_mp_mul_high_digs.c */ 492#include <tommath.h> 493#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C 494/* LibTomMath, multiple-precision integer library -- Tom St Denis 495 * 496 * LibTomMath is a library that provides multiple-precision 497 * integer arithmetic as well as number theoretic functionality. 498 * 499 * The library was designed directly after the MPI library by 500 * Michael Fromberger but has been written from scratch with 501 * additional optimizations in place. 502 * 503 * The library is free for all purposes without any express 504 * guarantee it works. 505 * 506 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 507 */ 508 509/* this is a modified version of fast_s_mul_digs that only produces 510 * output digits *above* digs. See the comments for fast_s_mul_digs 511 * to see how it works. 512 * 513 * This is used in the Barrett reduction since for one of the multiplications 514 * only the higher digits were needed. This essentially halves the work. 515 * 516 * Based on Algorithm 14.12 on pp.595 of HAC. 517 */ 518int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) 519{ 520 int olduse, res, pa, ix, iz; 521 mp_digit W[MP_WARRAY]; 522 mp_word _W; 523 524 /* grow the destination as required */ 525 pa = a->used + b->used; 526 if (c->alloc < pa) { 527 if ((res = mp_grow (c, pa)) != MP_OKAY) { 528 return res; 529 } 530 } 531 532 /* number of output digits to produce */ 533 pa = a->used + b->used; 534 _W = 0; 535 for (ix = digs; ix < pa; ix++) { 536 int tx, ty, iy; 537 mp_digit *tmpx, *tmpy; 538 539 /* get offsets into the two bignums */ 540 ty = MIN(b->used-1, ix); 541 tx = ix - ty; 542 543 /* setup temp aliases */ 544 tmpx = a->dp + tx; 545 tmpy = b->dp + ty; 546 547 /* this is the number of times the loop will iterrate, essentially its 548 while (tx++ < a->used && ty-- >= 0) { ... } 549 */ 550 iy = MIN(a->used-tx, ty+1); 551 552 /* execute loop */ 553 for (iz = 0; iz < iy; iz++) { 554 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); 555 } 556 557 /* store term */ 558 W[ix] = ((mp_digit)_W) & MP_MASK; 559 560 /* make next carry */ 561 _W = _W >> ((mp_word)DIGIT_BIT); 562 } 563 564 /* setup dest */ 565 olduse = c->used; 566 c->used = pa; 567 568 { 569 register mp_digit *tmpc; 570 571 tmpc = c->dp + digs; 572 for (ix = digs; ix < pa; ix++) { 573 /* now extract the previous digit [below the carry] */ 574 *tmpc++ = W[ix]; 575 } 576 577 /* clear unused digits [that existed in the old copy of c] */ 578 for (; ix < olduse; ix++) { 579 *tmpc++ = 0; 580 } 581 } 582 mp_clamp (c); 583 return MP_OKAY; 584} 585#endif 586 587/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */ 588/* $Revision: 1.5 $ */ 589/* $Date: 2006/11/14 03:46:25 $ */ 590 591/* End: bn_fast_s_mp_mul_high_digs.c */ 592 593/* Start: bn_fast_s_mp_sqr.c */ 594#include <tommath.h> 595#ifdef BN_FAST_S_MP_SQR_C 596/* LibTomMath, multiple-precision integer library -- Tom St Denis 597 * 598 * LibTomMath is a library that provides multiple-precision 599 * integer arithmetic as well as number theoretic functionality. 600 * 601 * The library was designed directly after the MPI library by 602 * Michael Fromberger but has been written from scratch with 603 * additional optimizations in place. 604 * 605 * The library is free for all purposes without any express 606 * guarantee it works. 607 * 608 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 609 */ 610 611/* the jist of squaring... 612 * you do like mult except the offset of the tmpx [one that 613 * starts closer to zero] can't equal the offset of tmpy. 614 * So basically you set up iy like before then you min it with 615 * (ty-tx) so that it never happens. You double all those 616 * you add in the inner loop 617 618After that loop you do the squares and add them in. 619*/ 620 621int fast_s_mp_sqr (mp_int * a, mp_int * b) 622{ 623 int olduse, res, pa, ix, iz; 624 mp_digit W[MP_WARRAY], *tmpx; 625 mp_word W1; 626 627 /* grow the destination as required */ 628 pa = a->used + a->used; 629 if (b->alloc < pa) { 630 if ((res = mp_grow (b, pa)) != MP_OKAY) { 631 return res; 632 } 633 } 634 635 /* number of output digits to produce */ 636 W1 = 0; 637 for (ix = 0; ix < pa; ix++) { 638 int tx, ty, iy; 639 mp_word _W; 640 mp_digit *tmpy; 641 642 /* clear counter */ 643 _W = 0; 644 645 /* get offsets into the two bignums */ 646 ty = MIN(a->used-1, ix); 647 tx = ix - ty; 648 649 /* setup temp aliases */ 650 tmpx = a->dp + tx; 651 tmpy = a->dp + ty; 652 653 /* this is the number of times the loop will iterrate, essentially 654 while (tx++ < a->used && ty-- >= 0) { ... } 655 */ 656 iy = MIN(a->used-tx, ty+1); 657 658 /* now for squaring tx can never equal ty 659 * we halve the distance since they approach at a rate of 2x 660 * and we have to round because odd cases need to be executed 661 */ 662 iy = MIN(iy, (ty-tx+1)>>1); 663 664 /* execute loop */ 665 for (iz = 0; iz < iy; iz++) { 666 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); 667 } 668 669 /* double the inner product and add carry */ 670 _W = _W + _W + W1; 671 672 /* even columns have the square term in them */ 673 if ((ix&1) == 0) { 674 _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); 675 } 676 677 /* store it */ 678 W[ix] = (mp_digit)(_W & MP_MASK); 679 680 /* make next carry */ 681 W1 = _W >> ((mp_word)DIGIT_BIT); 682 } 683 684 /* setup dest */ 685 olduse = b->used; 686 b->used = a->used+a->used; 687 688 { 689 mp_digit *tmpb; 690 tmpb = b->dp; 691 for (ix = 0; ix < pa; ix++) { 692 *tmpb++ = W[ix] & MP_MASK; 693 } 694 695 /* clear unused digits [that existed in the old copy of c] */ 696 for (; ix < olduse; ix++) { 697 *tmpb++ = 0; 698 } 699 } 700 mp_clamp (b); 701 return MP_OKAY; 702} 703#endif 704 705/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */ 706/* $Revision: 1.3 $ */ 707/* $Date: 2006/03/31 14:18:44 $ */ 708 709/* End: bn_fast_s_mp_sqr.c */ 710 711/* Start: bn_mp_2expt.c */ 712#include <tommath.h> 713#ifdef BN_MP_2EXPT_C 714/* LibTomMath, multiple-precision integer library -- Tom St Denis 715 * 716 * LibTomMath is a library that provides multiple-precision 717 * integer arithmetic as well as number theoretic functionality. 718 * 719 * The library was designed directly after the MPI library by 720 * Michael Fromberger but has been written from scratch with 721 * additional optimizations in place. 722 * 723 * The library is free for all purposes without any express 724 * guarantee it works. 725 * 726 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 727 */ 728 729/* computes a = 2**b 730 * 731 * Simple algorithm which zeroes the int, grows it then just sets one bit 732 * as required. 733 */ 734int 735mp_2expt (mp_int * a, int b) 736{ 737 int res; 738 739 /* zero a as per default */ 740 mp_zero (a); 741 742 /* grow a to accomodate the single bit */ 743 if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { 744 return res; 745 } 746 747 /* set the used count of where the bit will go */ 748 a->used = b / DIGIT_BIT + 1; 749 750 /* put the single bit in its place */ 751 a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); 752 753 return MP_OKAY; 754} 755#endif 756 757/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */ 758/* $Revision: 1.3 $ */ 759/* $Date: 2006/03/31 14:18:44 $ */ 760 761/* End: bn_mp_2expt.c */ 762 763/* Start: bn_mp_abs.c */ 764#include <tommath.h> 765#ifdef BN_MP_ABS_C 766/* LibTomMath, multiple-precision integer library -- Tom St Denis 767 * 768 * LibTomMath is a library that provides multiple-precision 769 * integer arithmetic as well as number theoretic functionality. 770 * 771 * The library was designed directly after the MPI library by 772 * Michael Fromberger but has been written from scratch with 773 * additional optimizations in place. 774 * 775 * The library is free for all purposes without any express 776 * guarantee it works. 777 * 778 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 779 */ 780 781/* b = |a| 782 * 783 * Simple function copies the input and fixes the sign to positive 784 */ 785int 786mp_abs (mp_int * a, mp_int * b) 787{ 788 int res; 789 790 /* copy a to b */ 791 if (a != b) { 792 if ((res = mp_copy (a, b)) != MP_OKAY) { 793 return res; 794 } 795 } 796 797 /* force the sign of b to positive */ 798 b->sign = MP_ZPOS; 799 800 return MP_OKAY; 801} 802#endif 803 804/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */ 805/* $Revision: 1.3 $ */ 806/* $Date: 2006/03/31 14:18:44 $ */ 807 808/* End: bn_mp_abs.c */ 809 810/* Start: bn_mp_add.c */ 811#include <tommath.h> 812#ifdef BN_MP_ADD_C 813/* LibTomMath, multiple-precision integer library -- Tom St Denis 814 * 815 * LibTomMath is a library that provides multiple-precision 816 * integer arithmetic as well as number theoretic functionality. 817 * 818 * The library was designed directly after the MPI library by 819 * Michael Fromberger but has been written from scratch with 820 * additional optimizations in place. 821 * 822 * The library is free for all purposes without any express 823 * guarantee it works. 824 * 825 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 826 */ 827 828/* high level addition (handles signs) */ 829int mp_add (mp_int * a, mp_int * b, mp_int * c) 830{ 831 int sa, sb, res; 832 833 /* get sign of both inputs */ 834 sa = a->sign; 835 sb = b->sign; 836 837 /* handle two cases, not four */ 838 if (sa == sb) { 839 /* both positive or both negative */ 840 /* add their magnitudes, copy the sign */ 841 c->sign = sa; 842 res = s_mp_add (a, b, c); 843 } else { 844 /* one positive, the other negative */ 845 /* subtract the one with the greater magnitude from */ 846 /* the one of the lesser magnitude. The result gets */ 847 /* the sign of the one with the greater magnitude. */ 848 if (mp_cmp_mag (a, b) == MP_LT) { 849 c->sign = sb; 850 res = s_mp_sub (b, a, c); 851 } else { 852 c->sign = sa; 853 res = s_mp_sub (a, b, c); 854 } 855 } 856 return res; 857} 858 859#endif 860 861/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */ 862/* $Revision: 1.3 $ */ 863/* $Date: 2006/03/31 14:18:44 $ */ 864 865/* End: bn_mp_add.c */ 866 867/* Start: bn_mp_add_d.c */ 868#include <tommath.h> 869#ifdef BN_MP_ADD_D_C 870/* LibTomMath, multiple-precision integer library -- Tom St Denis 871 * 872 * LibTomMath is a library that provides multiple-precision 873 * integer arithmetic as well as number theoretic functionality. 874 * 875 * The library was designed directly after the MPI library by 876 * Michael Fromberger but has been written from scratch with 877 * additional optimizations in place. 878 * 879 * The library is free for all purposes without any express 880 * guarantee it works. 881 * 882 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 883 */ 884 885/* single digit addition */ 886int 887mp_add_d (mp_int * a, mp_digit b, mp_int * c) 888{ 889 int res, ix, oldused; 890 mp_digit *tmpa, *tmpc, mu; 891 892 /* grow c as required */ 893 if (c->alloc < a->used + 1) { 894 if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { 895 return res; 896 } 897 } 898 899 /* if a is negative and |a| >= b, call c = |a| - b */ 900 if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { 901 /* temporarily fix sign of a */ 902 a->sign = MP_ZPOS; 903 904 /* c = |a| - b */ 905 res = mp_sub_d(a, b, c); 906 907 /* fix sign */ 908 a->sign = c->sign = MP_NEG; 909 910 /* clamp */ 911 mp_clamp(c); 912 913 return res; 914 } 915 916 /* old number of used digits in c */ 917 oldused = c->used; 918 919 /* sign always positive */ 920 c->sign = MP_ZPOS; 921 922 /* source alias */ 923 tmpa = a->dp; 924 925 /* destination alias */ 926 tmpc = c->dp; 927 928 /* if a is positive */ 929 if (a->sign == MP_ZPOS) { 930 /* add digit, after this we're propagating 931 * the carry. 932 */ 933 *tmpc = *tmpa++ + b; 934 mu = *tmpc >> DIGIT_BIT; 935 *tmpc++ &= MP_MASK; 936 937 /* now handle rest of the digits */ 938 for (ix = 1; ix < a->used; ix++) { 939 *tmpc = *tmpa++ + mu; 940 mu = *tmpc >> DIGIT_BIT; 941 *tmpc++ &= MP_MASK; 942 } 943 /* set final carry */ 944 ix++; 945 *tmpc++ = mu; 946 947 /* setup size */ 948 c->used = a->used + 1; 949 } else { 950 /* a was negative and |a| < b */ 951 c->used = 1; 952 953 /* the result is a single digit */ 954 if (a->used == 1) { 955 *tmpc++ = b - a->dp[0]; 956 } else { 957 *tmpc++ = b; 958 } 959 960 /* setup count so the clearing of oldused 961 * can fall through correctly 962 */ 963 ix = 1; 964 } 965 966 /* now zero to oldused */ 967 while (ix++ < oldused) { 968 *tmpc++ = 0; 969 } 970 mp_clamp(c); 971 972 return MP_OKAY; 973} 974 975#endif 976 977/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */ 978/* $Revision: 1.4 $ */ 979/* $Date: 2006/03/31 14:18:44 $ */ 980 981/* End: bn_mp_add_d.c */ 982 983/* Start: bn_mp_addmod.c */ 984#include <tommath.h> 985#ifdef BN_MP_ADDMOD_C 986/* LibTomMath, multiple-precision integer library -- Tom St Denis 987 * 988 * LibTomMath is a library that provides multiple-precision 989 * integer arithmetic as well as number theoretic functionality. 990 * 991 * The library was designed directly after the MPI library by 992 * Michael Fromberger but has been written from scratch with 993 * additional optimizations in place. 994 * 995 * The library is free for all purposes without any express 996 * guarantee it works. 997 * 998 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 999 */ 1000 1001/* d = a + b (mod c) */ 1002int 1003mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) 1004{ 1005 int res; 1006 mp_int t; 1007 1008 if ((res = mp_init (&t)) != MP_OKAY) { 1009 return res; 1010 } 1011 1012 if ((res = mp_add (a, b, &t)) != MP_OKAY) { 1013 mp_clear (&t); 1014 return res; 1015 } 1016 res = mp_mod (&t, c, d); 1017 mp_clear (&t); 1018 return res; 1019} 1020#endif 1021 1022/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */ 1023/* $Revision: 1.3 $ */ 1024/* $Date: 2006/03/31 14:18:44 $ */ 1025 1026/* End: bn_mp_addmod.c */ 1027 1028/* Start: bn_mp_and.c */ 1029#include <tommath.h> 1030#ifdef BN_MP_AND_C 1031/* LibTomMath, multiple-precision integer library -- Tom St Denis 1032 * 1033 * LibTomMath is a library that provides multiple-precision 1034 * integer arithmetic as well as number theoretic functionality. 1035 * 1036 * The library was designed directly after the MPI library by 1037 * Michael Fromberger but has been written from scratch with 1038 * additional optimizations in place. 1039 * 1040 * The library is free for all purposes without any express 1041 * guarantee it works. 1042 * 1043 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1044 */ 1045 1046/* AND two ints together */ 1047int 1048mp_and (mp_int * a, mp_int * b, mp_int * c) 1049{ 1050 int res, ix, px; 1051 mp_int t, *x; 1052 1053 if (a->used > b->used) { 1054 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 1055 return res; 1056 } 1057 px = b->used; 1058 x = b; 1059 } else { 1060 if ((res = mp_init_copy (&t, b)) != MP_OKAY) { 1061 return res; 1062 } 1063 px = a->used; 1064 x = a; 1065 } 1066 1067 for (ix = 0; ix < px; ix++) { 1068 t.dp[ix] &= x->dp[ix]; 1069 } 1070 1071 /* zero digits above the last from the smallest mp_int */ 1072 for (; ix < t.used; ix++) { 1073 t.dp[ix] = 0; 1074 } 1075 1076 mp_clamp (&t); 1077 mp_exch (c, &t); 1078 mp_clear (&t); 1079 return MP_OKAY; 1080} 1081#endif 1082 1083/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */ 1084/* $Revision: 1.3 $ */ 1085/* $Date: 2006/03/31 14:18:44 $ */ 1086 1087/* End: bn_mp_and.c */ 1088 1089/* Start: bn_mp_clamp.c */ 1090#include <tommath.h> 1091#ifdef BN_MP_CLAMP_C 1092/* LibTomMath, multiple-precision integer library -- Tom St Denis 1093 * 1094 * LibTomMath is a library that provides multiple-precision 1095 * integer arithmetic as well as number theoretic functionality. 1096 * 1097 * The library was designed directly after the MPI library by 1098 * Michael Fromberger but has been written from scratch with 1099 * additional optimizations in place. 1100 * 1101 * The library is free for all purposes without any express 1102 * guarantee it works. 1103 * 1104 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1105 */ 1106 1107/* trim unused digits 1108 * 1109 * This is used to ensure that leading zero digits are 1110 * trimed and the leading "used" digit will be non-zero 1111 * Typically very fast. Also fixes the sign if there 1112 * are no more leading digits 1113 */ 1114void 1115mp_clamp (mp_int * a) 1116{ 1117 /* decrease used while the most significant digit is 1118 * zero. 1119 */ 1120 while (a->used > 0 && a->dp[a->used - 1] == 0) { 1121 --(a->used); 1122 } 1123 1124 /* reset the sign flag if used == 0 */ 1125 if (a->used == 0) { 1126 a->sign = MP_ZPOS; 1127 } 1128} 1129#endif 1130 1131/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */ 1132/* $Revision: 1.3 $ */ 1133/* $Date: 2006/03/31 14:18:44 $ */ 1134 1135/* End: bn_mp_clamp.c */ 1136 1137/* Start: bn_mp_clear.c */ 1138#include <tommath.h> 1139#ifdef BN_MP_CLEAR_C 1140/* LibTomMath, multiple-precision integer library -- Tom St Denis 1141 * 1142 * LibTomMath is a library that provides multiple-precision 1143 * integer arithmetic as well as number theoretic functionality. 1144 * 1145 * The library was designed directly after the MPI library by 1146 * Michael Fromberger but has been written from scratch with 1147 * additional optimizations in place. 1148 * 1149 * The library is free for all purposes without any express 1150 * guarantee it works. 1151 * 1152 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1153 */ 1154 1155/* clear one (frees) */ 1156void 1157mp_clear (mp_int * a) 1158{ 1159 int i; 1160 1161 /* only do anything if a hasn't been freed previously */ 1162 if (a->dp != NULL) { 1163 /* first zero the digits */ 1164 for (i = 0; i < a->used; i++) { 1165 a->dp[i] = 0; 1166 } 1167 1168 /* free ram */ 1169 XFREE(a->dp); 1170 1171 /* reset members to make debugging easier */ 1172 a->dp = NULL; 1173 a->alloc = a->used = 0; 1174 a->sign = MP_ZPOS; 1175 } 1176} 1177#endif 1178 1179/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */ 1180/* $Revision: 1.3 $ */ 1181/* $Date: 2006/03/31 14:18:44 $ */ 1182 1183/* End: bn_mp_clear.c */ 1184 1185/* Start: bn_mp_clear_multi.c */ 1186#include <tommath.h> 1187#ifdef BN_MP_CLEAR_MULTI_C 1188/* LibTomMath, multiple-precision integer library -- Tom St Denis 1189 * 1190 * LibTomMath is a library that provides multiple-precision 1191 * integer arithmetic as well as number theoretic functionality. 1192 * 1193 * The library was designed directly after the MPI library by 1194 * Michael Fromberger but has been written from scratch with 1195 * additional optimizations in place. 1196 * 1197 * The library is free for all purposes without any express 1198 * guarantee it works. 1199 * 1200 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1201 */ 1202#include <stdarg.h> 1203 1204void mp_clear_multi(mp_int *mp, ...) 1205{ 1206 mp_int* next_mp = mp; 1207 va_list args; 1208 va_start(args, mp); 1209 while (next_mp != NULL) { 1210 mp_clear(next_mp); 1211 next_mp = va_arg(args, mp_int*); 1212 } 1213 va_end(args); 1214} 1215#endif 1216 1217/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */ 1218/* $Revision: 1.3 $ */ 1219/* $Date: 2006/03/31 14:18:44 $ */ 1220 1221/* End: bn_mp_clear_multi.c */ 1222 1223/* Start: bn_mp_cmp.c */ 1224#include <tommath.h> 1225#ifdef BN_MP_CMP_C 1226/* LibTomMath, multiple-precision integer library -- Tom St Denis 1227 * 1228 * LibTomMath is a library that provides multiple-precision 1229 * integer arithmetic as well as number theoretic functionality. 1230 * 1231 * The library was designed directly after the MPI library by 1232 * Michael Fromberger but has been written from scratch with 1233 * additional optimizations in place. 1234 * 1235 * The library is free for all purposes without any express 1236 * guarantee it works. 1237 * 1238 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1239 */ 1240 1241/* compare two ints (signed)*/ 1242int 1243mp_cmp (mp_int * a, mp_int * b) 1244{ 1245 /* compare based on sign */ 1246 if (a->sign != b->sign) { 1247 if (a->sign == MP_NEG) { 1248 return MP_LT; 1249 } else { 1250 return MP_GT; 1251 } 1252 } 1253 1254 /* compare digits */ 1255 if (a->sign == MP_NEG) { 1256 /* if negative compare opposite direction */ 1257 return mp_cmp_mag(b, a); 1258 } else { 1259 return mp_cmp_mag(a, b); 1260 } 1261} 1262#endif 1263 1264/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */ 1265/* $Revision: 1.3 $ */ 1266/* $Date: 2006/03/31 14:18:44 $ */ 1267 1268/* End: bn_mp_cmp.c */ 1269 1270/* Start: bn_mp_cmp_d.c */ 1271#include <tommath.h> 1272#ifdef BN_MP_CMP_D_C 1273/* LibTomMath, multiple-precision integer library -- Tom St Denis 1274 * 1275 * LibTomMath is a library that provides multiple-precision 1276 * integer arithmetic as well as number theoretic functionality. 1277 * 1278 * The library was designed directly after the MPI library by 1279 * Michael Fromberger but has been written from scratch with 1280 * additional optimizations in place. 1281 * 1282 * The library is free for all purposes without any express 1283 * guarantee it works. 1284 * 1285 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1286 */ 1287 1288/* compare a digit */ 1289int mp_cmp_d(mp_int * a, mp_digit b) 1290{ 1291 /* compare based on sign */ 1292 if (a->sign == MP_NEG) { 1293 return MP_LT; 1294 } 1295 1296 /* compare based on magnitude */ 1297 if (a->used > 1) { 1298 return MP_GT; 1299 } 1300 1301 /* compare the only digit of a to b */ 1302 if (a->dp[0] > b) { 1303 return MP_GT; 1304 } else if (a->dp[0] < b) { 1305 return MP_LT; 1306 } else { 1307 return MP_EQ; 1308 } 1309} 1310#endif 1311 1312/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */ 1313/* $Revision: 1.3 $ */ 1314/* $Date: 2006/03/31 14:18:44 $ */ 1315 1316/* End: bn_mp_cmp_d.c */ 1317 1318/* Start: bn_mp_cmp_mag.c */ 1319#include <tommath.h> 1320#ifdef BN_MP_CMP_MAG_C 1321/* LibTomMath, multiple-precision integer library -- Tom St Denis 1322 * 1323 * LibTomMath is a library that provides multiple-precision 1324 * integer arithmetic as well as number theoretic functionality. 1325 * 1326 * The library was designed directly after the MPI library by 1327 * Michael Fromberger but has been written from scratch with 1328 * additional optimizations in place. 1329 * 1330 * The library is free for all purposes without any express 1331 * guarantee it works. 1332 * 1333 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1334 */ 1335 1336/* compare maginitude of two ints (unsigned) */ 1337int mp_cmp_mag (mp_int * a, mp_int * b) 1338{ 1339 int n; 1340 mp_digit *tmpa, *tmpb; 1341 1342 /* compare based on # of non-zero digits */ 1343 if (a->used > b->used) { 1344 return MP_GT; 1345 } 1346 1347 if (a->used < b->used) { 1348 return MP_LT; 1349 } 1350 1351 /* alias for a */ 1352 tmpa = a->dp + (a->used - 1); 1353 1354 /* alias for b */ 1355 tmpb = b->dp + (a->used - 1); 1356 1357 /* compare based on digits */ 1358 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { 1359 if (*tmpa > *tmpb) { 1360 return MP_GT; 1361 } 1362 1363 if (*tmpa < *tmpb) { 1364 return MP_LT; 1365 } 1366 } 1367 return MP_EQ; 1368} 1369#endif 1370 1371/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */ 1372/* $Revision: 1.3 $ */ 1373/* $Date: 2006/03/31 14:18:44 $ */ 1374 1375/* End: bn_mp_cmp_mag.c */ 1376 1377/* Start: bn_mp_cnt_lsb.c */ 1378#include <tommath.h> 1379#ifdef BN_MP_CNT_LSB_C 1380/* LibTomMath, multiple-precision integer library -- Tom St Denis 1381 * 1382 * LibTomMath is a library that provides multiple-precision 1383 * integer arithmetic as well as number theoretic functionality. 1384 * 1385 * The library was designed directly after the MPI library by 1386 * Michael Fromberger but has been written from scratch with 1387 * additional optimizations in place. 1388 * 1389 * The library is free for all purposes without any express 1390 * guarantee it works. 1391 * 1392 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1393 */ 1394 1395static const int lnz[16] = { 1396 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 1397}; 1398 1399/* Counts the number of lsbs which are zero before the first zero bit */ 1400int mp_cnt_lsb(mp_int *a) 1401{ 1402 int x; 1403 mp_digit q, qq; 1404 1405 /* easy out */ 1406 if (mp_iszero(a) == 1) { 1407 return 0; 1408 } 1409 1410 /* scan lower digits until non-zero */ 1411 for (x = 0; x < a->used && a->dp[x] == 0; x++); 1412 q = a->dp[x]; 1413 x *= DIGIT_BIT; 1414 1415 /* now scan this digit until a 1 is found */ 1416 if ((q & 1) == 0) { 1417 do { 1418 qq = q & 15; 1419 x += lnz[qq]; 1420 q >>= 4; 1421 } while (qq == 0); 1422 } 1423 return x; 1424} 1425 1426#endif 1427 1428/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */ 1429/* $Revision: 1.3 $ */ 1430/* $Date: 2006/03/31 14:18:44 $ */ 1431 1432/* End: bn_mp_cnt_lsb.c */ 1433 1434/* Start: bn_mp_copy.c */ 1435#include <tommath.h> 1436#ifdef BN_MP_COPY_C 1437/* LibTomMath, multiple-precision integer library -- Tom St Denis 1438 * 1439 * LibTomMath is a library that provides multiple-precision 1440 * integer arithmetic as well as number theoretic functionality. 1441 * 1442 * The library was designed directly after the MPI library by 1443 * Michael Fromberger but has been written from scratch with 1444 * additional optimizations in place. 1445 * 1446 * The library is free for all purposes without any express 1447 * guarantee it works. 1448 * 1449 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1450 */ 1451 1452/* copy, b = a */ 1453int 1454mp_copy (mp_int * a, mp_int * b) 1455{ 1456 int res, n; 1457 1458 /* if dst == src do nothing */ 1459 if (a == b) { 1460 return MP_OKAY; 1461 } 1462 1463 /* grow dest */ 1464 if (b->alloc < a->used) { 1465 if ((res = mp_grow (b, a->used)) != MP_OKAY) { 1466 return res; 1467 } 1468 } 1469 1470 /* zero b and copy the parameters over */ 1471 { 1472 register mp_digit *tmpa, *tmpb; 1473 1474 /* pointer aliases */ 1475 1476 /* source */ 1477 tmpa = a->dp; 1478 1479 /* destination */ 1480 tmpb = b->dp; 1481 1482 /* copy all the digits */ 1483 for (n = 0; n < a->used; n++) { 1484 *tmpb++ = *tmpa++; 1485 } 1486 1487 /* clear high digits */ 1488 for (; n < b->used; n++) { 1489 *tmpb++ = 0; 1490 } 1491 } 1492 1493 /* copy used count and sign */ 1494 b->used = a->used; 1495 b->sign = a->sign; 1496 return MP_OKAY; 1497} 1498#endif 1499 1500/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */ 1501/* $Revision: 1.3 $ */ 1502/* $Date: 2006/03/31 14:18:44 $ */ 1503 1504/* End: bn_mp_copy.c */ 1505 1506/* Start: bn_mp_count_bits.c */ 1507#include <tommath.h> 1508#ifdef BN_MP_COUNT_BITS_C 1509/* LibTomMath, multiple-precision integer library -- Tom St Denis 1510 * 1511 * LibTomMath is a library that provides multiple-precision 1512 * integer arithmetic as well as number theoretic functionality. 1513 * 1514 * The library was designed directly after the MPI library by 1515 * Michael Fromberger but has been written from scratch with 1516 * additional optimizations in place. 1517 * 1518 * The library is free for all purposes without any express 1519 * guarantee it works. 1520 * 1521 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1522 */ 1523 1524/* returns the number of bits in an int */ 1525int 1526mp_count_bits (mp_int * a) 1527{ 1528 int r; 1529 mp_digit q; 1530 1531 /* shortcut */ 1532 if (a->used == 0) { 1533 return 0; 1534 } 1535 1536 /* get number of digits and add that */ 1537 r = (a->used - 1) * DIGIT_BIT; 1538 1539 /* take the last digit and count the bits in it */ 1540 q = a->dp[a->used - 1]; 1541 while (q > ((mp_digit) 0)) { 1542 ++r; 1543 q >>= ((mp_digit) 1); 1544 } 1545 return r; 1546} 1547#endif 1548 1549/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */ 1550/* $Revision: 1.3 $ */ 1551/* $Date: 2006/03/31 14:18:44 $ */ 1552 1553/* End: bn_mp_count_bits.c */ 1554 1555/* Start: bn_mp_div.c */ 1556#include <tommath.h> 1557#ifdef BN_MP_DIV_C 1558/* LibTomMath, multiple-precision integer library -- Tom St Denis 1559 * 1560 * LibTomMath is a library that provides multiple-precision 1561 * integer arithmetic as well as number theoretic functionality. 1562 * 1563 * The library was designed directly after the MPI library by 1564 * Michael Fromberger but has been written from scratch with 1565 * additional optimizations in place. 1566 * 1567 * The library is free for all purposes without any express 1568 * guarantee it works. 1569 * 1570 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1571 */ 1572 1573#ifdef BN_MP_DIV_SMALL 1574 1575/* slower bit-bang division... also smaller */ 1576int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) 1577{ 1578 mp_int ta, tb, tq, q; 1579 int res, n, n2; 1580 1581 /* is divisor zero ? */ 1582 if (mp_iszero (b) == 1) { 1583 return MP_VAL; 1584 } 1585 1586 /* if a < b then q=0, r = a */ 1587 if (mp_cmp_mag (a, b) == MP_LT) { 1588 if (d != NULL) { 1589 res = mp_copy (a, d); 1590 } else { 1591 res = MP_OKAY; 1592 } 1593 if (c != NULL) { 1594 mp_zero (c); 1595 } 1596 return res; 1597 } 1598 1599 /* init our temps */ 1600 if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { 1601 return res; 1602 } 1603 1604 1605 mp_set(&tq, 1); 1606 n = mp_count_bits(a) - mp_count_bits(b); 1607 if (((res = mp_abs(a, &ta)) != MP_OKAY) || 1608 ((res = mp_abs(b, &tb)) != MP_OKAY) || 1609 ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || 1610 ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { 1611 goto LBL_ERR; 1612 } 1613 1614 while (n-- >= 0) { 1615 if (mp_cmp(&tb, &ta) != MP_GT) { 1616 if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || 1617 ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { 1618 goto LBL_ERR; 1619 } 1620 } 1621 if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || 1622 ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { 1623 goto LBL_ERR; 1624 } 1625 } 1626 1627 /* now q == quotient and ta == remainder */ 1628 n = a->sign; 1629 n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); 1630 if (c != NULL) { 1631 mp_exch(c, &q); 1632 c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; 1633 } 1634 if (d != NULL) { 1635 mp_exch(d, &ta); 1636 d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; 1637 } 1638LBL_ERR: 1639 mp_clear_multi(&ta, &tb, &tq, &q, NULL); 1640 return res; 1641} 1642 1643#else 1644 1645/* integer signed division. 1646 * c*b + d == a [e.g. a/b, c=quotient, d=remainder] 1647 * HAC pp.598 Algorithm 14.20 1648 * 1649 * Note that the description in HAC is horribly 1650 * incomplete. For example, it doesn't consider 1651 * the case where digits are removed from 'x' in 1652 * the inner loop. It also doesn't consider the 1653 * case that y has fewer than three digits, etc.. 1654 * 1655 * The overall algorithm is as described as 1656 * 14.20 from HAC but fixed to treat these cases. 1657*/ 1658int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) 1659{ 1660 mp_int q, x, y, t1, t2; 1661 int res, n, t, i, norm, neg; 1662 1663 /* is divisor zero ? */ 1664 if (mp_iszero (b) == 1) { 1665 return MP_VAL; 1666 } 1667 1668 /* if a < b then q=0, r = a */ 1669 if (mp_cmp_mag (a, b) == MP_LT) { 1670 if (d != NULL) { 1671 res = mp_copy (a, d); 1672 } else { 1673 res = MP_OKAY; 1674 } 1675 if (c != NULL) { 1676 mp_zero (c); 1677 } 1678 return res; 1679 } 1680 1681 if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { 1682 return res; 1683 } 1684 q.used = a->used + 2; 1685 1686 if ((res = mp_init (&t1)) != MP_OKAY) { 1687 goto LBL_Q; 1688 } 1689 1690 if ((res = mp_init (&t2)) != MP_OKAY) { 1691 goto LBL_T1; 1692 } 1693 1694 if ((res = mp_init_copy (&x, a)) != MP_OKAY) { 1695 goto LBL_T2; 1696 } 1697 1698 if ((res = mp_init_copy (&y, b)) != MP_OKAY) { 1699 goto LBL_X; 1700 } 1701 1702 /* fix the sign */ 1703 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; 1704 x.sign = y.sign = MP_ZPOS; 1705 1706 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ 1707 norm = mp_count_bits(&y) % DIGIT_BIT; 1708 if (norm < (int)(DIGIT_BIT-1)) { 1709 norm = (DIGIT_BIT-1) - norm; 1710 if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { 1711 goto LBL_Y; 1712 } 1713 if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { 1714 goto LBL_Y; 1715 } 1716 } else { 1717 norm = 0; 1718 } 1719 1720 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ 1721 n = x.used - 1; 1722 t = y.used - 1; 1723 1724 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ 1725 if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ 1726 goto LBL_Y; 1727 } 1728 1729 while (mp_cmp (&x, &y) != MP_LT) { 1730 ++(q.dp[n - t]); 1731 if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { 1732 goto LBL_Y; 1733 } 1734 } 1735 1736 /* reset y by shifting it back down */ 1737 mp_rshd (&y, n - t); 1738 1739 /* step 3. for i from n down to (t + 1) */ 1740 for (i = n; i >= (t + 1); i--) { 1741 if (i > x.used) { 1742 continue; 1743 } 1744 1745 /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 1746 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ 1747 if (x.dp[i] == y.dp[t]) { 1748 q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); 1749 } else { 1750 mp_word tmp; 1751 tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); 1752 tmp |= ((mp_word) x.dp[i - 1]); 1753 tmp /= ((mp_word) y.dp[t]); 1754 if (tmp > (mp_word) MP_MASK) 1755 tmp = MP_MASK; 1756 q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); 1757 } 1758 1759 /* while (q{i-t-1} * (yt * b + y{t-1})) > 1760 xi * b**2 + xi-1 * b + xi-2 1761 1762 do q{i-t-1} -= 1; 1763 */ 1764 q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; 1765 do { 1766 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; 1767 1768 /* find left hand */ 1769 mp_zero (&t1); 1770 t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; 1771 t1.dp[1] = y.dp[t]; 1772 t1.used = 2; 1773 if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { 1774 goto LBL_Y; 1775 } 1776 1777 /* find right hand */ 1778 t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; 1779 t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; 1780 t2.dp[2] = x.dp[i]; 1781 t2.used = 3; 1782 } while (mp_cmp_mag(&t1, &t2) == MP_GT); 1783 1784 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ 1785 if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { 1786 goto LBL_Y; 1787 } 1788 1789 if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { 1790 goto LBL_Y; 1791 } 1792 1793 if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { 1794 goto LBL_Y; 1795 } 1796 1797 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ 1798 if (x.sign == MP_NEG) { 1799 if ((res = mp_copy (&y, &t1)) != MP_OKAY) { 1800 goto LBL_Y; 1801 } 1802 if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { 1803 goto LBL_Y; 1804 } 1805 if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { 1806 goto LBL_Y; 1807 } 1808 1809 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; 1810 } 1811 } 1812 1813 /* now q is the quotient and x is the remainder 1814 * [which we have to normalize] 1815 */ 1816 1817 /* get sign before writing to c */ 1818 x.sign = x.used == 0 ? MP_ZPOS : a->sign; 1819 1820 if (c != NULL) { 1821 mp_clamp (&q); 1822 mp_exch (&q, c); 1823 c->sign = neg; 1824 } 1825 1826 if (d != NULL) { 1827 mp_div_2d (&x, norm, &x, NULL); 1828 mp_exch (&x, d); 1829 } 1830 1831 res = MP_OKAY; 1832 1833LBL_Y:mp_clear (&y); 1834LBL_X:mp_clear (&x); 1835LBL_T2:mp_clear (&t2); 1836LBL_T1:mp_clear (&t1); 1837LBL_Q:mp_clear (&q); 1838 return res; 1839} 1840 1841#endif 1842 1843#endif 1844 1845/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */ 1846/* $Revision: 1.3 $ */ 1847/* $Date: 2006/03/31 14:18:44 $ */ 1848 1849/* End: bn_mp_div.c */ 1850 1851/* Start: bn_mp_div_2.c */ 1852#include <tommath.h> 1853#ifdef BN_MP_DIV_2_C 1854/* LibTomMath, multiple-precision integer library -- Tom St Denis 1855 * 1856 * LibTomMath is a library that provides multiple-precision 1857 * integer arithmetic as well as number theoretic functionality. 1858 * 1859 * The library was designed directly after the MPI library by 1860 * Michael Fromberger but has been written from scratch with 1861 * additional optimizations in place. 1862 * 1863 * The library is free for all purposes without any express 1864 * guarantee it works. 1865 * 1866 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1867 */ 1868 1869/* b = a/2 */ 1870int mp_div_2(mp_int * a, mp_int * b) 1871{ 1872 int x, res, oldused; 1873 1874 /* copy */ 1875 if (b->alloc < a->used) { 1876 if ((res = mp_grow (b, a->used)) != MP_OKAY) { 1877 return res; 1878 } 1879 } 1880 1881 oldused = b->used; 1882 b->used = a->used; 1883 { 1884 register mp_digit r, rr, *tmpa, *tmpb; 1885 1886 /* source alias */ 1887 tmpa = a->dp + b->used - 1; 1888 1889 /* dest alias */ 1890 tmpb = b->dp + b->used - 1; 1891 1892 /* carry */ 1893 r = 0; 1894 for (x = b->used - 1; x >= 0; x--) { 1895 /* get the carry for the next iteration */ 1896 rr = *tmpa & 1; 1897 1898 /* shift the current digit, add in carry and store */ 1899 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); 1900 1901 /* forward carry to next iteration */ 1902 r = rr; 1903 } 1904 1905 /* zero excess digits */ 1906 tmpb = b->dp + b->used; 1907 for (x = b->used; x < oldused; x++) { 1908 *tmpb++ = 0; 1909 } 1910 } 1911 b->sign = a->sign; 1912 mp_clamp (b); 1913 return MP_OKAY; 1914} 1915#endif 1916 1917/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */ 1918/* $Revision: 1.3 $ */ 1919/* $Date: 2006/03/31 14:18:44 $ */ 1920 1921/* End: bn_mp_div_2.c */ 1922 1923/* Start: bn_mp_div_2d.c */ 1924#include <tommath.h> 1925#ifdef BN_MP_DIV_2D_C 1926/* LibTomMath, multiple-precision integer library -- Tom St Denis 1927 * 1928 * LibTomMath is a library that provides multiple-precision 1929 * integer arithmetic as well as number theoretic functionality. 1930 * 1931 * The library was designed directly after the MPI library by 1932 * Michael Fromberger but has been written from scratch with 1933 * additional optimizations in place. 1934 * 1935 * The library is free for all purposes without any express 1936 * guarantee it works. 1937 * 1938 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 1939 */ 1940 1941/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ 1942int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) 1943{ 1944 mp_digit D, r, rr; 1945 int x, res; 1946 mp_int t; 1947 1948 1949 /* if the shift count is <= 0 then we do no work */ 1950 if (b <= 0) { 1951 res = mp_copy (a, c); 1952 if (d != NULL) { 1953 mp_zero (d); 1954 } 1955 return res; 1956 } 1957 1958 if ((res = mp_init (&t)) != MP_OKAY) { 1959 return res; 1960 } 1961 1962 /* get the remainder */ 1963 if (d != NULL) { 1964 if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { 1965 mp_clear (&t); 1966 return res; 1967 } 1968 } 1969 1970 /* copy */ 1971 if ((res = mp_copy (a, c)) != MP_OKAY) { 1972 mp_clear (&t); 1973 return res; 1974 } 1975 1976 /* shift by as many digits in the bit count */ 1977 if (b >= (int)DIGIT_BIT) { 1978 mp_rshd (c, b / DIGIT_BIT); 1979 } 1980 1981 /* shift any bit count < DIGIT_BIT */ 1982 D = (mp_digit) (b % DIGIT_BIT); 1983 if (D != 0) { 1984 register mp_digit *tmpc, mask, shift; 1985 1986 /* mask */ 1987 mask = (((mp_digit)1) << D) - 1; 1988 1989 /* shift for lsb */ 1990 shift = DIGIT_BIT - D; 1991 1992 /* alias */ 1993 tmpc = c->dp + (c->used - 1); 1994 1995 /* carry */ 1996 r = 0; 1997 for (x = c->used - 1; x >= 0; x--) { 1998 /* get the lower bits of this word in a temp */ 1999 rr = *tmpc & mask; 2000 2001 /* shift the current word and mix in the carry bits from the previous word */ 2002 *tmpc = (*tmpc >> D) | (r << shift); 2003 --tmpc; 2004 2005 /* set the carry to the carry bits of the current word found above */ 2006 r = rr; 2007 } 2008 } 2009 mp_clamp (c); 2010 if (d != NULL) { 2011 mp_exch (&t, d); 2012 } 2013 mp_clear (&t); 2014 return MP_OKAY; 2015} 2016#endif 2017 2018/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */ 2019/* $Revision: 1.3 $ */ 2020/* $Date: 2006/03/31 14:18:44 $ */ 2021 2022/* End: bn_mp_div_2d.c */ 2023 2024/* Start: bn_mp_div_3.c */ 2025#include <tommath.h> 2026#ifdef BN_MP_DIV_3_C 2027/* LibTomMath, multiple-precision integer library -- Tom St Denis 2028 * 2029 * LibTomMath is a library that provides multiple-precision 2030 * integer arithmetic as well as number theoretic functionality. 2031 * 2032 * The library was designed directly after the MPI library by 2033 * Michael Fromberger but has been written from scratch with 2034 * additional optimizations in place. 2035 * 2036 * The library is free for all purposes without any express 2037 * guarantee it works. 2038 * 2039 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2040 */ 2041 2042/* divide by three (based on routine from MPI and the GMP manual) */ 2043int 2044mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) 2045{ 2046 mp_int q; 2047 mp_word w, t; 2048 mp_digit b; 2049 int res, ix; 2050 2051 /* b = 2**DIGIT_BIT / 3 */ 2052 b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3); 2053 2054 if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { 2055 return res; 2056 } 2057 2058 q.used = a->used; 2059 q.sign = a->sign; 2060 w = 0; 2061 for (ix = a->used - 1; ix >= 0; ix--) { 2062 w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); 2063 2064 if (w >= 3) { 2065 /* multiply w by [1/3] */ 2066 t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); 2067 2068 /* now subtract 3 * [w/3] from w, to get the remainder */ 2069 w -= t+t+t; 2070 2071 /* fixup the remainder as required since 2072 * the optimization is not exact. 2073 */ 2074 while (w >= 3) { 2075 t += 1; 2076 w -= 3; 2077 } 2078 } else { 2079 t = 0; 2080 } 2081 q.dp[ix] = (mp_digit)t; 2082 } 2083 2084 /* [optional] store the remainder */ 2085 if (d != NULL) { 2086 *d = (mp_digit)w; 2087 } 2088 2089 /* [optional] store the quotient */ 2090 if (c != NULL) { 2091 mp_clamp(&q); 2092 mp_exch(&q, c); 2093 } 2094 mp_clear(&q); 2095 2096 return res; 2097} 2098 2099#endif 2100 2101/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */ 2102/* $Revision: 1.3 $ */ 2103/* $Date: 2006/03/31 14:18:44 $ */ 2104 2105/* End: bn_mp_div_3.c */ 2106 2107/* Start: bn_mp_div_d.c */ 2108#include <tommath.h> 2109#ifdef BN_MP_DIV_D_C 2110/* LibTomMath, multiple-precision integer library -- Tom St Denis 2111 * 2112 * LibTomMath is a library that provides multiple-precision 2113 * integer arithmetic as well as number theoretic functionality. 2114 * 2115 * The library was designed directly after the MPI library by 2116 * Michael Fromberger but has been written from scratch with 2117 * additional optimizations in place. 2118 * 2119 * The library is free for all purposes without any express 2120 * guarantee it works. 2121 * 2122 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2123 */ 2124 2125static int s_is_power_of_two(mp_digit b, int *p) 2126{ 2127 int x; 2128 2129 for (x = 1; x < DIGIT_BIT; x++) { 2130 if (b == (((mp_digit)1)<<x)) { 2131 *p = x; 2132 return 1; 2133 } 2134 } 2135 return 0; 2136} 2137 2138/* single digit division (based on routine from MPI) */ 2139int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) 2140{ 2141 mp_int q; 2142 mp_word w; 2143 mp_digit t; 2144 int res, ix; 2145 2146 /* cannot divide by zero */ 2147 if (b == 0) { 2148 return MP_VAL; 2149 } 2150 2151 /* quick outs */ 2152 if (b == 1 || mp_iszero(a) == 1) { 2153 if (d != NULL) { 2154 *d = 0; 2155 } 2156 if (c != NULL) { 2157 return mp_copy(a, c); 2158 } 2159 return MP_OKAY; 2160 } 2161 2162 /* power of two ? */ 2163 if (s_is_power_of_two(b, &ix) == 1) { 2164 if (d != NULL) { 2165 *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1); 2166 } 2167 if (c != NULL) { 2168 return mp_div_2d(a, ix, c, NULL); 2169 } 2170 return MP_OKAY; 2171 } 2172 2173#ifdef BN_MP_DIV_3_C 2174 /* three? */ 2175 if (b == 3) { 2176 return mp_div_3(a, c, d); 2177 } 2178#endif 2179 2180 /* no easy answer [c'est la vie]. Just division */ 2181 if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { 2182 return res; 2183 } 2184 2185 q.used = a->used; 2186 q.sign = a->sign; 2187 w = 0; 2188 for (ix = a->used - 1; ix >= 0; ix--) { 2189 w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); 2190 2191 if (w >= b) { 2192 t = (mp_digit)(w / b); 2193 w -= ((mp_word)t) * ((mp_word)b); 2194 } else { 2195 t = 0; 2196 } 2197 q.dp[ix] = (mp_digit)t; 2198 } 2199 2200 if (d != NULL) { 2201 *d = (mp_digit)w; 2202 } 2203 2204 if (c != NULL) { 2205 mp_clamp(&q); 2206 mp_exch(&q, c); 2207 } 2208 mp_clear(&q); 2209 2210 return res; 2211} 2212 2213#endif 2214 2215/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */ 2216/* $Revision: 1.3 $ */ 2217/* $Date: 2006/03/31 14:18:44 $ */ 2218 2219/* End: bn_mp_div_d.c */ 2220 2221/* Start: bn_mp_dr_is_modulus.c */ 2222#include <tommath.h> 2223#ifdef BN_MP_DR_IS_MODULUS_C 2224/* LibTomMath, multiple-precision integer library -- Tom St Denis 2225 * 2226 * LibTomMath is a library that provides multiple-precision 2227 * integer arithmetic as well as number theoretic functionality. 2228 * 2229 * The library was designed directly after the MPI library by 2230 * Michael Fromberger but has been written from scratch with 2231 * additional optimizations in place. 2232 * 2233 * The library is free for all purposes without any express 2234 * guarantee it works. 2235 * 2236 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2237 */ 2238 2239/* determines if a number is a valid DR modulus */ 2240int mp_dr_is_modulus(mp_int *a) 2241{ 2242 int ix; 2243 2244 /* must be at least two digits */ 2245 if (a->used < 2) { 2246 return 0; 2247 } 2248 2249 /* must be of the form b**k - a [a <= b] so all 2250 * but the first digit must be equal to -1 (mod b). 2251 */ 2252 for (ix = 1; ix < a->used; ix++) { 2253 if (a->dp[ix] != MP_MASK) { 2254 return 0; 2255 } 2256 } 2257 return 1; 2258} 2259 2260#endif 2261 2262/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */ 2263/* $Revision: 1.3 $ */ 2264/* $Date: 2006/03/31 14:18:44 $ */ 2265 2266/* End: bn_mp_dr_is_modulus.c */ 2267 2268/* Start: bn_mp_dr_reduce.c */ 2269#include <tommath.h> 2270#ifdef BN_MP_DR_REDUCE_C 2271/* LibTomMath, multiple-precision integer library -- Tom St Denis 2272 * 2273 * LibTomMath is a library that provides multiple-precision 2274 * integer arithmetic as well as number theoretic functionality. 2275 * 2276 * The library was designed directly after the MPI library by 2277 * Michael Fromberger but has been written from scratch with 2278 * additional optimizations in place. 2279 * 2280 * The library is free for all purposes without any express 2281 * guarantee it works. 2282 * 2283 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2284 */ 2285 2286/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. 2287 * 2288 * Based on algorithm from the paper 2289 * 2290 * "Generating Efficient Primes for Discrete Log Cryptosystems" 2291 * Chae Hoon Lim, Pil Joong Lee, 2292 * POSTECH Information Research Laboratories 2293 * 2294 * The modulus must be of a special format [see manual] 2295 * 2296 * Has been modified to use algorithm 7.10 from the LTM book instead 2297 * 2298 * Input x must be in the range 0 <= x <= (n-1)**2 2299 */ 2300int 2301mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) 2302{ 2303 int err, i, m; 2304 mp_word r; 2305 mp_digit mu, *tmpx1, *tmpx2; 2306 2307 /* m = digits in modulus */ 2308 m = n->used; 2309 2310 /* ensure that "x" has at least 2m digits */ 2311 if (x->alloc < m + m) { 2312 if ((err = mp_grow (x, m + m)) != MP_OKAY) { 2313 return err; 2314 } 2315 } 2316 2317/* top of loop, this is where the code resumes if 2318 * another reduction pass is required. 2319 */ 2320top: 2321 /* aliases for digits */ 2322 /* alias for lower half of x */ 2323 tmpx1 = x->dp; 2324 2325 /* alias for upper half of x, or x/B**m */ 2326 tmpx2 = x->dp + m; 2327 2328 /* set carry to zero */ 2329 mu = 0; 2330 2331 /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ 2332 for (i = 0; i < m; i++) { 2333 r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; 2334 *tmpx1++ = (mp_digit)(r & MP_MASK); 2335 mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT)); 2336 } 2337 2338 /* set final carry */ 2339 *tmpx1++ = mu; 2340 2341 /* zero words above m */ 2342 for (i = m + 1; i < x->used; i++) { 2343 *tmpx1++ = 0; 2344 } 2345 2346 /* clamp, sub and return */ 2347 mp_clamp (x); 2348 2349 /* if x >= n then subtract and reduce again 2350 * Each successive "recursion" makes the input smaller and smaller. 2351 */ 2352 if (mp_cmp_mag (x, n) != MP_LT) { 2353 s_mp_sub(x, n, x); 2354 goto top; 2355 } 2356 return MP_OKAY; 2357} 2358#endif 2359 2360/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */ 2361/* $Revision: 1.3 $ */ 2362/* $Date: 2006/03/31 14:18:44 $ */ 2363 2364/* End: bn_mp_dr_reduce.c */ 2365 2366/* Start: bn_mp_dr_setup.c */ 2367#include <tommath.h> 2368#ifdef BN_MP_DR_SETUP_C 2369/* LibTomMath, multiple-precision integer library -- Tom St Denis 2370 * 2371 * LibTomMath is a library that provides multiple-precision 2372 * integer arithmetic as well as number theoretic functionality. 2373 * 2374 * The library was designed directly after the MPI library by 2375 * Michael Fromberger but has been written from scratch with 2376 * additional optimizations in place. 2377 * 2378 * The library is free for all purposes without any express 2379 * guarantee it works. 2380 * 2381 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2382 */ 2383 2384/* determines the setup value */ 2385void mp_dr_setup(mp_int *a, mp_digit *d) 2386{ 2387 /* the casts are required if DIGIT_BIT is one less than 2388 * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] 2389 */ 2390 *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 2391 ((mp_word)a->dp[0])); 2392} 2393 2394#endif 2395 2396/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */ 2397/* $Revision: 1.3 $ */ 2398/* $Date: 2006/03/31 14:18:44 $ */ 2399 2400/* End: bn_mp_dr_setup.c */ 2401 2402/* Start: bn_mp_exch.c */ 2403#include <tommath.h> 2404#ifdef BN_MP_EXCH_C 2405/* LibTomMath, multiple-precision integer library -- Tom St Denis 2406 * 2407 * LibTomMath is a library that provides multiple-precision 2408 * integer arithmetic as well as number theoretic functionality. 2409 * 2410 * The library was designed directly after the MPI library by 2411 * Michael Fromberger but has been written from scratch with 2412 * additional optimizations in place. 2413 * 2414 * The library is free for all purposes without any express 2415 * guarantee it works. 2416 * 2417 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2418 */ 2419 2420/* swap the elements of two integers, for cases where you can't simply swap the 2421 * mp_int pointers around 2422 */ 2423void 2424mp_exch (mp_int * a, mp_int * b) 2425{ 2426 mp_int t; 2427 2428 t = *a; 2429 *a = *b; 2430 *b = t; 2431} 2432#endif 2433 2434/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */ 2435/* $Revision: 1.3 $ */ 2436/* $Date: 2006/03/31 14:18:44 $ */ 2437 2438/* End: bn_mp_exch.c */ 2439 2440/* Start: bn_mp_expt_d.c */ 2441#include <tommath.h> 2442#ifdef BN_MP_EXPT_D_C 2443/* LibTomMath, multiple-precision integer library -- Tom St Denis 2444 * 2445 * LibTomMath is a library that provides multiple-precision 2446 * integer arithmetic as well as number theoretic functionality. 2447 * 2448 * The library was designed directly after the MPI library by 2449 * Michael Fromberger but has been written from scratch with 2450 * additional optimizations in place. 2451 * 2452 * The library is free for all purposes without any express 2453 * guarantee it works. 2454 * 2455 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2456 */ 2457 2458/* calculate c = a**b using a square-multiply algorithm */ 2459int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) 2460{ 2461 int res, x; 2462 mp_int g; 2463 2464 if ((res = mp_init_copy (&g, a)) != MP_OKAY) { 2465 return res; 2466 } 2467 2468 /* set initial result */ 2469 mp_set (c, 1); 2470 2471 for (x = 0; x < (int) DIGIT_BIT; x++) { 2472 /* square */ 2473 if ((res = mp_sqr (c, c)) != MP_OKAY) { 2474 mp_clear (&g); 2475 return res; 2476 } 2477 2478 /* if the bit is set multiply */ 2479 if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { 2480 if ((res = mp_mul (c, &g, c)) != MP_OKAY) { 2481 mp_clear (&g); 2482 return res; 2483 } 2484 } 2485 2486 /* shift to next bit */ 2487 b <<= 1; 2488 } 2489 2490 mp_clear (&g); 2491 return MP_OKAY; 2492} 2493#endif 2494 2495/* $Source: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */ 2496/* $Revision: 1.3 $ */ 2497/* $Date: 2006/03/31 14:18:44 $ */ 2498 2499/* End: bn_mp_expt_d.c */ 2500 2501/* Start: bn_mp_exptmod.c */ 2502#include <tommath.h> 2503#ifdef BN_MP_EXPTMOD_C 2504/* LibTomMath, multiple-precision integer library -- Tom St Denis 2505 * 2506 * LibTomMath is a library that provides multiple-precision 2507 * integer arithmetic as well as number theoretic functionality. 2508 * 2509 * The library was designed directly after the MPI library by 2510 * Michael Fromberger but has been written from scratch with 2511 * additional optimizations in place. 2512 * 2513 * The library is free for all purposes without any express 2514 * guarantee it works. 2515 * 2516 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2517 */ 2518 2519 2520/* this is a shell function that calls either the normal or Montgomery 2521 * exptmod functions. Originally the call to the montgomery code was 2522 * embedded in the normal function but that wasted alot of stack space 2523 * for nothing (since 99% of the time the Montgomery code would be called) 2524 */ 2525int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) 2526{ 2527 int dr; 2528 2529 /* modulus P must be positive */ 2530 if (P->sign == MP_NEG) { 2531 return MP_VAL; 2532 } 2533 2534 /* if exponent X is negative we have to recurse */ 2535 if (X->sign == MP_NEG) { 2536#ifdef BN_MP_INVMOD_C 2537 mp_int tmpG, tmpX; 2538 int err; 2539 2540 /* first compute 1/G mod P */ 2541 if ((err = mp_init(&tmpG)) != MP_OKAY) { 2542 return err; 2543 } 2544 if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { 2545 mp_clear(&tmpG); 2546 return err; 2547 } 2548 2549 /* now get |X| */ 2550 if ((err = mp_init(&tmpX)) != MP_OKAY) { 2551 mp_clear(&tmpG); 2552 return err; 2553 } 2554 if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { 2555 mp_clear_multi(&tmpG, &tmpX, NULL); 2556 return err; 2557 } 2558 2559 /* and now compute (1/G)**|X| instead of G**X [X < 0] */ 2560 err = mp_exptmod(&tmpG, &tmpX, P, Y); 2561 mp_clear_multi(&tmpG, &tmpX, NULL); 2562 return err; 2563#else 2564 /* no invmod */ 2565 return MP_VAL; 2566#endif 2567 } 2568 2569/* modified diminished radix reduction */ 2570#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) 2571 if (mp_reduce_is_2k_l(P) == MP_YES) { 2572 return s_mp_exptmod(G, X, P, Y, 1); 2573 } 2574#endif 2575 2576#ifdef BN_MP_DR_IS_MODULUS_C 2577 /* is it a DR modulus? */ 2578 dr = mp_dr_is_modulus(P); 2579#else 2580 /* default to no */ 2581 dr = 0; 2582#endif 2583 2584#ifdef BN_MP_REDUCE_IS_2K_C 2585 /* if not, is it a unrestricted DR modulus? */ 2586 if (dr == 0) { 2587 dr = mp_reduce_is_2k(P) << 1; 2588 } 2589#endif 2590 2591 /* if the modulus is odd or dr != 0 use the montgomery method */ 2592#ifdef BN_MP_EXPTMOD_FAST_C 2593 if (mp_isodd (P) == 1 || dr != 0) { 2594 return mp_exptmod_fast (G, X, P, Y, dr); 2595 } else { 2596#endif 2597#ifdef BN_S_MP_EXPTMOD_C 2598 /* otherwise use the generic Barrett reduction technique */ 2599 return s_mp_exptmod (G, X, P, Y, 0); 2600#else 2601 /* no exptmod for evens */ 2602 return MP_VAL; 2603#endif 2604#ifdef BN_MP_EXPTMOD_FAST_C 2605 } 2606#endif 2607} 2608 2609#endif 2610 2611/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */ 2612/* $Revision: 1.4 $ */ 2613/* $Date: 2006/03/31 14:18:44 $ */ 2614 2615/* End: bn_mp_exptmod.c */ 2616 2617/* Start: bn_mp_exptmod_fast.c */ 2618#include <tommath.h> 2619#ifdef BN_MP_EXPTMOD_FAST_C 2620/* LibTomMath, multiple-precision integer library -- Tom St Denis 2621 * 2622 * LibTomMath is a library that provides multiple-precision 2623 * integer arithmetic as well as number theoretic functionality. 2624 * 2625 * The library was designed directly after the MPI library by 2626 * Michael Fromberger but has been written from scratch with 2627 * additional optimizations in place. 2628 * 2629 * The library is free for all purposes without any express 2630 * guarantee it works. 2631 * 2632 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2633 */ 2634 2635/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 2636 * 2637 * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. 2638 * The value of k changes based on the size of the exponent. 2639 * 2640 * Uses Montgomery or Diminished Radix reduction [whichever appropriate] 2641 */ 2642 2643#ifdef MP_LOW_MEM 2644 #define TAB_SIZE 32 2645#else 2646 #define TAB_SIZE 256 2647#endif 2648 2649int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) 2650{ 2651 mp_int M[TAB_SIZE], res; 2652 mp_digit buf, mp; 2653 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; 2654 2655 /* use a pointer to the reduction algorithm. This allows us to use 2656 * one of many reduction algorithms without modding the guts of 2657 * the code with if statements everywhere. 2658 */ 2659 int (*redux)(mp_int*,mp_int*,mp_digit); 2660 2661 /* find window size */ 2662 x = mp_count_bits (X); 2663 if (x <= 7) { 2664 winsize = 2; 2665 } else if (x <= 36) { 2666 winsize = 3; 2667 } else if (x <= 140) { 2668 winsize = 4; 2669 } else if (x <= 450) { 2670 winsize = 5; 2671 } else if (x <= 1303) { 2672 winsize = 6; 2673 } else if (x <= 3529) { 2674 winsize = 7; 2675 } else { 2676 winsize = 8; 2677 } 2678 2679#ifdef MP_LOW_MEM 2680 if (winsize > 5) { 2681 winsize = 5; 2682 } 2683#endif 2684 2685 /* init M array */ 2686 /* init first cell */ 2687 if ((err = mp_init(&M[1])) != MP_OKAY) { 2688 return err; 2689 } 2690 2691 /* now init the second half of the array */ 2692 for (x = 1<<(winsize-1); x < (1 << winsize); x++) { 2693 if ((err = mp_init(&M[x])) != MP_OKAY) { 2694 for (y = 1<<(winsize-1); y < x; y++) { 2695 mp_clear (&M[y]); 2696 } 2697 mp_clear(&M[1]); 2698 return err; 2699 } 2700 } 2701 2702 /* determine and setup reduction code */ 2703 if (redmode == 0) { 2704#ifdef BN_MP_MONTGOMERY_SETUP_C 2705 /* now setup montgomery */ 2706 if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { 2707 goto LBL_M; 2708 } 2709#else 2710 err = MP_VAL; 2711 goto LBL_M; 2712#endif 2713 2714 /* automatically pick the comba one if available (saves quite a few calls/ifs) */ 2715#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C 2716 if (((P->used * 2 + 1) < MP_WARRAY) && 2717 P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { 2718 redux = fast_mp_montgomery_reduce; 2719 } else 2720#endif 2721 { 2722#ifdef BN_MP_MONTGOMERY_REDUCE_C 2723 /* use slower baseline Montgomery method */ 2724 redux = mp_montgomery_reduce; 2725#else 2726 err = MP_VAL; 2727 goto LBL_M; 2728#endif 2729 } 2730 } else if (redmode == 1) { 2731#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) 2732 /* setup DR reduction for moduli of the form B**k - b */ 2733 mp_dr_setup(P, &mp); 2734 redux = mp_dr_reduce; 2735#else 2736 err = MP_VAL; 2737 goto LBL_M; 2738#endif 2739 } else { 2740#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) 2741 /* setup DR reduction for moduli of the form 2**k - b */ 2742 if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { 2743 goto LBL_M; 2744 } 2745 redux = mp_reduce_2k; 2746#else 2747 err = MP_VAL; 2748 goto LBL_M; 2749#endif 2750 } 2751 2752 /* setup result */ 2753 if ((err = mp_init (&res)) != MP_OKAY) { 2754 goto LBL_M; 2755 } 2756 2757 /* create M table 2758 * 2759 2760 * 2761 * The first half of the table is not computed though accept for M[0] and M[1] 2762 */ 2763 2764 if (redmode == 0) { 2765#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C 2766 /* now we need R mod m */ 2767 if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { 2768 goto LBL_RES; 2769 } 2770#else 2771 err = MP_VAL; 2772 goto LBL_RES; 2773#endif 2774 2775 /* now set M[1] to G * R mod m */ 2776 if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { 2777 goto LBL_RES; 2778 } 2779 } else { 2780 mp_set(&res, 1); 2781 if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { 2782 goto LBL_RES; 2783 } 2784 } 2785 2786 /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ 2787 if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { 2788 goto LBL_RES; 2789 } 2790 2791 for (x = 0; x < (winsize - 1); x++) { 2792 if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { 2793 goto LBL_RES; 2794 } 2795 if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { 2796 goto LBL_RES; 2797 } 2798 } 2799 2800 /* create upper table */ 2801 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { 2802 if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { 2803 goto LBL_RES; 2804 } 2805 if ((err = redux (&M[x], P, mp)) != MP_OKAY) { 2806 goto LBL_RES; 2807 } 2808 } 2809 2810 /* set initial mode and bit cnt */ 2811 mode = 0; 2812 bitcnt = 1; 2813 buf = 0; 2814 digidx = X->used - 1; 2815 bitcpy = 0; 2816 bitbuf = 0; 2817 2818 for (;;) { 2819 /* grab next digit as required */ 2820 if (--bitcnt == 0) { 2821 /* if digidx == -1 we are out of digits so break */ 2822 if (digidx == -1) { 2823 break; 2824 } 2825 /* read next digit and reset bitcnt */ 2826 buf = X->dp[digidx--]; 2827 bitcnt = (int)DIGIT_BIT; 2828 } 2829 2830 /* grab the next msb from the exponent */ 2831 y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 2832 buf <<= (mp_digit)1; 2833 2834 /* if the bit is zero and mode == 0 then we ignore it 2835 * These represent the leading zero bits before the first 1 bit 2836 * in the exponent. Technically this opt is not required but it 2837 * does lower the # of trivial squaring/reductions used 2838 */ 2839 if (mode == 0 && y == 0) { 2840 continue; 2841 } 2842 2843 /* if the bit is zero and mode == 1 then we square */ 2844 if (mode == 1 && y == 0) { 2845 if ((err = mp_sqr (&res, &res)) != MP_OKAY) { 2846 goto LBL_RES; 2847 } 2848 if ((err = redux (&res, P, mp)) != MP_OKAY) { 2849 goto LBL_RES; 2850 } 2851 continue; 2852 } 2853 2854 /* else we add it to the window */ 2855 bitbuf |= (y << (winsize - ++bitcpy)); 2856 mode = 2; 2857 2858 if (bitcpy == winsize) { 2859 /* ok window is filled so square as required and multiply */ 2860 /* square first */ 2861 for (x = 0; x < winsize; x++) { 2862 if ((err = mp_sqr (&res, &res)) != MP_OKAY) { 2863 goto LBL_RES; 2864 } 2865 if ((err = redux (&res, P, mp)) != MP_OKAY) { 2866 goto LBL_RES; 2867 } 2868 } 2869 2870 /* then multiply */ 2871 if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { 2872 goto LBL_RES; 2873 } 2874 if ((err = redux (&res, P, mp)) != MP_OKAY) { 2875 goto LBL_RES; 2876 } 2877 2878 /* empty window and reset */ 2879 bitcpy = 0; 2880 bitbuf = 0; 2881 mode = 1; 2882 } 2883 } 2884 2885 /* if bits remain then square/multiply */ 2886 if (mode == 2 && bitcpy > 0) { 2887 /* square then multiply if the bit is set */ 2888 for (x = 0; x < bitcpy; x++) { 2889 if ((err = mp_sqr (&res, &res)) != MP_OKAY) { 2890 goto LBL_RES; 2891 } 2892 if ((err = redux (&res, P, mp)) != MP_OKAY) { 2893 goto LBL_RES; 2894 } 2895 2896 /* get next bit of the window */ 2897 bitbuf <<= 1; 2898 if ((bitbuf & (1 << winsize)) != 0) { 2899 /* then multiply */ 2900 if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { 2901 goto LBL_RES; 2902 } 2903 if ((err = redux (&res, P, mp)) != MP_OKAY) { 2904 goto LBL_RES; 2905 } 2906 } 2907 } 2908 } 2909 2910 if (redmode == 0) { 2911 /* fixup result if Montgomery reduction is used 2912 * recall that any value in a Montgomery system is 2913 * actually multiplied by R mod n. So we have 2914 * to reduce one more time to cancel out the factor 2915 * of R. 2916 */ 2917 if ((err = redux(&res, P, mp)) != MP_OKAY) { 2918 goto LBL_RES; 2919 } 2920 } 2921 2922 /* swap res with Y */ 2923 mp_exch (&res, Y); 2924 err = MP_OKAY; 2925LBL_RES:mp_clear (&res); 2926LBL_M: 2927 mp_clear(&M[1]); 2928 for (x = 1<<(winsize-1); x < (1 << winsize); x++) { 2929 mp_clear (&M[x]); 2930 } 2931 return err; 2932} 2933#endif 2934 2935 2936/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */ 2937/* $Revision: 1.3 $ */ 2938/* $Date: 2006/03/31 14:18:44 $ */ 2939 2940/* End: bn_mp_exptmod_fast.c */ 2941 2942/* Start: bn_mp_exteuclid.c */ 2943#include <tommath.h> 2944#ifdef BN_MP_EXTEUCLID_C 2945/* LibTomMath, multiple-precision integer library -- Tom St Denis 2946 * 2947 * LibTomMath is a library that provides multiple-precision 2948 * integer arithmetic as well as number theoretic functionality. 2949 * 2950 * The library was designed directly after the MPI library by 2951 * Michael Fromberger but has been written from scratch with 2952 * additional optimizations in place. 2953 * 2954 * The library is free for all purposes without any express 2955 * guarantee it works. 2956 * 2957 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 2958 */ 2959 2960/* Extended euclidean algorithm of (a, b) produces 2961 a*u1 + b*u2 = u3 2962 */ 2963int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) 2964{ 2965 mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; 2966 int err; 2967 2968 if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { 2969 return err; 2970 } 2971 2972 /* initialize, (u1,u2,u3) = (1,0,a) */ 2973 mp_set(&u1, 1); 2974 if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } 2975 2976 /* initialize, (v1,v2,v3) = (0,1,b) */ 2977 mp_set(&v2, 1); 2978 if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } 2979 2980 /* loop while v3 != 0 */ 2981 while (mp_iszero(&v3) == MP_NO) { 2982 /* q = u3/v3 */ 2983 if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } 2984 2985 /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ 2986 if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } 2987 if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } 2988 if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } 2989 if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } 2990 if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } 2991 if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } 2992 2993 /* (u1,u2,u3) = (v1,v2,v3) */ 2994 if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } 2995 if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } 2996 if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } 2997 2998 /* (v1,v2,v3) = (t1,t2,t3) */ 2999 if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } 3000 if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } 3001 if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } 3002 } 3003 3004 /* make sure U3 >= 0 */ 3005 if (u3.sign == MP_NEG) { 3006 mp_neg(&u1, &u1); 3007 mp_neg(&u2, &u2); 3008 mp_neg(&u3, &u3); 3009 } 3010 3011 /* copy result out */ 3012 if (U1 != NULL) { mp_exch(U1, &u1); } 3013 if (U2 != NULL) { mp_exch(U2, &u2); } 3014 if (U3 != NULL) { mp_exch(U3, &u3); } 3015 3016 err = MP_OKAY; 3017_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); 3018 return err; 3019} 3020#endif 3021 3022/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */ 3023/* $Revision: 1.3 $ */ 3024/* $Date: 2006/03/31 14:18:44 $ */ 3025 3026/* End: bn_mp_exteuclid.c */ 3027 3028/* Start: bn_mp_fread.c */ 3029#include <tommath.h> 3030#ifdef BN_MP_FREAD_C 3031/* LibTomMath, multiple-precision integer library -- Tom St Denis 3032 * 3033 * LibTomMath is a library that provides multiple-precision 3034 * integer arithmetic as well as number theoretic functionality. 3035 * 3036 * The library was designed directly after the MPI library by 3037 * Michael Fromberger but has been written from scratch with 3038 * additional optimizations in place. 3039 * 3040 * The library is free for all purposes without any express 3041 * guarantee it works. 3042 * 3043 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3044 */ 3045 3046/* read a bigint from a file stream in ASCII */ 3047int mp_fread(mp_int *a, int radix, FILE *stream) 3048{ 3049 int err, ch, neg, y; 3050 3051 /* clear a */ 3052 mp_zero(a); 3053 3054 /* if first digit is - then set negative */ 3055 ch = fgetc(stream); 3056 if (ch == '-') { 3057 neg = MP_NEG; 3058 ch = fgetc(stream); 3059 } else { 3060 neg = MP_ZPOS; 3061 } 3062 3063 for (;;) { 3064 /* find y in the radix map */ 3065 for (y = 0; y < radix; y++) { 3066 if (mp_s_rmap[y] == ch) { 3067 break; 3068 } 3069 } 3070 if (y == radix) { 3071 break; 3072 } 3073 3074 /* shift up and add */ 3075 if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { 3076 return err; 3077 } 3078 if ((err = mp_add_d(a, y, a)) != MP_OKAY) { 3079 return err; 3080 } 3081 3082 ch = fgetc(stream); 3083 } 3084 if (mp_cmp_d(a, 0) != MP_EQ) { 3085 a->sign = neg; 3086 } 3087 3088 return MP_OKAY; 3089} 3090 3091#endif 3092 3093/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */ 3094/* $Revision: 1.3 $ */ 3095/* $Date: 2006/03/31 14:18:44 $ */ 3096 3097/* End: bn_mp_fread.c */ 3098 3099/* Start: bn_mp_fwrite.c */ 3100#include <tommath.h> 3101#ifdef BN_MP_FWRITE_C 3102/* LibTomMath, multiple-precision integer library -- Tom St Denis 3103 * 3104 * LibTomMath is a library that provides multiple-precision 3105 * integer arithmetic as well as number theoretic functionality. 3106 * 3107 * The library was designed directly after the MPI library by 3108 * Michael Fromberger but has been written from scratch with 3109 * additional optimizations in place. 3110 * 3111 * The library is free for all purposes without any express 3112 * guarantee it works. 3113 * 3114 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3115 */ 3116 3117int mp_fwrite(mp_int *a, int radix, FILE *stream) 3118{ 3119 char *buf; 3120 int err, len, x; 3121 3122 if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) { 3123 return err; 3124 } 3125 3126 buf = OPT_CAST(char) XMALLOC (len); 3127 if (buf == NULL) { 3128 return MP_MEM; 3129 } 3130 3131 if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { 3132 XFREE (buf); 3133 return err; 3134 } 3135 3136 for (x = 0; x < len; x++) { 3137 if (fputc(buf[x], stream) == EOF) { 3138 XFREE (buf); 3139 return MP_VAL; 3140 } 3141 } 3142 3143 XFREE (buf); 3144 return MP_OKAY; 3145} 3146 3147#endif 3148 3149/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */ 3150/* $Revision: 1.3 $ */ 3151/* $Date: 2006/03/31 14:18:44 $ */ 3152 3153/* End: bn_mp_fwrite.c */ 3154 3155/* Start: bn_mp_gcd.c */ 3156#include <tommath.h> 3157#ifdef BN_MP_GCD_C 3158/* LibTomMath, multiple-precision integer library -- Tom St Denis 3159 * 3160 * LibTomMath is a library that provides multiple-precision 3161 * integer arithmetic as well as number theoretic functionality. 3162 * 3163 * The library was designed directly after the MPI library by 3164 * Michael Fromberger but has been written from scratch with 3165 * additional optimizations in place. 3166 * 3167 * The library is free for all purposes without any express 3168 * guarantee it works. 3169 * 3170 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3171 */ 3172 3173/* Greatest Common Divisor using the binary method */ 3174int mp_gcd (mp_int * a, mp_int * b, mp_int * c) 3175{ 3176 mp_int u, v; 3177 int k, u_lsb, v_lsb, res; 3178 3179 /* either zero than gcd is the largest */ 3180 if (mp_iszero (a) == MP_YES) { 3181 return mp_abs (b, c); 3182 } 3183 if (mp_iszero (b) == MP_YES) { 3184 return mp_abs (a, c); 3185 } 3186 3187 /* get copies of a and b we can modify */ 3188 if ((res = mp_init_copy (&u, a)) != MP_OKAY) { 3189 return res; 3190 } 3191 3192 if ((res = mp_init_copy (&v, b)) != MP_OKAY) { 3193 goto LBL_U; 3194 } 3195 3196 /* must be positive for the remainder of the algorithm */ 3197 u.sign = v.sign = MP_ZPOS; 3198 3199 /* B1. Find the common power of two for u and v */ 3200 u_lsb = mp_cnt_lsb(&u); 3201 v_lsb = mp_cnt_lsb(&v); 3202 k = MIN(u_lsb, v_lsb); 3203 3204 if (k > 0) { 3205 /* divide the power of two out */ 3206 if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { 3207 goto LBL_V; 3208 } 3209 3210 if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { 3211 goto LBL_V; 3212 } 3213 } 3214 3215 /* divide any remaining factors of two out */ 3216 if (u_lsb != k) { 3217 if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { 3218 goto LBL_V; 3219 } 3220 } 3221 3222 if (v_lsb != k) { 3223 if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { 3224 goto LBL_V; 3225 } 3226 } 3227 3228 while (mp_iszero(&v) == 0) { 3229 /* make sure v is the largest */ 3230 if (mp_cmp_mag(&u, &v) == MP_GT) { 3231 /* swap u and v to make sure v is >= u */ 3232 mp_exch(&u, &v); 3233 } 3234 3235 /* subtract smallest from largest */ 3236 if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { 3237 goto LBL_V; 3238 } 3239 3240 /* Divide out all factors of two */ 3241 if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { 3242 goto LBL_V; 3243 } 3244 } 3245 3246 /* multiply by 2**k which we divided out at the beginning */ 3247 if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { 3248 goto LBL_V; 3249 } 3250 c->sign = MP_ZPOS; 3251 res = MP_OKAY; 3252LBL_V:mp_clear (&u); 3253LBL_U:mp_clear (&v); 3254 return res; 3255} 3256#endif 3257 3258/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */ 3259/* $Revision: 1.4 $ */ 3260/* $Date: 2006/03/31 14:18:44 $ */ 3261 3262/* End: bn_mp_gcd.c */ 3263 3264/* Start: bn_mp_get_int.c */ 3265#include <tommath.h> 3266#ifdef BN_MP_GET_INT_C 3267/* LibTomMath, multiple-precision integer library -- Tom St Denis 3268 * 3269 * LibTomMath is a library that provides multiple-precision 3270 * integer arithmetic as well as number theoretic functionality. 3271 * 3272 * The library was designed directly after the MPI library by 3273 * Michael Fromberger but has been written from scratch with 3274 * additional optimizations in place. 3275 * 3276 * The library is free for all purposes without any express 3277 * guarantee it works. 3278 * 3279 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3280 */ 3281 3282/* get the lower 32-bits of an mp_int */ 3283unsigned long mp_get_int(mp_int * a) 3284{ 3285 int i; 3286 unsigned long res; 3287 3288 if (a->used == 0) { 3289 return 0; 3290 } 3291 3292 /* get number of digits of the lsb we have to read */ 3293 i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1; 3294 3295 /* get most significant digit of result */ 3296 res = DIGIT(a,i); 3297 3298 while (--i >= 0) { 3299 res = (res << DIGIT_BIT) | DIGIT(a,i); 3300 } 3301 3302 /* force result to 32-bits always so it is consistent on non 32-bit platforms */ 3303 return res & 0xFFFFFFFFUL; 3304} 3305#endif 3306 3307/* $Source: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */ 3308/* $Revision: 1.3 $ */ 3309/* $Date: 2006/03/31 14:18:44 $ */ 3310 3311/* End: bn_mp_get_int.c */ 3312 3313/* Start: bn_mp_grow.c */ 3314#include <tommath.h> 3315#ifdef BN_MP_GROW_C 3316/* LibTomMath, multiple-precision integer library -- Tom St Denis 3317 * 3318 * LibTomMath is a library that provides multiple-precision 3319 * integer arithmetic as well as number theoretic functionality. 3320 * 3321 * The library was designed directly after the MPI library by 3322 * Michael Fromberger but has been written from scratch with 3323 * additional optimizations in place. 3324 * 3325 * The library is free for all purposes without any express 3326 * guarantee it works. 3327 * 3328 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3329 */ 3330 3331/* grow as required */ 3332int mp_grow (mp_int * a, int size) 3333{ 3334 int i; 3335 mp_digit *tmp; 3336 3337 /* if the alloc size is smaller alloc more ram */ 3338 if (a->alloc < size) { 3339 /* ensure there are always at least MP_PREC digits extra on top */ 3340 size += (MP_PREC * 2) - (size % MP_PREC); 3341 3342 /* reallocate the array a->dp 3343 * 3344 * We store the return in a temporary variable 3345 * in case the operation failed we don't want 3346 * to overwrite the dp member of a. 3347 */ 3348 tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); 3349 if (tmp == NULL) { 3350 /* reallocation failed but "a" is still valid [can be freed] */ 3351 return MP_MEM; 3352 } 3353 3354 /* reallocation succeeded so set a->dp */ 3355 a->dp = tmp; 3356 3357 /* zero excess digits */ 3358 i = a->alloc; 3359 a->alloc = size; 3360 for (; i < a->alloc; i++) { 3361 a->dp[i] = 0; 3362 } 3363 } 3364 return MP_OKAY; 3365} 3366#endif 3367 3368/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */ 3369/* $Revision: 1.3 $ */ 3370/* $Date: 2006/03/31 14:18:44 $ */ 3371 3372/* End: bn_mp_grow.c */ 3373 3374/* Start: bn_mp_init.c */ 3375#include <tommath.h> 3376#ifdef BN_MP_INIT_C 3377/* LibTomMath, multiple-precision integer library -- Tom St Denis 3378 * 3379 * LibTomMath is a library that provides multiple-precision 3380 * integer arithmetic as well as number theoretic functionality. 3381 * 3382 * The library was designed directly after the MPI library by 3383 * Michael Fromberger but has been written from scratch with 3384 * additional optimizations in place. 3385 * 3386 * The library is free for all purposes without any express 3387 * guarantee it works. 3388 * 3389 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3390 */ 3391 3392/* init a new mp_int */ 3393int mp_init (mp_int * a) 3394{ 3395 int i; 3396 3397 /* allocate memory required and clear it */ 3398 a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); 3399 if (a->dp == NULL) { 3400 return MP_MEM; 3401 } 3402 3403 /* set the digits to zero */ 3404 for (i = 0; i < MP_PREC; i++) { 3405 a->dp[i] = 0; 3406 } 3407 3408 /* set the used to zero, allocated digits to the default precision 3409 * and sign to positive */ 3410 a->used = 0; 3411 a->alloc = MP_PREC; 3412 a->sign = MP_ZPOS; 3413 3414 return MP_OKAY; 3415} 3416#endif 3417 3418/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */ 3419/* $Revision: 1.3 $ */ 3420/* $Date: 2006/03/31 14:18:44 $ */ 3421 3422/* End: bn_mp_init.c */ 3423 3424/* Start: bn_mp_init_copy.c */ 3425#include <tommath.h> 3426#ifdef BN_MP_INIT_COPY_C 3427/* LibTomMath, multiple-precision integer library -- Tom St Denis 3428 * 3429 * LibTomMath is a library that provides multiple-precision 3430 * integer arithmetic as well as number theoretic functionality. 3431 * 3432 * The library was designed directly after the MPI library by 3433 * Michael Fromberger but has been written from scratch with 3434 * additional optimizations in place. 3435 * 3436 * The library is free for all purposes without any express 3437 * guarantee it works. 3438 * 3439 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3440 */ 3441 3442/* creates "a" then copies b into it */ 3443int mp_init_copy (mp_int * a, mp_int * b) 3444{ 3445 int res; 3446 3447 if ((res = mp_init (a)) != MP_OKAY) { 3448 return res; 3449 } 3450 return mp_copy (b, a); 3451} 3452#endif 3453 3454/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */ 3455/* $Revision: 1.3 $ */ 3456/* $Date: 2006/03/31 14:18:44 $ */ 3457 3458/* End: bn_mp_init_copy.c */ 3459 3460/* Start: bn_mp_init_multi.c */ 3461#include <tommath.h> 3462#ifdef BN_MP_INIT_MULTI_C 3463/* LibTomMath, multiple-precision integer library -- Tom St Denis 3464 * 3465 * LibTomMath is a library that provides multiple-precision 3466 * integer arithmetic as well as number theoretic functionality. 3467 * 3468 * The library was designed directly after the MPI library by 3469 * Michael Fromberger but has been written from scratch with 3470 * additional optimizations in place. 3471 * 3472 * The library is free for all purposes without any express 3473 * guarantee it works. 3474 * 3475 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3476 */ 3477#include <stdarg.h> 3478 3479int mp_init_multi(mp_int *mp, ...) 3480{ 3481 mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ 3482 int n = 0; /* Number of ok inits */ 3483 mp_int* cur_arg = mp; 3484 va_list args; 3485 3486 va_start(args, mp); /* init args to next argument from caller */ 3487 while (cur_arg != NULL) { 3488 if (mp_init(cur_arg) != MP_OKAY) { 3489 /* Oops - error! Back-track and mp_clear what we already 3490 succeeded in init-ing, then return error. 3491 */ 3492 va_list clean_args; 3493 3494 /* end the current list */ 3495 va_end(args); 3496 3497 /* now start cleaning up */ 3498 cur_arg = mp; 3499 va_start(clean_args, mp); 3500 while (n--) { 3501 mp_clear(cur_arg); 3502 cur_arg = va_arg(clean_args, mp_int*); 3503 } 3504 va_end(clean_args); 3505 res = MP_MEM; 3506 break; 3507 } 3508 n++; 3509 cur_arg = va_arg(args, mp_int*); 3510 } 3511 va_end(args); 3512 return res; /* Assumed ok, if error flagged above. */ 3513} 3514 3515#endif 3516 3517/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */ 3518/* $Revision: 1.3 $ */ 3519/* $Date: 2006/03/31 14:18:44 $ */ 3520 3521/* End: bn_mp_init_multi.c */ 3522 3523/* Start: bn_mp_init_set.c */ 3524#include <tommath.h> 3525#ifdef BN_MP_INIT_SET_C 3526/* LibTomMath, multiple-precision integer library -- Tom St Denis 3527 * 3528 * LibTomMath is a library that provides multiple-precision 3529 * integer arithmetic as well as number theoretic functionality. 3530 * 3531 * The library was designed directly after the MPI library by 3532 * Michael Fromberger but has been written from scratch with 3533 * additional optimizations in place. 3534 * 3535 * The library is free for all purposes without any express 3536 * guarantee it works. 3537 * 3538 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3539 */ 3540 3541/* initialize and set a digit */ 3542int mp_init_set (mp_int * a, mp_digit b) 3543{ 3544 int err; 3545 if ((err = mp_init(a)) != MP_OKAY) { 3546 return err; 3547 } 3548 mp_set(a, b); 3549 return err; 3550} 3551#endif 3552 3553/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */ 3554/* $Revision: 1.3 $ */ 3555/* $Date: 2006/03/31 14:18:44 $ */ 3556 3557/* End: bn_mp_init_set.c */ 3558 3559/* Start: bn_mp_init_set_int.c */ 3560#include <tommath.h> 3561#ifdef BN_MP_INIT_SET_INT_C 3562/* LibTomMath, multiple-precision integer library -- Tom St Denis 3563 * 3564 * LibTomMath is a library that provides multiple-precision 3565 * integer arithmetic as well as number theoretic functionality. 3566 * 3567 * The library was designed directly after the MPI library by 3568 * Michael Fromberger but has been written from scratch with 3569 * additional optimizations in place. 3570 * 3571 * The library is free for all purposes without any express 3572 * guarantee it works. 3573 * 3574 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3575 */ 3576 3577/* initialize and set a digit */ 3578int mp_init_set_int (mp_int * a, unsigned long b) 3579{ 3580 int err; 3581 if ((err = mp_init(a)) != MP_OKAY) { 3582 return err; 3583 } 3584 return mp_set_int(a, b); 3585} 3586#endif 3587 3588/* $Source: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */ 3589/* $Revision: 1.3 $ */ 3590/* $Date: 2006/03/31 14:18:44 $ */ 3591 3592/* End: bn_mp_init_set_int.c */ 3593 3594/* Start: bn_mp_init_size.c */ 3595#include <tommath.h> 3596#ifdef BN_MP_INIT_SIZE_C 3597/* LibTomMath, multiple-precision integer library -- Tom St Denis 3598 * 3599 * LibTomMath is a library that provides multiple-precision 3600 * integer arithmetic as well as number theoretic functionality. 3601 * 3602 * The library was designed directly after the MPI library by 3603 * Michael Fromberger but has been written from scratch with 3604 * additional optimizations in place. 3605 * 3606 * The library is free for all purposes without any express 3607 * guarantee it works. 3608 * 3609 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3610 */ 3611 3612/* init an mp_init for a given size */ 3613int mp_init_size (mp_int * a, int size) 3614{ 3615 int x; 3616 3617 /* pad size so there are always extra digits */ 3618 size += (MP_PREC * 2) - (size % MP_PREC); 3619 3620 /* alloc mem */ 3621 a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); 3622 if (a->dp == NULL) { 3623 return MP_MEM; 3624 } 3625 3626 /* set the members */ 3627 a->used = 0; 3628 a->alloc = size; 3629 a->sign = MP_ZPOS; 3630 3631 /* zero the digits */ 3632 for (x = 0; x < size; x++) { 3633 a->dp[x] = 0; 3634 } 3635 3636 return MP_OKAY; 3637} 3638#endif 3639 3640/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */ 3641/* $Revision: 1.3 $ */ 3642/* $Date: 2006/03/31 14:18:44 $ */ 3643 3644/* End: bn_mp_init_size.c */ 3645 3646/* Start: bn_mp_invmod.c */ 3647#include <tommath.h> 3648#ifdef BN_MP_INVMOD_C 3649/* LibTomMath, multiple-precision integer library -- Tom St Denis 3650 * 3651 * LibTomMath is a library that provides multiple-precision 3652 * integer arithmetic as well as number theoretic functionality. 3653 * 3654 * The library was designed directly after the MPI library by 3655 * Michael Fromberger but has been written from scratch with 3656 * additional optimizations in place. 3657 * 3658 * The library is free for all purposes without any express 3659 * guarantee it works. 3660 * 3661 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3662 */ 3663 3664/* hac 14.61, pp608 */ 3665int mp_invmod (mp_int * a, mp_int * b, mp_int * c) 3666{ 3667 /* b cannot be negative */ 3668 if (b->sign == MP_NEG || mp_iszero(b) == 1) { 3669 return MP_VAL; 3670 } 3671 3672#ifdef BN_FAST_MP_INVMOD_C 3673 /* if the modulus is odd we can use a faster routine instead */ 3674 if (mp_isodd (b) == 1) { 3675 return fast_mp_invmod (a, b, c); 3676 } 3677#endif 3678 3679#ifdef BN_MP_INVMOD_SLOW_C 3680 return mp_invmod_slow(a, b, c); 3681#endif 3682 3683 return MP_VAL; 3684} 3685#endif 3686 3687/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */ 3688/* $Revision: 1.3 $ */ 3689/* $Date: 2006/03/31 14:18:44 $ */ 3690 3691/* End: bn_mp_invmod.c */ 3692 3693/* Start: bn_mp_invmod_slow.c */ 3694#include <tommath.h> 3695#ifdef BN_MP_INVMOD_SLOW_C 3696/* LibTomMath, multiple-precision integer library -- Tom St Denis 3697 * 3698 * LibTomMath is a library that provides multiple-precision 3699 * integer arithmetic as well as number theoretic functionality. 3700 * 3701 * The library was designed directly after the MPI library by 3702 * Michael Fromberger but has been written from scratch with 3703 * additional optimizations in place. 3704 * 3705 * The library is free for all purposes without any express 3706 * guarantee it works. 3707 * 3708 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3709 */ 3710 3711/* hac 14.61, pp608 */ 3712int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) 3713{ 3714 mp_int x, y, u, v, A, B, C, D; 3715 int res; 3716 3717 /* b cannot be negative */ 3718 if (b->sign == MP_NEG || mp_iszero(b) == 1) { 3719 return MP_VAL; 3720 } 3721 3722 /* init temps */ 3723 if ((res = mp_init_multi(&x, &y, &u, &v, 3724 &A, &B, &C, &D, NULL)) != MP_OKAY) { 3725 return res; 3726 } 3727 3728 /* x = a, y = b */ 3729 if ((res = mp_mod(a, b, &x)) != MP_OKAY) { 3730 goto LBL_ERR; 3731 } 3732 if ((res = mp_copy (b, &y)) != MP_OKAY) { 3733 goto LBL_ERR; 3734 } 3735 3736 /* 2. [modified] if x,y are both even then return an error! */ 3737 if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { 3738 res = MP_VAL; 3739 goto LBL_ERR; 3740 } 3741 3742 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ 3743 if ((res = mp_copy (&x, &u)) != MP_OKAY) { 3744 goto LBL_ERR; 3745 } 3746 if ((res = mp_copy (&y, &v)) != MP_OKAY) { 3747 goto LBL_ERR; 3748 } 3749 mp_set (&A, 1); 3750 mp_set (&D, 1); 3751 3752top: 3753 /* 4. while u is even do */ 3754 while (mp_iseven (&u) == 1) { 3755 /* 4.1 u = u/2 */ 3756 if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { 3757 goto LBL_ERR; 3758 } 3759 /* 4.2 if A or B is odd then */ 3760 if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { 3761 /* A = (A+y)/2, B = (B-x)/2 */ 3762 if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { 3763 goto LBL_ERR; 3764 } 3765 if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { 3766 goto LBL_ERR; 3767 } 3768 } 3769 /* A = A/2, B = B/2 */ 3770 if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { 3771 goto LBL_ERR; 3772 } 3773 if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { 3774 goto LBL_ERR; 3775 } 3776 } 3777 3778 /* 5. while v is even do */ 3779 while (mp_iseven (&v) == 1) { 3780 /* 5.1 v = v/2 */ 3781 if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { 3782 goto LBL_ERR; 3783 } 3784 /* 5.2 if C or D is odd then */ 3785 if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { 3786 /* C = (C+y)/2, D = (D-x)/2 */ 3787 if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { 3788 goto LBL_ERR; 3789 } 3790 if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { 3791 goto LBL_ERR; 3792 } 3793 } 3794 /* C = C/2, D = D/2 */ 3795 if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { 3796 goto LBL_ERR; 3797 } 3798 if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { 3799 goto LBL_ERR; 3800 } 3801 } 3802 3803 /* 6. if u >= v then */ 3804 if (mp_cmp (&u, &v) != MP_LT) { 3805 /* u = u - v, A = A - C, B = B - D */ 3806 if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { 3807 goto LBL_ERR; 3808 } 3809 3810 if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { 3811 goto LBL_ERR; 3812 } 3813 3814 if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { 3815 goto LBL_ERR; 3816 } 3817 } else { 3818 /* v - v - u, C = C - A, D = D - B */ 3819 if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { 3820 goto LBL_ERR; 3821 } 3822 3823 if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { 3824 goto LBL_ERR; 3825 } 3826 3827 if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { 3828 goto LBL_ERR; 3829 } 3830 } 3831 3832 /* if not zero goto step 4 */ 3833 if (mp_iszero (&u) == 0) 3834 goto top; 3835 3836 /* now a = C, b = D, gcd == g*v */ 3837 3838 /* if v != 1 then there is no inverse */ 3839 if (mp_cmp_d (&v, 1) != MP_EQ) { 3840 res = MP_VAL; 3841 goto LBL_ERR; 3842 } 3843 3844 /* if its too low */ 3845 while (mp_cmp_d(&C, 0) == MP_LT) { 3846 if ((res = mp_add(&C, b, &C)) != MP_OKAY) { 3847 goto LBL_ERR; 3848 } 3849 } 3850 3851 /* too big */ 3852 while (mp_cmp_mag(&C, b) != MP_LT) { 3853 if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { 3854 goto LBL_ERR; 3855 } 3856 } 3857 3858 /* C is now the inverse */ 3859 mp_exch (&C, c); 3860 res = MP_OKAY; 3861LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); 3862 return res; 3863} 3864#endif 3865 3866/* $Source: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */ 3867/* $Revision: 1.3 $ */ 3868/* $Date: 2006/03/31 14:18:44 $ */ 3869 3870/* End: bn_mp_invmod_slow.c */ 3871 3872/* Start: bn_mp_is_square.c */ 3873#include <tommath.h> 3874#ifdef BN_MP_IS_SQUARE_C 3875/* LibTomMath, multiple-precision integer library -- Tom St Denis 3876 * 3877 * LibTomMath is a library that provides multiple-precision 3878 * integer arithmetic as well as number theoretic functionality. 3879 * 3880 * The library was designed directly after the MPI library by 3881 * Michael Fromberger but has been written from scratch with 3882 * additional optimizations in place. 3883 * 3884 * The library is free for all purposes without any express 3885 * guarantee it works. 3886 * 3887 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 3888 */ 3889 3890/* Check if remainders are possible squares - fast exclude non-squares */ 3891static const char rem_128[128] = { 3892 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3893 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3894 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3895 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3896 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3897 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3898 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3899 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 3900}; 3901 3902static const char rem_105[105] = { 3903 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 3904 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 3905 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 3906 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3907 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 3908 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 3909 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 3910}; 3911 3912/* Store non-zero to ret if arg is square, and zero if not */ 3913int mp_is_square(mp_int *arg,int *ret) 3914{ 3915 int res; 3916 mp_digit c; 3917 mp_int t; 3918 unsigned long r; 3919 3920 /* Default to Non-square :) */ 3921 *ret = MP_NO; 3922 3923 if (arg->sign == MP_NEG) { 3924 return MP_VAL; 3925 } 3926 3927 /* digits used? (TSD) */ 3928 if (arg->used == 0) { 3929 return MP_OKAY; 3930 } 3931 3932 /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ 3933 if (rem_128[127 & DIGIT(arg,0)] == 1) { 3934 return MP_OKAY; 3935 } 3936 3937 /* Next check mod 105 (3*5*7) */ 3938 if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) { 3939 return res; 3940 } 3941 if (rem_105[c] == 1) { 3942 return MP_OKAY; 3943 } 3944 3945 3946 if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) { 3947 return res; 3948 } 3949 if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) { 3950 goto ERR; 3951 } 3952 r = mp_get_int(&t); 3953 /* Check for other prime modules, note it's not an ERROR but we must 3954 * free "t" so the easiest way is to goto ERR. We know that res 3955 * is already equal to MP_OKAY from the mp_mod call 3956 */ 3957 if ( (1L<<(r%11)) & 0x5C4L ) goto ERR; 3958 if ( (1L<<(r%13)) & 0x9E4L ) goto ERR; 3959 if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR; 3960 if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR; 3961 if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR; 3962 if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR; 3963 if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR; 3964 3965 /* Final check - is sqr(sqrt(arg)) == arg ? */ 3966 if ((res = mp_sqrt(arg,&t)) != MP_OKAY) { 3967 goto ERR; 3968 } 3969 if ((res = mp_sqr(&t,&t)) != MP_OKAY) { 3970 goto ERR; 3971 } 3972 3973 *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; 3974ERR:mp_clear(&t); 3975 return res; 3976} 3977#endif 3978 3979/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */ 3980/* $Revision: 1.3 $ */ 3981/* $Date: 2006/03/31 14:18:44 $ */ 3982 3983/* End: bn_mp_is_square.c */ 3984 3985/* Start: bn_mp_jacobi.c */ 3986#include <tommath.h> 3987#ifdef BN_MP_JACOBI_C 3988/* LibTomMath, multiple-precision integer library -- Tom St Denis 3989 * 3990 * LibTomMath is a library that provides multiple-precision 3991 * integer arithmetic as well as number theoretic functionality. 3992 * 3993 * The library was designed directly after the MPI library by 3994 * Michael Fromberger but has been written from scratch with 3995 * additional optimizations in place. 3996 * 3997 * The library is free for all purposes without any express 3998 * guarantee it works. 3999 * 4000 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4001 */ 4002 4003/* computes the jacobi c = (a | n) (or Legendre if n is prime) 4004 * HAC pp. 73 Algorithm 2.149 4005 */ 4006int mp_jacobi (mp_int * a, mp_int * p, int *c) 4007{ 4008 mp_int a1, p1; 4009 int k, s, r, res; 4010 mp_digit residue; 4011 4012 /* if p <= 0 return MP_VAL */ 4013 if (mp_cmp_d(p, 0) != MP_GT) { 4014 return MP_VAL; 4015 } 4016 4017 /* step 1. if a == 0, return 0 */ 4018 if (mp_iszero (a) == 1) { 4019 *c = 0; 4020 return MP_OKAY; 4021 } 4022 4023 /* step 2. if a == 1, return 1 */ 4024 if (mp_cmp_d (a, 1) == MP_EQ) { 4025 *c = 1; 4026 return MP_OKAY; 4027 } 4028 4029 /* default */ 4030 s = 0; 4031 4032 /* step 3. write a = a1 * 2**k */ 4033 if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { 4034 return res; 4035 } 4036 4037 if ((res = mp_init (&p1)) != MP_OKAY) { 4038 goto LBL_A1; 4039 } 4040 4041 /* divide out larger power of two */ 4042 k = mp_cnt_lsb(&a1); 4043 if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) { 4044 goto LBL_P1; 4045 } 4046 4047 /* step 4. if e is even set s=1 */ 4048 if ((k & 1) == 0) { 4049 s = 1; 4050 } else { 4051 /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */ 4052 residue = p->dp[0] & 7; 4053 4054 if (residue == 1 || residue == 7) { 4055 s = 1; 4056 } else if (residue == 3 || residue == 5) { 4057 s = -1; 4058 } 4059 } 4060 4061 /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ 4062 if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { 4063 s = -s; 4064 } 4065 4066 /* if a1 == 1 we're done */ 4067 if (mp_cmp_d (&a1, 1) == MP_EQ) { 4068 *c = s; 4069 } else { 4070 /* n1 = n mod a1 */ 4071 if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) { 4072 goto LBL_P1; 4073 } 4074 if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) { 4075 goto LBL_P1; 4076 } 4077 *c = s * r; 4078 } 4079 4080 /* done */ 4081 res = MP_OKAY; 4082LBL_P1:mp_clear (&p1); 4083LBL_A1:mp_clear (&a1); 4084 return res; 4085} 4086#endif 4087 4088/* $Source: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */ 4089/* $Revision: 1.3 $ */ 4090/* $Date: 2006/03/31 14:18:44 $ */ 4091 4092/* End: bn_mp_jacobi.c */ 4093 4094/* Start: bn_mp_karatsuba_mul.c */ 4095#include <tommath.h> 4096#ifdef BN_MP_KARATSUBA_MUL_C 4097/* LibTomMath, multiple-precision integer library -- Tom St Denis 4098 * 4099 * LibTomMath is a library that provides multiple-precision 4100 * integer arithmetic as well as number theoretic functionality. 4101 * 4102 * The library was designed directly after the MPI library by 4103 * Michael Fromberger but has been written from scratch with 4104 * additional optimizations in place. 4105 * 4106 * The library is free for all purposes without any express 4107 * guarantee it works. 4108 * 4109 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4110 */ 4111 4112/* c = |a| * |b| using Karatsuba Multiplication using 4113 * three half size multiplications 4114 * 4115 * Let B represent the radix [e.g. 2**DIGIT_BIT] and 4116 * let n represent half of the number of digits in 4117 * the min(a,b) 4118 * 4119 * a = a1 * B**n + a0 4120 * b = b1 * B**n + b0 4121 * 4122 * Then, a * b => 4123 a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0 4124 * 4125 * Note that a1b1 and a0b0 are used twice and only need to be 4126 * computed once. So in total three half size (half # of 4127 * digit) multiplications are performed, a0b0, a1b1 and 4128 * (a1+b1)(a0+b0) 4129 * 4130 * Note that a multiplication of half the digits requires 4131 * 1/4th the number of single precision multiplications so in 4132 * total after one call 25% of the single precision multiplications 4133 * are saved. Note also that the call to mp_mul can end up back 4134 * in this function if the a0, a1, b0, or b1 are above the threshold. 4135 * This is known as divide-and-conquer and leads to the famous 4136 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 4137 * the standard O(N**2) that the baseline/comba methods use. 4138 * Generally though the overhead of this method doesn't pay off 4139 * until a certain size (N ~ 80) is reached. 4140 */ 4141int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) 4142{ 4143 mp_int x0, x1, y0, y1, t1, x0y0, x1y1; 4144 int B, err; 4145 4146 /* default the return code to an error */ 4147 err = MP_MEM; 4148 4149 /* min # of digits */ 4150 B = MIN (a->used, b->used); 4151 4152 /* now divide in two */ 4153 B = B >> 1; 4154 4155 /* init copy all the temps */ 4156 if (mp_init_size (&x0, B) != MP_OKAY) 4157 goto ERR; 4158 if (mp_init_size (&x1, a->used - B) != MP_OKAY) 4159 goto X0; 4160 if (mp_init_size (&y0, B) != MP_OKAY) 4161 goto X1; 4162 if (mp_init_size (&y1, b->used - B) != MP_OKAY) 4163 goto Y0; 4164 4165 /* init temps */ 4166 if (mp_init_size (&t1, B * 2) != MP_OKAY) 4167 goto Y1; 4168 if (mp_init_size (&x0y0, B * 2) != MP_OKAY) 4169 goto T1; 4170 if (mp_init_size (&x1y1, B * 2) != MP_OKAY) 4171 goto X0Y0; 4172 4173 /* now shift the digits */ 4174 x0.used = y0.used = B; 4175 x1.used = a->used - B; 4176 y1.used = b->used - B; 4177 4178 { 4179 register int x; 4180 register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; 4181 4182 /* we copy the digits directly instead of using higher level functions 4183 * since we also need to shift the digits 4184 */ 4185 tmpa = a->dp; 4186 tmpb = b->dp; 4187 4188 tmpx = x0.dp; 4189 tmpy = y0.dp; 4190 for (x = 0; x < B; x++) { 4191 *tmpx++ = *tmpa++; 4192 *tmpy++ = *tmpb++; 4193 } 4194 4195 tmpx = x1.dp; 4196 for (x = B; x < a->used; x++) { 4197 *tmpx++ = *tmpa++; 4198 } 4199 4200 tmpy = y1.dp; 4201 for (x = B; x < b->used; x++) { 4202 *tmpy++ = *tmpb++; 4203 } 4204 } 4205 4206 /* only need to clamp the lower words since by definition the 4207 * upper words x1/y1 must have a known number of digits 4208 */ 4209 mp_clamp (&x0); 4210 mp_clamp (&y0); 4211 4212 /* now calc the products x0y0 and x1y1 */ 4213 /* after this x0 is no longer required, free temp [x0==t2]! */ 4214 if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) 4215 goto X1Y1; /* x0y0 = x0*y0 */ 4216 if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) 4217 goto X1Y1; /* x1y1 = x1*y1 */ 4218 4219 /* now calc x1+x0 and y1+y0 */ 4220 if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) 4221 goto X1Y1; /* t1 = x1 - x0 */ 4222 if (s_mp_add (&y1, &y0, &x0) != MP_OKAY) 4223 goto X1Y1; /* t2 = y1 - y0 */ 4224 if (mp_mul (&t1, &x0, &t1) != MP_OKAY) 4225 goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */ 4226 4227 /* add x0y0 */ 4228 if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY) 4229 goto X1Y1; /* t2 = x0y0 + x1y1 */ 4230 if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY) 4231 goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */ 4232 4233 /* shift by B */ 4234 if (mp_lshd (&t1, B) != MP_OKAY) 4235 goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */ 4236 if (mp_lshd (&x1y1, B * 2) != MP_OKAY) 4237 goto X1Y1; /* x1y1 = x1y1 << 2*B */ 4238 4239 if (mp_add (&x0y0, &t1, &t1) != MP_OKAY) 4240 goto X1Y1; /* t1 = x0y0 + t1 */ 4241 if (mp_add (&t1, &x1y1, c) != MP_OKAY) 4242 goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */ 4243 4244 /* Algorithm succeeded set the return code to MP_OKAY */ 4245 err = MP_OKAY; 4246 4247X1Y1:mp_clear (&x1y1); 4248X0Y0:mp_clear (&x0y0); 4249T1:mp_clear (&t1); 4250Y1:mp_clear (&y1); 4251Y0:mp_clear (&y0); 4252X1:mp_clear (&x1); 4253X0:mp_clear (&x0); 4254ERR: 4255 return err; 4256} 4257#endif 4258 4259/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_mul.c,v $ */ 4260/* $Revision: 1.5 $ */ 4261/* $Date: 2006/03/31 14:18:44 $ */ 4262 4263/* End: bn_mp_karatsuba_mul.c */ 4264 4265/* Start: bn_mp_karatsuba_sqr.c */ 4266#include <tommath.h> 4267#ifdef BN_MP_KARATSUBA_SQR_C 4268/* LibTomMath, multiple-precision integer library -- Tom St Denis 4269 * 4270 * LibTomMath is a library that provides multiple-precision 4271 * integer arithmetic as well as number theoretic functionality. 4272 * 4273 * The library was designed directly after the MPI library by 4274 * Michael Fromberger but has been written from scratch with 4275 * additional optimizations in place. 4276 * 4277 * The library is free for all purposes without any express 4278 * guarantee it works. 4279 * 4280 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4281 */ 4282 4283/* Karatsuba squaring, computes b = a*a using three 4284 * half size squarings 4285 * 4286 * See comments of karatsuba_mul for details. It 4287 * is essentially the same algorithm but merely 4288 * tuned to perform recursive squarings. 4289 */ 4290int mp_karatsuba_sqr (mp_int * a, mp_int * b) 4291{ 4292 mp_int x0, x1, t1, t2, x0x0, x1x1; 4293 int B, err; 4294 4295 err = MP_MEM; 4296 4297 /* min # of digits */ 4298 B = a->used; 4299 4300 /* now divide in two */ 4301 B = B >> 1; 4302 4303 /* init copy all the temps */ 4304 if (mp_init_size (&x0, B) != MP_OKAY) 4305 goto ERR; 4306 if (mp_init_size (&x1, a->used - B) != MP_OKAY) 4307 goto X0; 4308 4309 /* init temps */ 4310 if (mp_init_size (&t1, a->used * 2) != MP_OKAY) 4311 goto X1; 4312 if (mp_init_size (&t2, a->used * 2) != MP_OKAY) 4313 goto T1; 4314 if (mp_init_size (&x0x0, B * 2) != MP_OKAY) 4315 goto T2; 4316 if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) 4317 goto X0X0; 4318 4319 { 4320 register int x; 4321 register mp_digit *dst, *src; 4322 4323 src = a->dp; 4324 4325 /* now shift the digits */ 4326 dst = x0.dp; 4327 for (x = 0; x < B; x++) { 4328 *dst++ = *src++; 4329 } 4330 4331 dst = x1.dp; 4332 for (x = B; x < a->used; x++) { 4333 *dst++ = *src++; 4334 } 4335 } 4336 4337 x0.used = B; 4338 x1.used = a->used - B; 4339 4340 mp_clamp (&x0); 4341 4342 /* now calc the products x0*x0 and x1*x1 */ 4343 if (mp_sqr (&x0, &x0x0) != MP_OKAY) 4344 goto X1X1; /* x0x0 = x0*x0 */ 4345 if (mp_sqr (&x1, &x1x1) != MP_OKAY) 4346 goto X1X1; /* x1x1 = x1*x1 */ 4347 4348 /* now calc (x1+x0)**2 */ 4349 if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) 4350 goto X1X1; /* t1 = x1 - x0 */ 4351 if (mp_sqr (&t1, &t1) != MP_OKAY) 4352 goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ 4353 4354 /* add x0y0 */ 4355 if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) 4356 goto X1X1; /* t2 = x0x0 + x1x1 */ 4357 if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY) 4358 goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */ 4359 4360 /* shift by B */ 4361 if (mp_lshd (&t1, B) != MP_OKAY) 4362 goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */ 4363 if (mp_lshd (&x1x1, B * 2) != MP_OKAY) 4364 goto X1X1; /* x1x1 = x1x1 << 2*B */ 4365 4366 if (mp_add (&x0x0, &t1, &t1) != MP_OKAY) 4367 goto X1X1; /* t1 = x0x0 + t1 */ 4368 if (mp_add (&t1, &x1x1, b) != MP_OKAY) 4369 goto X1X1; /* t1 = x0x0 + t1 + x1x1 */ 4370 4371 err = MP_OKAY; 4372 4373X1X1:mp_clear (&x1x1); 4374X0X0:mp_clear (&x0x0); 4375T2:mp_clear (&t2); 4376T1:mp_clear (&t1); 4377X1:mp_clear (&x1); 4378X0:mp_clear (&x0); 4379ERR: 4380 return err; 4381} 4382#endif 4383 4384/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_sqr.c,v $ */ 4385/* $Revision: 1.5 $ */ 4386/* $Date: 2006/03/31 14:18:44 $ */ 4387 4388/* End: bn_mp_karatsuba_sqr.c */ 4389 4390/* Start: bn_mp_lcm.c */ 4391#include <tommath.h> 4392#ifdef BN_MP_LCM_C 4393/* LibTomMath, multiple-precision integer library -- Tom St Denis 4394 * 4395 * LibTomMath is a library that provides multiple-precision 4396 * integer arithmetic as well as number theoretic functionality. 4397 * 4398 * The library was designed directly after the MPI library by 4399 * Michael Fromberger but has been written from scratch with 4400 * additional optimizations in place. 4401 * 4402 * The library is free for all purposes without any express 4403 * guarantee it works. 4404 * 4405 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4406 */ 4407 4408/* computes least common multiple as |a*b|/(a, b) */ 4409int mp_lcm (mp_int * a, mp_int * b, mp_int * c) 4410{ 4411 int res; 4412 mp_int t1, t2; 4413 4414 4415 if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) { 4416 return res; 4417 } 4418 4419 /* t1 = get the GCD of the two inputs */ 4420 if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) { 4421 goto LBL_T; 4422 } 4423 4424 /* divide the smallest by the GCD */ 4425 if (mp_cmp_mag(a, b) == MP_LT) { 4426 /* store quotient in t2 such that t2 * b is the LCM */ 4427 if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { 4428 goto LBL_T; 4429 } 4430 res = mp_mul(b, &t2, c); 4431 } else { 4432 /* store quotient in t2 such that t2 * a is the LCM */ 4433 if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { 4434 goto LBL_T; 4435 } 4436 res = mp_mul(a, &t2, c); 4437 } 4438 4439 /* fix the sign to positive */ 4440 c->sign = MP_ZPOS; 4441 4442LBL_T: 4443 mp_clear_multi (&t1, &t2, NULL); 4444 return res; 4445} 4446#endif 4447 4448/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */ 4449/* $Revision: 1.3 $ */ 4450/* $Date: 2006/03/31 14:18:44 $ */ 4451 4452/* End: bn_mp_lcm.c */ 4453 4454/* Start: bn_mp_lshd.c */ 4455#include <tommath.h> 4456#ifdef BN_MP_LSHD_C 4457/* LibTomMath, multiple-precision integer library -- Tom St Denis 4458 * 4459 * LibTomMath is a library that provides multiple-precision 4460 * integer arithmetic as well as number theoretic functionality. 4461 * 4462 * The library was designed directly after the MPI library by 4463 * Michael Fromberger but has been written from scratch with 4464 * additional optimizations in place. 4465 * 4466 * The library is free for all purposes without any express 4467 * guarantee it works. 4468 * 4469 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4470 */ 4471 4472/* shift left a certain amount of digits */ 4473int mp_lshd (mp_int * a, int b) 4474{ 4475 int x, res; 4476 4477 /* if its less than zero return */ 4478 if (b <= 0) { 4479 return MP_OKAY; 4480 } 4481 4482 /* grow to fit the new digits */ 4483 if (a->alloc < a->used + b) { 4484 if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { 4485 return res; 4486 } 4487 } 4488 4489 { 4490 register mp_digit *top, *bottom; 4491 4492 /* increment the used by the shift amount then copy upwards */ 4493 a->used += b; 4494 4495 /* top */ 4496 top = a->dp + a->used - 1; 4497 4498 /* base */ 4499 bottom = a->dp + a->used - 1 - b; 4500 4501 /* much like mp_rshd this is implemented using a sliding window 4502 * except the window goes the otherway around. Copying from 4503 * the bottom to the top. see bn_mp_rshd.c for more info. 4504 */ 4505 for (x = a->used - 1; x >= b; x--) { 4506 *top-- = *bottom--; 4507 } 4508 4509 /* zero the lower digits */ 4510 top = a->dp; 4511 for (x = 0; x < b; x++) { 4512 *top++ = 0; 4513 } 4514 } 4515 return MP_OKAY; 4516} 4517#endif 4518 4519/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */ 4520/* $Revision: 1.3 $ */ 4521/* $Date: 2006/03/31 14:18:44 $ */ 4522 4523/* End: bn_mp_lshd.c */ 4524 4525/* Start: bn_mp_mod.c */ 4526#include <tommath.h> 4527#ifdef BN_MP_MOD_C 4528/* LibTomMath, multiple-precision integer library -- Tom St Denis 4529 * 4530 * LibTomMath is a library that provides multiple-precision 4531 * integer arithmetic as well as number theoretic functionality. 4532 * 4533 * The library was designed directly after the MPI library by 4534 * Michael Fromberger but has been written from scratch with 4535 * additional optimizations in place. 4536 * 4537 * The library is free for all purposes without any express 4538 * guarantee it works. 4539 * 4540 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4541 */ 4542 4543/* c = a mod b, 0 <= c < b */ 4544int 4545mp_mod (mp_int * a, mp_int * b, mp_int * c) 4546{ 4547 mp_int t; 4548 int res; 4549 4550 if ((res = mp_init (&t)) != MP_OKAY) { 4551 return res; 4552 } 4553 4554 if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { 4555 mp_clear (&t); 4556 return res; 4557 } 4558 4559 if (t.sign != b->sign) { 4560 res = mp_add (b, &t, c); 4561 } else { 4562 res = MP_OKAY; 4563 mp_exch (&t, c); 4564 } 4565 4566 mp_clear (&t); 4567 return res; 4568} 4569#endif 4570 4571/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */ 4572/* $Revision: 1.3 $ */ 4573/* $Date: 2006/03/31 14:18:44 $ */ 4574 4575/* End: bn_mp_mod.c */ 4576 4577/* Start: bn_mp_mod_2d.c */ 4578#include <tommath.h> 4579#ifdef BN_MP_MOD_2D_C 4580/* LibTomMath, multiple-precision integer library -- Tom St Denis 4581 * 4582 * LibTomMath is a library that provides multiple-precision 4583 * integer arithmetic as well as number theoretic functionality. 4584 * 4585 * The library was designed directly after the MPI library by 4586 * Michael Fromberger but has been written from scratch with 4587 * additional optimizations in place. 4588 * 4589 * The library is free for all purposes without any express 4590 * guarantee it works. 4591 * 4592 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4593 */ 4594 4595/* calc a value mod 2**b */ 4596int 4597mp_mod_2d (mp_int * a, int b, mp_int * c) 4598{ 4599 int x, res; 4600 4601 /* if b is <= 0 then zero the int */ 4602 if (b <= 0) { 4603 mp_zero (c); 4604 return MP_OKAY; 4605 } 4606 4607 /* if the modulus is larger than the value than return */ 4608 if (b >= (int) (a->used * DIGIT_BIT)) { 4609 res = mp_copy (a, c); 4610 return res; 4611 } 4612 4613 /* copy */ 4614 if ((res = mp_copy (a, c)) != MP_OKAY) { 4615 return res; 4616 } 4617 4618 /* zero digits above the last digit of the modulus */ 4619 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { 4620 c->dp[x] = 0; 4621 } 4622 /* clear the digit that is not completely outside/inside the modulus */ 4623 c->dp[b / DIGIT_BIT] &= 4624 (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); 4625 mp_clamp (c); 4626 return MP_OKAY; 4627} 4628#endif 4629 4630/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */ 4631/* $Revision: 1.3 $ */ 4632/* $Date: 2006/03/31 14:18:44 $ */ 4633 4634/* End: bn_mp_mod_2d.c */ 4635 4636/* Start: bn_mp_mod_d.c */ 4637#include <tommath.h> 4638#ifdef BN_MP_MOD_D_C 4639/* LibTomMath, multiple-precision integer library -- Tom St Denis 4640 * 4641 * LibTomMath is a library that provides multiple-precision 4642 * integer arithmetic as well as number theoretic functionality. 4643 * 4644 * The library was designed directly after the MPI library by 4645 * Michael Fromberger but has been written from scratch with 4646 * additional optimizations in place. 4647 * 4648 * The library is free for all purposes without any express 4649 * guarantee it works. 4650 * 4651 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4652 */ 4653 4654int 4655mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) 4656{ 4657 return mp_div_d(a, b, NULL, c); 4658} 4659#endif 4660 4661/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */ 4662/* $Revision: 1.3 $ */ 4663/* $Date: 2006/03/31 14:18:44 $ */ 4664 4665/* End: bn_mp_mod_d.c */ 4666 4667/* Start: bn_mp_montgomery_calc_normalization.c */ 4668#include <tommath.h> 4669#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C 4670/* LibTomMath, multiple-precision integer library -- Tom St Denis 4671 * 4672 * LibTomMath is a library that provides multiple-precision 4673 * integer arithmetic as well as number theoretic functionality. 4674 * 4675 * The library was designed directly after the MPI library by 4676 * Michael Fromberger but has been written from scratch with 4677 * additional optimizations in place. 4678 * 4679 * The library is free for all purposes without any express 4680 * guarantee it works. 4681 * 4682 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4683 */ 4684 4685/* 4686 * shifts with subtractions when the result is greater than b. 4687 * 4688 * The method is slightly modified to shift B unconditionally upto just under 4689 * the leading bit of b. This saves alot of multiple precision shifting. 4690 */ 4691int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) 4692{ 4693 int x, bits, res; 4694 4695 /* how many bits of last digit does b use */ 4696 bits = mp_count_bits (b) % DIGIT_BIT; 4697 4698 if (b->used > 1) { 4699 if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { 4700 return res; 4701 } 4702 } else { 4703 mp_set(a, 1); 4704 bits = 1; 4705 } 4706 4707 4708 /* now compute C = A * B mod b */ 4709 for (x = bits - 1; x < (int)DIGIT_BIT; x++) { 4710 if ((res = mp_mul_2 (a, a)) != MP_OKAY) { 4711 return res; 4712 } 4713 if (mp_cmp_mag (a, b) != MP_LT) { 4714 if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { 4715 return res; 4716 } 4717 } 4718 } 4719 4720 return MP_OKAY; 4721} 4722#endif 4723 4724/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */ 4725/* $Revision: 1.3 $ */ 4726/* $Date: 2006/03/31 14:18:44 $ */ 4727 4728/* End: bn_mp_montgomery_calc_normalization.c */ 4729 4730/* Start: bn_mp_montgomery_reduce.c */ 4731#include <tommath.h> 4732#ifdef BN_MP_MONTGOMERY_REDUCE_C 4733/* LibTomMath, multiple-precision integer library -- Tom St Denis 4734 * 4735 * LibTomMath is a library that provides multiple-precision 4736 * integer arithmetic as well as number theoretic functionality. 4737 * 4738 * The library was designed directly after the MPI library by 4739 * Michael Fromberger but has been written from scratch with 4740 * additional optimizations in place. 4741 * 4742 * The library is free for all purposes without any express 4743 * guarantee it works. 4744 * 4745 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4746 */ 4747 4748/* computes xR**-1 == x (mod N) via Montgomery Reduction */ 4749int 4750mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) 4751{ 4752 int ix, res, digs; 4753 mp_digit mu; 4754 4755 /* can the fast reduction [comba] method be used? 4756 * 4757 * Note that unlike in mul you're safely allowed *less* 4758 * than the available columns [255 per default] since carries 4759 * are fixed up in the inner loop. 4760 */ 4761 digs = n->used * 2 + 1; 4762 if ((digs < MP_WARRAY) && 4763 n->used < 4764 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { 4765 return fast_mp_montgomery_reduce (x, n, rho); 4766 } 4767 4768 /* grow the input as required */ 4769 if (x->alloc < digs) { 4770 if ((res = mp_grow (x, digs)) != MP_OKAY) { 4771 return res; 4772 } 4773 } 4774 x->used = digs; 4775 4776 for (ix = 0; ix < n->used; ix++) { 4777 /* mu = ai * rho mod b 4778 * 4779 * The value of rho must be precalculated via 4780 * montgomery_setup() such that 4781 * it equals -1/n0 mod b this allows the 4782 * following inner loop to reduce the 4783 * input one digit at a time 4784 */ 4785 mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK); 4786 4787 /* a = a + mu * m * b**i */ 4788 { 4789 register int iy; 4790 register mp_digit *tmpn, *tmpx, u; 4791 register mp_word r; 4792 4793 /* alias for digits of the modulus */ 4794 tmpn = n->dp; 4795 4796 /* alias for the digits of x [the input] */ 4797 tmpx = x->dp + ix; 4798 4799 /* set the carry to zero */ 4800 u = 0; 4801 4802 /* Multiply and add in place */ 4803 for (iy = 0; iy < n->used; iy++) { 4804 /* compute product and sum */ 4805 r = ((mp_word)mu) * ((mp_word)*tmpn++) + 4806 ((mp_word) u) + ((mp_word) * tmpx); 4807 4808 /* get carry */ 4809 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); 4810 4811 /* fix digit */ 4812 *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK)); 4813 } 4814 /* At this point the ix'th digit of x should be zero */ 4815 4816 4817 /* propagate carries upwards as required*/ 4818 while (u) { 4819 *tmpx += u; 4820 u = *tmpx >> DIGIT_BIT; 4821 *tmpx++ &= MP_MASK; 4822 } 4823 } 4824 } 4825 4826 /* at this point the n.used'th least 4827 * significant digits of x are all zero 4828 * which means we can shift x to the 4829 * right by n.used digits and the 4830 * residue is unchanged. 4831 */ 4832 4833 /* x = x/b**n.used */ 4834 mp_clamp(x); 4835 mp_rshd (x, n->used); 4836 4837 /* if x >= n then x = x - n */ 4838 if (mp_cmp_mag (x, n) != MP_LT) { 4839 return s_mp_sub (x, n, x); 4840 } 4841 4842 return MP_OKAY; 4843} 4844#endif 4845 4846/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */ 4847/* $Revision: 1.3 $ */ 4848/* $Date: 2006/03/31 14:18:44 $ */ 4849 4850/* End: bn_mp_montgomery_reduce.c */ 4851 4852/* Start: bn_mp_montgomery_setup.c */ 4853#include <tommath.h> 4854#ifdef BN_MP_MONTGOMERY_SETUP_C 4855/* LibTomMath, multiple-precision integer library -- Tom St Denis 4856 * 4857 * LibTomMath is a library that provides multiple-precision 4858 * integer arithmetic as well as number theoretic functionality. 4859 * 4860 * The library was designed directly after the MPI library by 4861 * Michael Fromberger but has been written from scratch with 4862 * additional optimizations in place. 4863 * 4864 * The library is free for all purposes without any express 4865 * guarantee it works. 4866 * 4867 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4868 */ 4869 4870/* setups the montgomery reduction stuff */ 4871int 4872mp_montgomery_setup (mp_int * n, mp_digit * rho) 4873{ 4874 mp_digit x, b; 4875 4876/* fast inversion mod 2**k 4877 * 4878 * Based on the fact that 4879 * 4880 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) 4881 * => 2*X*A - X*X*A*A = 1 4882 * => 2*(1) - (1) = 1 4883 */ 4884 b = n->dp[0]; 4885 4886 if ((b & 1) == 0) { 4887 return MP_VAL; 4888 } 4889 4890 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ 4891 x *= 2 - b * x; /* here x*a==1 mod 2**8 */ 4892#if !defined(MP_8BIT) 4893 x *= 2 - b * x; /* here x*a==1 mod 2**16 */ 4894#endif 4895#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) 4896 x *= 2 - b * x; /* here x*a==1 mod 2**32 */ 4897#endif 4898#ifdef MP_64BIT 4899 x *= 2 - b * x; /* here x*a==1 mod 2**64 */ 4900#endif 4901 4902 /* rho = -1/m mod b */ 4903 *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; 4904 4905 return MP_OKAY; 4906} 4907#endif 4908 4909/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */ 4910/* $Revision: 1.4 $ */ 4911/* $Date: 2006/12/04 21:34:03 $ */ 4912 4913/* End: bn_mp_montgomery_setup.c */ 4914 4915/* Start: bn_mp_mul.c */ 4916#include <tommath.h> 4917#ifdef BN_MP_MUL_C 4918/* LibTomMath, multiple-precision integer library -- Tom St Denis 4919 * 4920 * LibTomMath is a library that provides multiple-precision 4921 * integer arithmetic as well as number theoretic functionality. 4922 * 4923 * The library was designed directly after the MPI library by 4924 * Michael Fromberger but has been written from scratch with 4925 * additional optimizations in place. 4926 * 4927 * The library is free for all purposes without any express 4928 * guarantee it works. 4929 * 4930 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 4931 */ 4932 4933/* high level multiplication (handles sign) */ 4934int mp_mul (mp_int * a, mp_int * b, mp_int * c) 4935{ 4936 int res, neg; 4937 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; 4938 4939 /* use Toom-Cook? */ 4940#ifdef BN_MP_TOOM_MUL_C 4941 if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { 4942 res = mp_toom_mul(a, b, c); 4943 } else 4944#endif 4945#ifdef BN_MP_KARATSUBA_MUL_C 4946 /* use Karatsuba? */ 4947 if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { 4948 res = mp_karatsuba_mul (a, b, c); 4949 } else 4950#endif 4951 { 4952 /* can we use the fast multiplier? 4953 * 4954 * The fast multiplier can be used if the output will 4955 * have less than MP_WARRAY digits and the number of 4956 * digits won't affect carry propagation 4957 */ 4958 int digs = a->used + b->used + 1; 4959 4960#ifdef BN_FAST_S_MP_MUL_DIGS_C 4961 if ((digs < MP_WARRAY) && 4962 MIN(a->used, b->used) <= 4963 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { 4964 res = fast_s_mp_mul_digs (a, b, c, digs); 4965 } else 4966#endif 4967#ifdef BN_S_MP_MUL_DIGS_C 4968 res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ 4969#else 4970 res = MP_VAL; 4971#endif 4972 4973 } 4974 c->sign = (c->used > 0) ? neg : MP_ZPOS; 4975 return res; 4976} 4977#endif 4978 4979/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */ 4980/* $Revision: 1.3 $ */ 4981/* $Date: 2006/03/31 14:18:44 $ */ 4982 4983/* End: bn_mp_mul.c */ 4984 4985/* Start: bn_mp_mul_2.c */ 4986#include <tommath.h> 4987#ifdef BN_MP_MUL_2_C 4988/* LibTomMath, multiple-precision integer library -- Tom St Denis 4989 * 4990 * LibTomMath is a library that provides multiple-precision 4991 * integer arithmetic as well as number theoretic functionality. 4992 * 4993 * The library was designed directly after the MPI library by 4994 * Michael Fromberger but has been written from scratch with 4995 * additional optimizations in place. 4996 * 4997 * The library is free for all purposes without any express 4998 * guarantee it works. 4999 * 5000 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5001 */ 5002 5003/* b = a*2 */ 5004int mp_mul_2(mp_int * a, mp_int * b) 5005{ 5006 int x, res, oldused; 5007 5008 /* grow to accomodate result */ 5009 if (b->alloc < a->used + 1) { 5010 if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { 5011 return res; 5012 } 5013 } 5014 5015 oldused = b->used; 5016 b->used = a->used; 5017 5018 { 5019 register mp_digit r, rr, *tmpa, *tmpb; 5020 5021 /* alias for source */ 5022 tmpa = a->dp; 5023 5024 /* alias for dest */ 5025 tmpb = b->dp; 5026 5027 /* carry */ 5028 r = 0; 5029 for (x = 0; x < a->used; x++) { 5030 5031 /* get what will be the *next* carry bit from the 5032 * MSB of the current digit 5033 */ 5034 rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); 5035 5036 /* now shift up this digit, add in the carry [from the previous] */ 5037 *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; 5038 5039 /* copy the carry that would be from the source 5040 * digit into the next iteration 5041 */ 5042 r = rr; 5043 } 5044 5045 /* new leading digit? */ 5046 if (r != 0) { 5047 /* add a MSB which is always 1 at this point */ 5048 *tmpb = 1; 5049 ++(b->used); 5050 } 5051 5052 /* now zero any excess digits on the destination 5053 * that we didn't write to 5054 */ 5055 tmpb = b->dp + b->used; 5056 for (x = b->used; x < oldused; x++) { 5057 *tmpb++ = 0; 5058 } 5059 } 5060 b->sign = a->sign; 5061 return MP_OKAY; 5062} 5063#endif 5064 5065/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */ 5066/* $Revision: 1.3 $ */ 5067/* $Date: 2006/03/31 14:18:44 $ */ 5068 5069/* End: bn_mp_mul_2.c */ 5070 5071/* Start: bn_mp_mul_2d.c */ 5072#include <tommath.h> 5073#ifdef BN_MP_MUL_2D_C 5074/* LibTomMath, multiple-precision integer library -- Tom St Denis 5075 * 5076 * LibTomMath is a library that provides multiple-precision 5077 * integer arithmetic as well as number theoretic functionality. 5078 * 5079 * The library was designed directly after the MPI library by 5080 * Michael Fromberger but has been written from scratch with 5081 * additional optimizations in place. 5082 * 5083 * The library is free for all purposes without any express 5084 * guarantee it works. 5085 * 5086 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5087 */ 5088 5089/* shift left by a certain bit count */ 5090int mp_mul_2d (mp_int * a, int b, mp_int * c) 5091{ 5092 mp_digit d; 5093 int res; 5094 5095 /* copy */ 5096 if (a != c) { 5097 if ((res = mp_copy (a, c)) != MP_OKAY) { 5098 return res; 5099 } 5100 } 5101 5102 if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { 5103 if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { 5104 return res; 5105 } 5106 } 5107 5108 /* shift by as many digits in the bit count */ 5109 if (b >= (int)DIGIT_BIT) { 5110 if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { 5111 return res; 5112 } 5113 } 5114 5115 /* shift any bit count < DIGIT_BIT */ 5116 d = (mp_digit) (b % DIGIT_BIT); 5117 if (d != 0) { 5118 register mp_digit *tmpc, shift, mask, r, rr; 5119 register int x; 5120 5121 /* bitmask for carries */ 5122 mask = (((mp_digit)1) << d) - 1; 5123 5124 /* shift for msbs */ 5125 shift = DIGIT_BIT - d; 5126 5127 /* alias */ 5128 tmpc = c->dp; 5129 5130 /* carry */ 5131 r = 0; 5132 for (x = 0; x < c->used; x++) { 5133 /* get the higher bits of the current word */ 5134 rr = (*tmpc >> shift) & mask; 5135 5136 /* shift the current word and OR in the carry */ 5137 *tmpc = ((*tmpc << d) | r) & MP_MASK; 5138 ++tmpc; 5139 5140 /* set the carry to the carry bits of the current word */ 5141 r = rr; 5142 } 5143 5144 /* set final carry */ 5145 if (r != 0) { 5146 c->dp[(c->used)++] = r; 5147 } 5148 } 5149 mp_clamp (c); 5150 return MP_OKAY; 5151} 5152#endif 5153 5154/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */ 5155/* $Revision: 1.3 $ */ 5156/* $Date: 2006/03/31 14:18:44 $ */ 5157 5158/* End: bn_mp_mul_2d.c */ 5159 5160/* Start: bn_mp_mul_d.c */ 5161#include <tommath.h> 5162#ifdef BN_MP_MUL_D_C 5163/* LibTomMath, multiple-precision integer library -- Tom St Denis 5164 * 5165 * LibTomMath is a library that provides multiple-precision 5166 * integer arithmetic as well as number theoretic functionality. 5167 * 5168 * The library was designed directly after the MPI library by 5169 * Michael Fromberger but has been written from scratch with 5170 * additional optimizations in place. 5171 * 5172 * The library is free for all purposes without any express 5173 * guarantee it works. 5174 * 5175 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5176 */ 5177 5178/* multiply by a digit */ 5179int 5180mp_mul_d (mp_int * a, mp_digit b, mp_int * c) 5181{ 5182 mp_digit u, *tmpa, *tmpc; 5183 mp_word r; 5184 int ix, res, olduse; 5185 5186 /* make sure c is big enough to hold a*b */ 5187 if (c->alloc < a->used + 1) { 5188 if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { 5189 return res; 5190 } 5191 } 5192 5193 /* get the original destinations used count */ 5194 olduse = c->used; 5195 5196 /* set the sign */ 5197 c->sign = a->sign; 5198 5199 /* alias for a->dp [source] */ 5200 tmpa = a->dp; 5201 5202 /* alias for c->dp [dest] */ 5203 tmpc = c->dp; 5204 5205 /* zero carry */ 5206 u = 0; 5207 5208 /* compute columns */ 5209 for (ix = 0; ix < a->used; ix++) { 5210 /* compute product and carry sum for this term */ 5211 r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); 5212 5213 /* mask off higher bits to get a single digit */ 5214 *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); 5215 5216 /* send carry into next iteration */ 5217 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); 5218 } 5219 5220 /* store final carry [if any] and increment ix offset */ 5221 *tmpc++ = u; 5222 ++ix; 5223 5224 /* now zero digits above the top */ 5225 while (ix++ < olduse) { 5226 *tmpc++ = 0; 5227 } 5228 5229 /* set used count */ 5230 c->used = a->used + 1; 5231 mp_clamp(c); 5232 5233 return MP_OKAY; 5234} 5235#endif 5236 5237/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */ 5238/* $Revision: 1.3 $ */ 5239/* $Date: 2006/03/31 14:18:44 $ */ 5240 5241/* End: bn_mp_mul_d.c */ 5242 5243/* Start: bn_mp_mulmod.c */ 5244#include <tommath.h> 5245#ifdef BN_MP_MULMOD_C 5246/* LibTomMath, multiple-precision integer library -- Tom St Denis 5247 * 5248 * LibTomMath is a library that provides multiple-precision 5249 * integer arithmetic as well as number theoretic functionality. 5250 * 5251 * The library was designed directly after the MPI library by 5252 * Michael Fromberger but has been written from scratch with 5253 * additional optimizations in place. 5254 * 5255 * The library is free for all purposes without any express 5256 * guarantee it works. 5257 * 5258 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5259 */ 5260 5261/* d = a * b (mod c) */ 5262int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) 5263{ 5264 int res; 5265 mp_int t; 5266 5267 if ((res = mp_init (&t)) != MP_OKAY) { 5268 return res; 5269 } 5270 5271 if ((res = mp_mul (a, b, &t)) != MP_OKAY) { 5272 mp_clear (&t); 5273 return res; 5274 } 5275 res = mp_mod (&t, c, d); 5276 mp_clear (&t); 5277 return res; 5278} 5279#endif 5280 5281/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */ 5282/* $Revision: 1.4 $ */ 5283/* $Date: 2006/03/31 14:18:44 $ */ 5284 5285/* End: bn_mp_mulmod.c */ 5286 5287/* Start: bn_mp_n_root.c */ 5288#include <tommath.h> 5289#ifdef BN_MP_N_ROOT_C 5290/* LibTomMath, multiple-precision integer library -- Tom St Denis 5291 * 5292 * LibTomMath is a library that provides multiple-precision 5293 * integer arithmetic as well as number theoretic functionality. 5294 * 5295 * The library was designed directly after the MPI library by 5296 * Michael Fromberger but has been written from scratch with 5297 * additional optimizations in place. 5298 * 5299 * The library is free for all purposes without any express 5300 * guarantee it works. 5301 * 5302 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5303 */ 5304 5305/* find the n'th root of an integer 5306 * 5307 * Result found such that (c)**b <= a and (c+1)**b > a 5308 * 5309 * This algorithm uses Newton's approximation 5310 * x[i+1] = x[i] - f(x[i])/f'(x[i]) 5311 * which will find the root in log(N) time where 5312 * each step involves a fair bit. This is not meant to 5313 * find huge roots [square and cube, etc]. 5314 */ 5315int mp_n_root (mp_int * a, mp_digit b, mp_int * c) 5316{ 5317 mp_int t1, t2, t3; 5318 int res, neg; 5319 5320 /* input must be positive if b is even */ 5321 if ((b & 1) == 0 && a->sign == MP_NEG) { 5322 return MP_VAL; 5323 } 5324 5325 if ((res = mp_init (&t1)) != MP_OKAY) { 5326 return res; 5327 } 5328 5329 if ((res = mp_init (&t2)) != MP_OKAY) { 5330 goto LBL_T1; 5331 } 5332 5333 if ((res = mp_init (&t3)) != MP_OKAY) { 5334 goto LBL_T2; 5335 } 5336 5337 /* if a is negative fudge the sign but keep track */ 5338 neg = a->sign; 5339 a->sign = MP_ZPOS; 5340 5341 /* t2 = 2 */ 5342 mp_set (&t2, 2); 5343 5344 do { 5345 /* t1 = t2 */ 5346 if ((res = mp_copy (&t2, &t1)) != MP_OKAY) { 5347 goto LBL_T3; 5348 } 5349 5350 /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ 5351 5352 /* t3 = t1**(b-1) */ 5353 if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) { 5354 goto LBL_T3; 5355 } 5356 5357 /* numerator */ 5358 /* t2 = t1**b */ 5359 if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) { 5360 goto LBL_T3; 5361 } 5362 5363 /* t2 = t1**b - a */ 5364 if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) { 5365 goto LBL_T3; 5366 } 5367 5368 /* denominator */ 5369 /* t3 = t1**(b-1) * b */ 5370 if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) { 5371 goto LBL_T3; 5372 } 5373 5374 /* t3 = (t1**b - a)/(b * t1**(b-1)) */ 5375 if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) { 5376 goto LBL_T3; 5377 } 5378 5379 if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) { 5380 goto LBL_T3; 5381 } 5382 } while (mp_cmp (&t1, &t2) != MP_EQ); 5383 5384 /* result can be off by a few so check */ 5385 for (;;) { 5386 if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) { 5387 goto LBL_T3; 5388 } 5389 5390 if (mp_cmp (&t2, a) == MP_GT) { 5391 if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { 5392 goto LBL_T3; 5393 } 5394 } else { 5395 break; 5396 } 5397 } 5398 5399 /* reset the sign of a first */ 5400 a->sign = neg; 5401 5402 /* set the result */ 5403 mp_exch (&t1, c); 5404 5405 /* set the sign of the result */ 5406 c->sign = neg; 5407 5408 res = MP_OKAY; 5409 5410LBL_T3:mp_clear (&t3); 5411LBL_T2:mp_clear (&t2); 5412LBL_T1:mp_clear (&t1); 5413 return res; 5414} 5415#endif 5416 5417/* $Source: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */ 5418/* $Revision: 1.3 $ */ 5419/* $Date: 2006/03/31 14:18:44 $ */ 5420 5421/* End: bn_mp_n_root.c */ 5422 5423/* Start: bn_mp_neg.c */ 5424#include <tommath.h> 5425#ifdef BN_MP_NEG_C 5426/* LibTomMath, multiple-precision integer library -- Tom St Denis 5427 * 5428 * LibTomMath is a library that provides multiple-precision 5429 * integer arithmetic as well as number theoretic functionality. 5430 * 5431 * The library was designed directly after the MPI library by 5432 * Michael Fromberger but has been written from scratch with 5433 * additional optimizations in place. 5434 * 5435 * The library is free for all purposes without any express 5436 * guarantee it works. 5437 * 5438 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5439 */ 5440 5441/* b = -a */ 5442int mp_neg (mp_int * a, mp_int * b) 5443{ 5444 int res; 5445 if (a != b) { 5446 if ((res = mp_copy (a, b)) != MP_OKAY) { 5447 return res; 5448 } 5449 } 5450 5451 if (mp_iszero(b) != MP_YES) { 5452 b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; 5453 } else { 5454 b->sign = MP_ZPOS; 5455 } 5456 5457 return MP_OKAY; 5458} 5459#endif 5460 5461/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */ 5462/* $Revision: 1.3 $ */ 5463/* $Date: 2006/03/31 14:18:44 $ */ 5464 5465/* End: bn_mp_neg.c */ 5466 5467/* Start: bn_mp_or.c */ 5468#include <tommath.h> 5469#ifdef BN_MP_OR_C 5470/* LibTomMath, multiple-precision integer library -- Tom St Denis 5471 * 5472 * LibTomMath is a library that provides multiple-precision 5473 * integer arithmetic as well as number theoretic functionality. 5474 * 5475 * The library was designed directly after the MPI library by 5476 * Michael Fromberger but has been written from scratch with 5477 * additional optimizations in place. 5478 * 5479 * The library is free for all purposes without any express 5480 * guarantee it works. 5481 * 5482 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5483 */ 5484 5485/* OR two ints together */ 5486int mp_or (mp_int * a, mp_int * b, mp_int * c) 5487{ 5488 int res, ix, px; 5489 mp_int t, *x; 5490 5491 if (a->used > b->used) { 5492 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 5493 return res; 5494 } 5495 px = b->used; 5496 x = b; 5497 } else { 5498 if ((res = mp_init_copy (&t, b)) != MP_OKAY) { 5499 return res; 5500 } 5501 px = a->used; 5502 x = a; 5503 } 5504 5505 for (ix = 0; ix < px; ix++) { 5506 t.dp[ix] |= x->dp[ix]; 5507 } 5508 mp_clamp (&t); 5509 mp_exch (c, &t); 5510 mp_clear (&t); 5511 return MP_OKAY; 5512} 5513#endif 5514 5515/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */ 5516/* $Revision: 1.3 $ */ 5517/* $Date: 2006/03/31 14:18:44 $ */ 5518 5519/* End: bn_mp_or.c */ 5520 5521/* Start: bn_mp_prime_fermat.c */ 5522#include <tommath.h> 5523#ifdef BN_MP_PRIME_FERMAT_C 5524/* LibTomMath, multiple-precision integer library -- Tom St Denis 5525 * 5526 * LibTomMath is a library that provides multiple-precision 5527 * integer arithmetic as well as number theoretic functionality. 5528 * 5529 * The library was designed directly after the MPI library by 5530 * Michael Fromberger but has been written from scratch with 5531 * additional optimizations in place. 5532 * 5533 * The library is free for all purposes without any express 5534 * guarantee it works. 5535 * 5536 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5537 */ 5538 5539/* performs one Fermat test. 5540 * 5541 * If "a" were prime then b**a == b (mod a) since the order of 5542 * the multiplicative sub-group would be phi(a) = a-1. That means 5543 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a). 5544 * 5545 * Sets result to 1 if the congruence holds, or zero otherwise. 5546 */ 5547int mp_prime_fermat (mp_int * a, mp_int * b, int *result) 5548{ 5549 mp_int t; 5550 int err; 5551 5552 /* default to composite */ 5553 *result = MP_NO; 5554 5555 /* ensure b > 1 */ 5556 if (mp_cmp_d(b, 1) != MP_GT) { 5557 return MP_VAL; 5558 } 5559 5560 /* init t */ 5561 if ((err = mp_init (&t)) != MP_OKAY) { 5562 return err; 5563 } 5564 5565 /* compute t = b**a mod a */ 5566 if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) { 5567 goto LBL_T; 5568 } 5569 5570 /* is it equal to b? */ 5571 if (mp_cmp (&t, b) == MP_EQ) { 5572 *result = MP_YES; 5573 } 5574 5575 err = MP_OKAY; 5576LBL_T:mp_clear (&t); 5577 return err; 5578} 5579#endif 5580 5581/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */ 5582/* $Revision: 1.3 $ */ 5583/* $Date: 2006/03/31 14:18:44 $ */ 5584 5585/* End: bn_mp_prime_fermat.c */ 5586 5587/* Start: bn_mp_prime_is_divisible.c */ 5588#include <tommath.h> 5589#ifdef BN_MP_PRIME_IS_DIVISIBLE_C 5590/* LibTomMath, multiple-precision integer library -- Tom St Denis 5591 * 5592 * LibTomMath is a library that provides multiple-precision 5593 * integer arithmetic as well as number theoretic functionality. 5594 * 5595 * The library was designed directly after the MPI library by 5596 * Michael Fromberger but has been written from scratch with 5597 * additional optimizations in place. 5598 * 5599 * The library is free for all purposes without any express 5600 * guarantee it works. 5601 * 5602 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5603 */ 5604 5605/* determines if an integers is divisible by one 5606 * of the first PRIME_SIZE primes or not 5607 * 5608 * sets result to 0 if not, 1 if yes 5609 */ 5610int mp_prime_is_divisible (mp_int * a, int *result) 5611{ 5612 int err, ix; 5613 mp_digit res; 5614 5615 /* default to not */ 5616 *result = MP_NO; 5617 5618 for (ix = 0; ix < PRIME_SIZE; ix++) { 5619 /* what is a mod LBL_prime_tab[ix] */ 5620 if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) { 5621 return err; 5622 } 5623 5624 /* is the residue zero? */ 5625 if (res == 0) { 5626 *result = MP_YES; 5627 return MP_OKAY; 5628 } 5629 } 5630 5631 return MP_OKAY; 5632} 5633#endif 5634 5635/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */ 5636/* $Revision: 1.3 $ */ 5637/* $Date: 2006/03/31 14:18:44 $ */ 5638 5639/* End: bn_mp_prime_is_divisible.c */ 5640 5641/* Start: bn_mp_prime_is_prime.c */ 5642#include <tommath.h> 5643#ifdef BN_MP_PRIME_IS_PRIME_C 5644/* LibTomMath, multiple-precision integer library -- Tom St Denis 5645 * 5646 * LibTomMath is a library that provides multiple-precision 5647 * integer arithmetic as well as number theoretic functionality. 5648 * 5649 * The library was designed directly after the MPI library by 5650 * Michael Fromberger but has been written from scratch with 5651 * additional optimizations in place. 5652 * 5653 * The library is free for all purposes without any express 5654 * guarantee it works. 5655 * 5656 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5657 */ 5658 5659/* performs a variable number of rounds of Miller-Rabin 5660 * 5661 * Probability of error after t rounds is no more than 5662 5663 * 5664 * Sets result to 1 if probably prime, 0 otherwise 5665 */ 5666int mp_prime_is_prime (mp_int * a, int t, int *result) 5667{ 5668 mp_int b; 5669 int ix, err, res; 5670 5671 /* default to no */ 5672 *result = MP_NO; 5673 5674 /* valid value of t? */ 5675 if (t <= 0 || t > PRIME_SIZE) { 5676 return MP_VAL; 5677 } 5678 5679 /* is the input equal to one of the primes in the table? */ 5680 for (ix = 0; ix < PRIME_SIZE; ix++) { 5681 if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { 5682 *result = 1; 5683 return MP_OKAY; 5684 } 5685 } 5686 5687 /* first perform trial division */ 5688 if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { 5689 return err; 5690 } 5691 5692 /* return if it was trivially divisible */ 5693 if (res == MP_YES) { 5694 return MP_OKAY; 5695 } 5696 5697 /* now perform the miller-rabin rounds */ 5698 if ((err = mp_init (&b)) != MP_OKAY) { 5699 return err; 5700 } 5701 5702 for (ix = 0; ix < t; ix++) { 5703 /* set the prime */ 5704 mp_set (&b, ltm_prime_tab[ix]); 5705 5706 if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { 5707 goto LBL_B; 5708 } 5709 5710 if (res == MP_NO) { 5711 goto LBL_B; 5712 } 5713 } 5714 5715 /* passed the test */ 5716 *result = MP_YES; 5717LBL_B:mp_clear (&b); 5718 return err; 5719} 5720#endif 5721 5722/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */ 5723/* $Revision: 1.3 $ */ 5724/* $Date: 2006/03/31 14:18:44 $ */ 5725 5726/* End: bn_mp_prime_is_prime.c */ 5727 5728/* Start: bn_mp_prime_miller_rabin.c */ 5729#include <tommath.h> 5730#ifdef BN_MP_PRIME_MILLER_RABIN_C 5731/* LibTomMath, multiple-precision integer library -- Tom St Denis 5732 * 5733 * LibTomMath is a library that provides multiple-precision 5734 * integer arithmetic as well as number theoretic functionality. 5735 * 5736 * The library was designed directly after the MPI library by 5737 * Michael Fromberger but has been written from scratch with 5738 * additional optimizations in place. 5739 * 5740 * The library is free for all purposes without any express 5741 * guarantee it works. 5742 * 5743 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5744 */ 5745 5746/* Miller-Rabin test of "a" to the base of "b" as described in 5747 * HAC pp. 139 Algorithm 4.24 5748 * 5749 * Sets result to 0 if definitely composite or 1 if probably prime. 5750 * Randomly the chance of error is no more than 1/4 and often 5751 * very much lower. 5752 */ 5753int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) 5754{ 5755 mp_int n1, y, r; 5756 int s, j, err; 5757 5758 /* default */ 5759 *result = MP_NO; 5760 5761 /* ensure b > 1 */ 5762 if (mp_cmp_d(b, 1) != MP_GT) { 5763 return MP_VAL; 5764 } 5765 5766 /* get n1 = a - 1 */ 5767 if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { 5768 return err; 5769 } 5770 if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { 5771 goto LBL_N1; 5772 } 5773 5774 /* set 2**s * r = n1 */ 5775 if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { 5776 goto LBL_N1; 5777 } 5778 5779 /* count the number of least significant bits 5780 * which are zero 5781 */ 5782 s = mp_cnt_lsb(&r); 5783 5784 /* now divide n - 1 by 2**s */ 5785 if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) { 5786 goto LBL_R; 5787 } 5788 5789 /* compute y = b**r mod a */ 5790 if ((err = mp_init (&y)) != MP_OKAY) { 5791 goto LBL_R; 5792 } 5793 if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { 5794 goto LBL_Y; 5795 } 5796 5797 /* if y != 1 and y != n1 do */ 5798 if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { 5799 j = 1; 5800 /* while j <= s-1 and y != n1 */ 5801 while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { 5802 if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { 5803 goto LBL_Y; 5804 } 5805 5806 /* if y == 1 then composite */ 5807 if (mp_cmp_d (&y, 1) == MP_EQ) { 5808 goto LBL_Y; 5809 } 5810 5811 ++j; 5812 } 5813 5814 /* if y != n1 then composite */ 5815 if (mp_cmp (&y, &n1) != MP_EQ) { 5816 goto LBL_Y; 5817 } 5818 } 5819 5820 /* probably prime now */ 5821 *result = MP_YES; 5822LBL_Y:mp_clear (&y); 5823LBL_R:mp_clear (&r); 5824LBL_N1:mp_clear (&n1); 5825 return err; 5826} 5827#endif 5828 5829/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */ 5830/* $Revision: 1.3 $ */ 5831/* $Date: 2006/03/31 14:18:44 $ */ 5832 5833/* End: bn_mp_prime_miller_rabin.c */ 5834 5835/* Start: bn_mp_prime_next_prime.c */ 5836#include <tommath.h> 5837#ifdef BN_MP_PRIME_NEXT_PRIME_C 5838/* LibTomMath, multiple-precision integer library -- Tom St Denis 5839 * 5840 * LibTomMath is a library that provides multiple-precision 5841 * integer arithmetic as well as number theoretic functionality. 5842 * 5843 * The library was designed directly after the MPI library by 5844 * Michael Fromberger but has been written from scratch with 5845 * additional optimizations in place. 5846 * 5847 * The library is free for all purposes without any express 5848 * guarantee it works. 5849 * 5850 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 5851 */ 5852 5853/* finds the next prime after the number "a" using "t" trials 5854 * of Miller-Rabin. 5855 * 5856 * bbs_style = 1 means the prime must be congruent to 3 mod 4 5857 */ 5858int mp_prime_next_prime(mp_int *a, int t, int bbs_style) 5859{ 5860 int err, res, x, y; 5861 mp_digit res_tab[PRIME_SIZE], step, kstep; 5862 mp_int b; 5863 5864 /* ensure t is valid */ 5865 if (t <= 0 || t > PRIME_SIZE) { 5866 return MP_VAL; 5867 } 5868 5869 /* force positive */ 5870 a->sign = MP_ZPOS; 5871 5872 /* simple algo if a is less than the largest prime in the table */ 5873 if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) { 5874 /* find which prime it is bigger than */ 5875 for (x = PRIME_SIZE - 2; x >= 0; x--) { 5876 if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) { 5877 if (bbs_style == 1) { 5878 /* ok we found a prime smaller or 5879 * equal [so the next is larger] 5880 * 5881 * however, the prime must be 5882 * congruent to 3 mod 4 5883 */ 5884 if ((ltm_prime_tab[x + 1] & 3) != 3) { 5885 /* scan upwards for a prime congruent to 3 mod 4 */ 5886 for (y = x + 1; y < PRIME_SIZE; y++) { 5887 if ((ltm_prime_tab[y] & 3) == 3) { 5888 mp_set(a, ltm_prime_tab[y]); 5889 return MP_OKAY; 5890 } 5891 } 5892 } 5893 } else { 5894 mp_set(a, ltm_prime_tab[x + 1]); 5895 return MP_OKAY; 5896 } 5897 } 5898 } 5899 /* at this point a maybe 1 */ 5900 if (mp_cmp_d(a, 1) == MP_EQ) { 5901 mp_set(a, 2); 5902 return MP_OKAY; 5903 } 5904 /* fall through to the sieve */ 5905 } 5906 5907 /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ 5908 if (bbs_style == 1) { 5909 kstep = 4; 5910 } else { 5911 kstep = 2; 5912 } 5913 5914 /* at this point we will use a combination of a sieve and Miller-Rabin */ 5915 5916 if (bbs_style == 1) { 5917 /* if a mod 4 != 3 subtract the correct value to make it so */ 5918 if ((a->dp[0] & 3) != 3) { 5919 if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; }; 5920 } 5921 } else { 5922 if (mp_iseven(a) == 1) { 5923 /* force odd */ 5924 if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { 5925 return err; 5926 } 5927 } 5928 } 5929 5930 /* generate the restable */ 5931 for (x = 1; x < PRIME_SIZE; x++) { 5932 if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) { 5933 return err; 5934 } 5935 } 5936 5937 /* init temp used for Miller-Rabin Testing */ 5938 if ((err = mp_init(&b)) != MP_OKAY) { 5939 return err; 5940 } 5941 5942 for (;;) { 5943 /* skip to the next non-trivially divisible candidate */ 5944 step = 0; 5945 do { 5946 /* y == 1 if any residue was zero [e.g. cannot be prime] */ 5947 y = 0; 5948 5949 /* increase step to next candidate */ 5950 step += kstep; 5951 5952 /* compute the new residue without using division */ 5953 for (x = 1; x < PRIME_SIZE; x++) { 5954 /* add the step to each residue */ 5955 res_tab[x] += kstep; 5956 5957 /* subtract the modulus [instead of using division] */ 5958 if (res_tab[x] >= ltm_prime_tab[x]) { 5959 res_tab[x] -= ltm_prime_tab[x]; 5960 } 5961 5962 /* set flag if zero */ 5963 if (res_tab[x] == 0) { 5964 y = 1; 5965 } 5966 } 5967 } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep)); 5968 5969 /* add the step */ 5970 if ((err = mp_add_d(a, step, a)) != MP_OKAY) { 5971 goto LBL_ERR; 5972 } 5973 5974 /* if didn't pass sieve and step == MAX then skip test */ 5975 if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) { 5976 continue; 5977 } 5978 5979 /* is this prime? */ 5980 for (x = 0; x < t; x++) { 5981 mp_set(&b, ltm_prime_tab[t]); 5982 if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { 5983 goto LBL_ERR; 5984 } 5985 if (res == MP_NO) { 5986 break; 5987 } 5988 } 5989 5990 if (res == MP_YES) { 5991 break; 5992 } 5993 } 5994 5995 err = MP_OKAY; 5996LBL_ERR: 5997 mp_clear(&b); 5998 return err; 5999} 6000 6001#endif 6002 6003/* $Source: /cvs/libtom/libtommath/bn_mp_prime_next_prime.c,v $ */ 6004/* $Revision: 1.3 $ */ 6005/* $Date: 2006/03/31 14:18:44 $ */ 6006 6007/* End: bn_mp_prime_next_prime.c */ 6008 6009/* Start: bn_mp_prime_rabin_miller_trials.c */ 6010#include <tommath.h> 6011#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C 6012/* LibTomMath, multiple-precision integer library -- Tom St Denis 6013 * 6014 * LibTomMath is a library that provides multiple-precision 6015 * integer arithmetic as well as number theoretic functionality. 6016 * 6017 * The library was designed directly after the MPI library by 6018 * Michael Fromberger but has been written from scratch with 6019 * additional optimizations in place. 6020 * 6021 * The library is free for all purposes without any express 6022 * guarantee it works. 6023 * 6024 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6025 */ 6026 6027 6028static const struct { 6029 int k, t; 6030} sizes[] = { 6031{ 128, 28 }, 6032{ 256, 16 }, 6033{ 384, 10 }, 6034{ 512, 7 }, 6035{ 640, 6 }, 6036{ 768, 5 }, 6037{ 896, 4 }, 6038{ 1024, 4 } 6039}; 6040 6041/* returns # of RM trials required for a given bit size */ 6042int mp_prime_rabin_miller_trials(int size) 6043{ 6044 int x; 6045 6046 for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { 6047 if (sizes[x].k == size) { 6048 return sizes[x].t; 6049 } else if (sizes[x].k > size) { 6050 return (x == 0) ? sizes[0].t : sizes[x - 1].t; 6051 } 6052 } 6053 return sizes[x-1].t + 1; 6054} 6055 6056 6057#endif 6058 6059/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */ 6060/* $Revision: 1.3 $ */ 6061/* $Date: 2006/03/31 14:18:44 $ */ 6062 6063/* End: bn_mp_prime_rabin_miller_trials.c */ 6064 6065/* Start: bn_mp_prime_random_ex.c */ 6066#include <tommath.h> 6067#ifdef BN_MP_PRIME_RANDOM_EX_C 6068/* LibTomMath, multiple-precision integer library -- Tom St Denis 6069 * 6070 * LibTomMath is a library that provides multiple-precision 6071 * integer arithmetic as well as number theoretic functionality. 6072 * 6073 * The library was designed directly after the MPI library by 6074 * Michael Fromberger but has been written from scratch with 6075 * additional optimizations in place. 6076 * 6077 * The library is free for all purposes without any express 6078 * guarantee it works. 6079 * 6080 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6081 */ 6082 6083/* makes a truly random prime of a given size (bits), 6084 * 6085 * Flags are as follows: 6086 * 6087 * LTM_PRIME_BBS - make prime congruent to 3 mod 4 6088 * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) 6089 * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero 6090 * LTM_PRIME_2MSB_ON - make the 2nd highest bit one 6091 * 6092 * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can 6093 * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself 6094 * so it can be NULL 6095 * 6096 */ 6097 6098/* This is possibly the mother of all prime generation functions, muahahahahaha! */ 6099int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat) 6100{ 6101 unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; 6102 int res, err, bsize, maskOR_msb_offset; 6103 6104 /* sanity check the input */ 6105 if (size <= 1 || t <= 0) { 6106 return MP_VAL; 6107 } 6108 6109 /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */ 6110 if (flags & LTM_PRIME_SAFE) { 6111 flags |= LTM_PRIME_BBS; 6112 } 6113 6114 /* calc the byte size */ 6115 bsize = (size>>3) + ((size&7)?1:0); 6116 6117 /* we need a buffer of bsize bytes */ 6118 tmp = OPT_CAST(unsigned char) XMALLOC(bsize); 6119 if (tmp == NULL) { 6120 return MP_MEM; 6121 } 6122 6123 /* calc the maskAND value for the MSbyte*/ 6124 maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7))); 6125 6126 /* calc the maskOR_msb */ 6127 maskOR_msb = 0; 6128 maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; 6129 if (flags & LTM_PRIME_2MSB_ON) { 6130 maskOR_msb |= 0x80 >> ((9 - size) & 7); 6131 } 6132 6133 /* get the maskOR_lsb */ 6134 maskOR_lsb = 1; 6135 if (flags & LTM_PRIME_BBS) { 6136 maskOR_lsb |= 3; 6137 } 6138 6139 do { 6140 /* read the bytes */ 6141 if (cb(tmp, bsize, dat) != bsize) { 6142 err = MP_VAL; 6143 goto error; 6144 } 6145 6146 /* work over the MSbyte */ 6147 tmp[0] &= maskAND; 6148 tmp[0] |= 1 << ((size - 1) & 7); 6149 6150 /* mix in the maskORs */ 6151 tmp[maskOR_msb_offset] |= maskOR_msb; 6152 tmp[bsize-1] |= maskOR_lsb; 6153 6154 /* read it in */ 6155 if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; } 6156 6157 /* is it prime? */ 6158 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } 6159 if (res == MP_NO) { 6160 continue; 6161 } 6162 6163 if (flags & LTM_PRIME_SAFE) { 6164 /* see if (a-1)/2 is prime */ 6165 if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; } 6166 if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; } 6167 6168 /* is it prime? */ 6169 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } 6170 } 6171 } while (res == MP_NO); 6172 6173 if (flags & LTM_PRIME_SAFE) { 6174 /* restore a to the original value */ 6175 if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; } 6176 if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; } 6177 } 6178 6179 err = MP_OKAY; 6180error: 6181 XFREE(tmp); 6182 return err; 6183} 6184 6185 6186#endif 6187 6188/* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */ 6189/* $Revision: 1.4 $ */ 6190/* $Date: 2006/03/31 14:18:44 $ */ 6191 6192/* End: bn_mp_prime_random_ex.c */ 6193 6194/* Start: bn_mp_radix_size.c */ 6195#include <tommath.h> 6196#ifdef BN_MP_RADIX_SIZE_C 6197/* LibTomMath, multiple-precision integer library -- Tom St Denis 6198 * 6199 * LibTomMath is a library that provides multiple-precision 6200 * integer arithmetic as well as number theoretic functionality. 6201 * 6202 * The library was designed directly after the MPI library by 6203 * Michael Fromberger but has been written from scratch with 6204 * additional optimizations in place. 6205 * 6206 * The library is free for all purposes without any express 6207 * guarantee it works. 6208 * 6209 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6210 */ 6211 6212/* returns size of ASCII reprensentation */ 6213int mp_radix_size (mp_int * a, int radix, int *size) 6214{ 6215 int res, digs; 6216 mp_int t; 6217 mp_digit d; 6218 6219 *size = 0; 6220 6221 /* special case for binary */ 6222 if (radix == 2) { 6223 *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; 6224 return MP_OKAY; 6225 } 6226 6227 /* make sure the radix is in range */ 6228 if (radix < 2 || radix > 64) { 6229 return MP_VAL; 6230 } 6231 6232 if (mp_iszero(a) == MP_YES) { 6233 *size = 2; 6234 return MP_OKAY; 6235 } 6236 6237 /* digs is the digit count */ 6238 digs = 0; 6239 6240 /* if it's negative add one for the sign */ 6241 if (a->sign == MP_NEG) { 6242 ++digs; 6243 } 6244 6245 /* init a copy of the input */ 6246 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 6247 return res; 6248 } 6249 6250 /* force temp to positive */ 6251 t.sign = MP_ZPOS; 6252 6253 /* fetch out all of the digits */ 6254 while (mp_iszero (&t) == MP_NO) { 6255 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { 6256 mp_clear (&t); 6257 return res; 6258 } 6259 ++digs; 6260 } 6261 mp_clear (&t); 6262 6263 /* return digs + 1, the 1 is for the NULL byte that would be required. */ 6264 *size = digs + 1; 6265 return MP_OKAY; 6266} 6267 6268#endif 6269 6270/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */ 6271/* $Revision: 1.4 $ */ 6272/* $Date: 2006/03/31 14:18:44 $ */ 6273 6274/* End: bn_mp_radix_size.c */ 6275 6276/* Start: bn_mp_radix_smap.c */ 6277#include <tommath.h> 6278#ifdef BN_MP_RADIX_SMAP_C 6279/* LibTomMath, multiple-precision integer library -- Tom St Denis 6280 * 6281 * LibTomMath is a library that provides multiple-precision 6282 * integer arithmetic as well as number theoretic functionality. 6283 * 6284 * The library was designed directly after the MPI library by 6285 * Michael Fromberger but has been written from scratch with 6286 * additional optimizations in place. 6287 * 6288 * The library is free for all purposes without any express 6289 * guarantee it works. 6290 * 6291 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6292 */ 6293 6294/* chars used in radix conversions */ 6295const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; 6296#endif 6297 6298/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */ 6299/* $Revision: 1.3 $ */ 6300/* $Date: 2006/03/31 14:18:44 $ */ 6301 6302/* End: bn_mp_radix_smap.c */ 6303 6304/* Start: bn_mp_rand.c */ 6305#include <tommath.h> 6306#ifdef BN_MP_RAND_C 6307/* LibTomMath, multiple-precision integer library -- Tom St Denis 6308 * 6309 * LibTomMath is a library that provides multiple-precision 6310 * integer arithmetic as well as number theoretic functionality. 6311 * 6312 * The library was designed directly after the MPI library by 6313 * Michael Fromberger but has been written from scratch with 6314 * additional optimizations in place. 6315 * 6316 * The library is free for all purposes without any express 6317 * guarantee it works. 6318 * 6319 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6320 */ 6321 6322/* makes a pseudo-random int of a given size */ 6323int 6324mp_rand (mp_int * a, int digits) 6325{ 6326 int res; 6327 mp_digit d; 6328 6329 mp_zero (a); 6330 if (digits <= 0) { 6331 return MP_OKAY; 6332 } 6333 6334 /* first place a random non-zero digit */ 6335 do { 6336 d = ((mp_digit) abs (rand ())) & MP_MASK; 6337 } while (d == 0); 6338 6339 if ((res = mp_add_d (a, d, a)) != MP_OKAY) { 6340 return res; 6341 } 6342 6343 while (--digits > 0) { 6344 if ((res = mp_lshd (a, 1)) != MP_OKAY) { 6345 return res; 6346 } 6347 6348 if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { 6349 return res; 6350 } 6351 } 6352 6353 return MP_OKAY; 6354} 6355#endif 6356 6357/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */ 6358/* $Revision: 1.3 $ */ 6359/* $Date: 2006/03/31 14:18:44 $ */ 6360 6361/* End: bn_mp_rand.c */ 6362 6363/* Start: bn_mp_read_radix.c */ 6364#include <tommath.h> 6365#ifdef BN_MP_READ_RADIX_C 6366/* LibTomMath, multiple-precision integer library -- Tom St Denis 6367 * 6368 * LibTomMath is a library that provides multiple-precision 6369 * integer arithmetic as well as number theoretic functionality. 6370 * 6371 * The library was designed directly after the MPI library by 6372 * Michael Fromberger but has been written from scratch with 6373 * additional optimizations in place. 6374 * 6375 * The library is free for all purposes without any express 6376 * guarantee it works. 6377 * 6378 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6379 */ 6380 6381/* read a string [ASCII] in a given radix */ 6382int mp_read_radix (mp_int * a, const char *str, int radix) 6383{ 6384 int y, res, neg; 6385 char ch; 6386 6387 /* zero the digit bignum */ 6388 mp_zero(a); 6389 6390 /* make sure the radix is ok */ 6391 if (radix < 2 || radix > 64) { 6392 return MP_VAL; 6393 } 6394 6395 /* if the leading digit is a 6396 * minus set the sign to negative. 6397 */ 6398 if (*str == '-') { 6399 ++str; 6400 neg = MP_NEG; 6401 } else { 6402 neg = MP_ZPOS; 6403 } 6404 6405 /* set the integer to the default of zero */ 6406 mp_zero (a); 6407 6408 /* process each digit of the string */ 6409 while (*str) { 6410 /* if the radix < 36 the conversion is case insensitive 6411 * this allows numbers like 1AB and 1ab to represent the same value 6412 * [e.g. in hex] 6413 */ 6414 ch = (char) ((radix < 36) ? toupper (*str) : *str); 6415 for (y = 0; y < 64; y++) { 6416 if (ch == mp_s_rmap[y]) { 6417 break; 6418 } 6419 } 6420 6421 /* if the char was found in the map 6422 * and is less than the given radix add it 6423 * to the number, otherwise exit the loop. 6424 */ 6425 if (y < radix) { 6426 if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { 6427 return res; 6428 } 6429 if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { 6430 return res; 6431 } 6432 } else { 6433 break; 6434 } 6435 ++str; 6436 } 6437 6438 /* set the sign only if a != 0 */ 6439 if (mp_iszero(a) != 1) { 6440 a->sign = neg; 6441 } 6442 return MP_OKAY; 6443} 6444#endif 6445 6446/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */ 6447/* $Revision: 1.4 $ */ 6448/* $Date: 2006/03/31 14:18:44 $ */ 6449 6450/* End: bn_mp_read_radix.c */ 6451 6452/* Start: bn_mp_read_signed_bin.c */ 6453#include <tommath.h> 6454#ifdef BN_MP_READ_SIGNED_BIN_C 6455/* LibTomMath, multiple-precision integer library -- Tom St Denis 6456 * 6457 * LibTomMath is a library that provides multiple-precision 6458 * integer arithmetic as well as number theoretic functionality. 6459 * 6460 * The library was designed directly after the MPI library by 6461 * Michael Fromberger but has been written from scratch with 6462 * additional optimizations in place. 6463 * 6464 * The library is free for all purposes without any express 6465 * guarantee it works. 6466 * 6467 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6468 */ 6469 6470/* read signed bin, big endian, first byte is 0==positive or 1==negative */ 6471int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c) 6472{ 6473 int res; 6474 6475 /* read magnitude */ 6476 if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) { 6477 return res; 6478 } 6479 6480 /* first byte is 0 for positive, non-zero for negative */ 6481 if (b[0] == 0) { 6482 a->sign = MP_ZPOS; 6483 } else { 6484 a->sign = MP_NEG; 6485 } 6486 6487 return MP_OKAY; 6488} 6489#endif 6490 6491/* $Source: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */ 6492/* $Revision: 1.4 $ */ 6493/* $Date: 2006/03/31 14:18:44 $ */ 6494 6495/* End: bn_mp_read_signed_bin.c */ 6496 6497/* Start: bn_mp_read_unsigned_bin.c */ 6498#include <tommath.h> 6499#ifdef BN_MP_READ_UNSIGNED_BIN_C 6500/* LibTomMath, multiple-precision integer library -- Tom St Denis 6501 * 6502 * LibTomMath is a library that provides multiple-precision 6503 * integer arithmetic as well as number theoretic functionality. 6504 * 6505 * The library was designed directly after the MPI library by 6506 * Michael Fromberger but has been written from scratch with 6507 * additional optimizations in place. 6508 * 6509 * The library is free for all purposes without any express 6510 * guarantee it works. 6511 * 6512 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6513 */ 6514 6515/* reads a unsigned char array, assumes the msb is stored first [big endian] */ 6516int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) 6517{ 6518 int res; 6519 6520 /* make sure there are at least two digits */ 6521 if (a->alloc < 2) { 6522 if ((res = mp_grow(a, 2)) != MP_OKAY) { 6523 return res; 6524 } 6525 } 6526 6527 /* zero the int */ 6528 mp_zero (a); 6529 6530 /* read the bytes in */ 6531 while (c-- > 0) { 6532 if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { 6533 return res; 6534 } 6535 6536#ifndef MP_8BIT 6537 a->dp[0] |= *b++; 6538 a->used += 1; 6539#else 6540 a->dp[0] = (*b & MP_MASK); 6541 a->dp[1] |= ((*b++ >> 7U) & 1); 6542 a->used += 2; 6543#endif 6544 } 6545 mp_clamp (a); 6546 return MP_OKAY; 6547} 6548#endif 6549 6550/* $Source: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */ 6551/* $Revision: 1.4 $ */ 6552/* $Date: 2006/03/31 14:18:44 $ */ 6553 6554/* End: bn_mp_read_unsigned_bin.c */ 6555 6556/* Start: bn_mp_reduce.c */ 6557#include <tommath.h> 6558#ifdef BN_MP_REDUCE_C 6559/* LibTomMath, multiple-precision integer library -- Tom St Denis 6560 * 6561 * LibTomMath is a library that provides multiple-precision 6562 * integer arithmetic as well as number theoretic functionality. 6563 * 6564 * The library was designed directly after the MPI library by 6565 * Michael Fromberger but has been written from scratch with 6566 * additional optimizations in place. 6567 * 6568 * The library is free for all purposes without any express 6569 * guarantee it works. 6570 * 6571 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6572 */ 6573 6574/* reduces x mod m, assumes 0 < x < m**2, mu is 6575 * precomputed via mp_reduce_setup. 6576 * From HAC pp.604 Algorithm 14.42 6577 */ 6578int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) 6579{ 6580 mp_int q; 6581 int res, um = m->used; 6582 6583 /* q = x */ 6584 if ((res = mp_init_copy (&q, x)) != MP_OKAY) { 6585 return res; 6586 } 6587 6588 /* q1 = x / b**(k-1) */ 6589 mp_rshd (&q, um - 1); 6590 6591 /* according to HAC this optimization is ok */ 6592 if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { 6593 if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { 6594 goto CLEANUP; 6595 } 6596 } else { 6597#ifdef BN_S_MP_MUL_HIGH_DIGS_C 6598 if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { 6599 goto CLEANUP; 6600 } 6601#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) 6602 if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { 6603 goto CLEANUP; 6604 } 6605#else 6606 { 6607 res = MP_VAL; 6608 goto CLEANUP; 6609 } 6610#endif 6611 } 6612 6613 /* q3 = q2 / b**(k+1) */ 6614 mp_rshd (&q, um + 1); 6615 6616 /* x = x mod b**(k+1), quick (no division) */ 6617 if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { 6618 goto CLEANUP; 6619 } 6620 6621 /* q = q * m mod b**(k+1), quick (no division) */ 6622 if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { 6623 goto CLEANUP; 6624 } 6625 6626 /* x = x - q */ 6627 if ((res = mp_sub (x, &q, x)) != MP_OKAY) { 6628 goto CLEANUP; 6629 } 6630 6631 /* If x < 0, add b**(k+1) to it */ 6632 if (mp_cmp_d (x, 0) == MP_LT) { 6633 mp_set (&q, 1); 6634 if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) 6635 goto CLEANUP; 6636 if ((res = mp_add (x, &q, x)) != MP_OKAY) 6637 goto CLEANUP; 6638 } 6639 6640 /* Back off if it's too big */ 6641 while (mp_cmp (x, m) != MP_LT) { 6642 if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { 6643 goto CLEANUP; 6644 } 6645 } 6646 6647CLEANUP: 6648 mp_clear (&q); 6649 6650 return res; 6651} 6652#endif 6653 6654/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */ 6655/* $Revision: 1.3 $ */ 6656/* $Date: 2006/03/31 14:18:44 $ */ 6657 6658/* End: bn_mp_reduce.c */ 6659 6660/* Start: bn_mp_reduce_2k.c */ 6661#include <tommath.h> 6662#ifdef BN_MP_REDUCE_2K_C 6663/* LibTomMath, multiple-precision integer library -- Tom St Denis 6664 * 6665 * LibTomMath is a library that provides multiple-precision 6666 * integer arithmetic as well as number theoretic functionality. 6667 * 6668 * The library was designed directly after the MPI library by 6669 * Michael Fromberger but has been written from scratch with 6670 * additional optimizations in place. 6671 * 6672 * The library is free for all purposes without any express 6673 * guarantee it works. 6674 * 6675 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6676 */ 6677 6678/* reduces a modulo n where n is of the form 2**p - d */ 6679int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) 6680{ 6681 mp_int q; 6682 int p, res; 6683 6684 if ((res = mp_init(&q)) != MP_OKAY) { 6685 return res; 6686 } 6687 6688 p = mp_count_bits(n); 6689top: 6690 /* q = a/2**p, a = a mod 2**p */ 6691 if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { 6692 goto ERR; 6693 } 6694 6695 if (d != 1) { 6696 /* q = q * d */ 6697 if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 6698 goto ERR; 6699 } 6700 } 6701 6702 /* a = a + q */ 6703 if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { 6704 goto ERR; 6705 } 6706 6707 if (mp_cmp_mag(a, n) != MP_LT) { 6708 s_mp_sub(a, n, a); 6709 goto top; 6710 } 6711 6712ERR: 6713 mp_clear(&q); 6714 return res; 6715} 6716 6717#endif 6718 6719/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */ 6720/* $Revision: 1.3 $ */ 6721/* $Date: 2006/03/31 14:18:44 $ */ 6722 6723/* End: bn_mp_reduce_2k.c */ 6724 6725/* Start: bn_mp_reduce_2k_l.c */ 6726#include <tommath.h> 6727#ifdef BN_MP_REDUCE_2K_L_C 6728/* LibTomMath, multiple-precision integer library -- Tom St Denis 6729 * 6730 * LibTomMath is a library that provides multiple-precision 6731 * integer arithmetic as well as number theoretic functionality. 6732 * 6733 * The library was designed directly after the MPI library by 6734 * Michael Fromberger but has been written from scratch with 6735 * additional optimizations in place. 6736 * 6737 * The library is free for all purposes without any express 6738 * guarantee it works. 6739 * 6740 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6741 */ 6742 6743/* reduces a modulo n where n is of the form 2**p - d 6744 This differs from reduce_2k since "d" can be larger 6745 than a single digit. 6746*/ 6747int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) 6748{ 6749 mp_int q; 6750 int p, res; 6751 6752 if ((res = mp_init(&q)) != MP_OKAY) { 6753 return res; 6754 } 6755 6756 p = mp_count_bits(n); 6757top: 6758 /* q = a/2**p, a = a mod 2**p */ 6759 if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { 6760 goto ERR; 6761 } 6762 6763 /* q = q * d */ 6764 if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 6765 goto ERR; 6766 } 6767 6768 /* a = a + q */ 6769 if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { 6770 goto ERR; 6771 } 6772 6773 if (mp_cmp_mag(a, n) != MP_LT) { 6774 s_mp_sub(a, n, a); 6775 goto top; 6776 } 6777 6778ERR: 6779 mp_clear(&q); 6780 return res; 6781} 6782 6783#endif 6784 6785/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */ 6786/* $Revision: 1.3 $ */ 6787/* $Date: 2006/03/31 14:18:44 $ */ 6788 6789/* End: bn_mp_reduce_2k_l.c */ 6790 6791/* Start: bn_mp_reduce_2k_setup.c */ 6792#include <tommath.h> 6793#ifdef BN_MP_REDUCE_2K_SETUP_C 6794/* LibTomMath, multiple-precision integer library -- Tom St Denis 6795 * 6796 * LibTomMath is a library that provides multiple-precision 6797 * integer arithmetic as well as number theoretic functionality. 6798 * 6799 * The library was designed directly after the MPI library by 6800 * Michael Fromberger but has been written from scratch with 6801 * additional optimizations in place. 6802 * 6803 * The library is free for all purposes without any express 6804 * guarantee it works. 6805 * 6806 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6807 */ 6808 6809/* determines the setup value */ 6810int mp_reduce_2k_setup(mp_int *a, mp_digit *d) 6811{ 6812 int res, p; 6813 mp_int tmp; 6814 6815 if ((res = mp_init(&tmp)) != MP_OKAY) { 6816 return res; 6817 } 6818 6819 p = mp_count_bits(a); 6820 if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { 6821 mp_clear(&tmp); 6822 return res; 6823 } 6824 6825 if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { 6826 mp_clear(&tmp); 6827 return res; 6828 } 6829 6830 *d = tmp.dp[0]; 6831 mp_clear(&tmp); 6832 return MP_OKAY; 6833} 6834#endif 6835 6836/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */ 6837/* $Revision: 1.3 $ */ 6838/* $Date: 2006/03/31 14:18:44 $ */ 6839 6840/* End: bn_mp_reduce_2k_setup.c */ 6841 6842/* Start: bn_mp_reduce_2k_setup_l.c */ 6843#include <tommath.h> 6844#ifdef BN_MP_REDUCE_2K_SETUP_L_C 6845/* LibTomMath, multiple-precision integer library -- Tom St Denis 6846 * 6847 * LibTomMath is a library that provides multiple-precision 6848 * integer arithmetic as well as number theoretic functionality. 6849 * 6850 * The library was designed directly after the MPI library by 6851 * Michael Fromberger but has been written from scratch with 6852 * additional optimizations in place. 6853 * 6854 * The library is free for all purposes without any express 6855 * guarantee it works. 6856 * 6857 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6858 */ 6859 6860/* determines the setup value */ 6861int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) 6862{ 6863 int res; 6864 mp_int tmp; 6865 6866 if ((res = mp_init(&tmp)) != MP_OKAY) { 6867 return res; 6868 } 6869 6870 if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { 6871 goto ERR; 6872 } 6873 6874 if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { 6875 goto ERR; 6876 } 6877 6878ERR: 6879 mp_clear(&tmp); 6880 return res; 6881} 6882#endif 6883 6884/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */ 6885/* $Revision: 1.3 $ */ 6886/* $Date: 2006/03/31 14:18:44 $ */ 6887 6888/* End: bn_mp_reduce_2k_setup_l.c */ 6889 6890/* Start: bn_mp_reduce_is_2k.c */ 6891#include <tommath.h> 6892#ifdef BN_MP_REDUCE_IS_2K_C 6893/* LibTomMath, multiple-precision integer library -- Tom St Denis 6894 * 6895 * LibTomMath is a library that provides multiple-precision 6896 * integer arithmetic as well as number theoretic functionality. 6897 * 6898 * The library was designed directly after the MPI library by 6899 * Michael Fromberger but has been written from scratch with 6900 * additional optimizations in place. 6901 * 6902 * The library is free for all purposes without any express 6903 * guarantee it works. 6904 * 6905 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6906 */ 6907 6908/* determines if mp_reduce_2k can be used */ 6909int mp_reduce_is_2k(mp_int *a) 6910{ 6911 int ix, iy, iw; 6912 mp_digit iz; 6913 6914 if (a->used == 0) { 6915 return MP_NO; 6916 } else if (a->used == 1) { 6917 return MP_YES; 6918 } else if (a->used > 1) { 6919 iy = mp_count_bits(a); 6920 iz = 1; 6921 iw = 1; 6922 6923 /* Test every bit from the second digit up, must be 1 */ 6924 for (ix = DIGIT_BIT; ix < iy; ix++) { 6925 if ((a->dp[iw] & iz) == 0) { 6926 return MP_NO; 6927 } 6928 iz <<= 1; 6929 if (iz > (mp_digit)MP_MASK) { 6930 ++iw; 6931 iz = 1; 6932 } 6933 } 6934 } 6935 return MP_YES; 6936} 6937 6938#endif 6939 6940/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */ 6941/* $Revision: 1.3 $ */ 6942/* $Date: 2006/03/31 14:18:44 $ */ 6943 6944/* End: bn_mp_reduce_is_2k.c */ 6945 6946/* Start: bn_mp_reduce_is_2k_l.c */ 6947#include <tommath.h> 6948#ifdef BN_MP_REDUCE_IS_2K_L_C 6949/* LibTomMath, multiple-precision integer library -- Tom St Denis 6950 * 6951 * LibTomMath is a library that provides multiple-precision 6952 * integer arithmetic as well as number theoretic functionality. 6953 * 6954 * The library was designed directly after the MPI library by 6955 * Michael Fromberger but has been written from scratch with 6956 * additional optimizations in place. 6957 * 6958 * The library is free for all purposes without any express 6959 * guarantee it works. 6960 * 6961 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 6962 */ 6963 6964/* determines if reduce_2k_l can be used */ 6965int mp_reduce_is_2k_l(mp_int *a) 6966{ 6967 int ix, iy; 6968 6969 if (a->used == 0) { 6970 return MP_NO; 6971 } else if (a->used == 1) { 6972 return MP_YES; 6973 } else if (a->used > 1) { 6974 /* if more than half of the digits are -1 we're sold */ 6975 for (iy = ix = 0; ix < a->used; ix++) { 6976 if (a->dp[ix] == MP_MASK) { 6977 ++iy; 6978 } 6979 } 6980 return (iy >= (a->used/2)) ? MP_YES : MP_NO; 6981 6982 } 6983 return MP_NO; 6984} 6985 6986#endif 6987 6988/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */ 6989/* $Revision: 1.3 $ */ 6990/* $Date: 2006/03/31 14:18:44 $ */ 6991 6992/* End: bn_mp_reduce_is_2k_l.c */ 6993 6994/* Start: bn_mp_reduce_setup.c */ 6995#include <tommath.h> 6996#ifdef BN_MP_REDUCE_SETUP_C 6997/* LibTomMath, multiple-precision integer library -- Tom St Denis 6998 * 6999 * LibTomMath is a library that provides multiple-precision 7000 * integer arithmetic as well as number theoretic functionality. 7001 * 7002 * The library was designed directly after the MPI library by 7003 * Michael Fromberger but has been written from scratch with 7004 * additional optimizations in place. 7005 * 7006 * The library is free for all purposes without any express 7007 * guarantee it works. 7008 * 7009 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7010 */ 7011 7012/* pre-calculate the value required for Barrett reduction 7013 * For a given modulus "b" it calulates the value required in "a" 7014 */ 7015int mp_reduce_setup (mp_int * a, mp_int * b) 7016{ 7017 int res; 7018 7019 if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { 7020 return res; 7021 } 7022 return mp_div (a, b, a, NULL); 7023} 7024#endif 7025 7026/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */ 7027/* $Revision: 1.3 $ */ 7028/* $Date: 2006/03/31 14:18:44 $ */ 7029 7030/* End: bn_mp_reduce_setup.c */ 7031 7032/* Start: bn_mp_rshd.c */ 7033#include <tommath.h> 7034#ifdef BN_MP_RSHD_C 7035/* LibTomMath, multiple-precision integer library -- Tom St Denis 7036 * 7037 * LibTomMath is a library that provides multiple-precision 7038 * integer arithmetic as well as number theoretic functionality. 7039 * 7040 * The library was designed directly after the MPI library by 7041 * Michael Fromberger but has been written from scratch with 7042 * additional optimizations in place. 7043 * 7044 * The library is free for all purposes without any express 7045 * guarantee it works. 7046 * 7047 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7048 */ 7049 7050/* shift right a certain amount of digits */ 7051void mp_rshd (mp_int * a, int b) 7052{ 7053 int x; 7054 7055 /* if b <= 0 then ignore it */ 7056 if (b <= 0) { 7057 return; 7058 } 7059 7060 /* if b > used then simply zero it and return */ 7061 if (a->used <= b) { 7062 mp_zero (a); 7063 return; 7064 } 7065 7066 { 7067 register mp_digit *bottom, *top; 7068 7069 /* shift the digits down */ 7070 7071 /* bottom */ 7072 bottom = a->dp; 7073 7074 /* top [offset into digits] */ 7075 top = a->dp + b; 7076 7077 /* this is implemented as a sliding window where 7078 * the window is b-digits long and digits from 7079 * the top of the window are copied to the bottom 7080 * 7081 * e.g. 7082 7083 b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> 7084 /\ | ----> 7085 \-------------------/ ----> 7086 */ 7087 for (x = 0; x < (a->used - b); x++) { 7088 *bottom++ = *top++; 7089 } 7090 7091 /* zero the top digits */ 7092 for (; x < a->used; x++) { 7093 *bottom++ = 0; 7094 } 7095 } 7096 7097 /* remove excess digits */ 7098 a->used -= b; 7099} 7100#endif 7101 7102/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */ 7103/* $Revision: 1.3 $ */ 7104/* $Date: 2006/03/31 14:18:44 $ */ 7105 7106/* End: bn_mp_rshd.c */ 7107 7108/* Start: bn_mp_set.c */ 7109#include <tommath.h> 7110#ifdef BN_MP_SET_C 7111/* LibTomMath, multiple-precision integer library -- Tom St Denis 7112 * 7113 * LibTomMath is a library that provides multiple-precision 7114 * integer arithmetic as well as number theoretic functionality. 7115 * 7116 * The library was designed directly after the MPI library by 7117 * Michael Fromberger but has been written from scratch with 7118 * additional optimizations in place. 7119 * 7120 * The library is free for all purposes without any express 7121 * guarantee it works. 7122 * 7123 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7124 */ 7125 7126/* set to a digit */ 7127void mp_set (mp_int * a, mp_digit b) 7128{ 7129 mp_zero (a); 7130 a->dp[0] = b & MP_MASK; 7131 a->used = (a->dp[0] != 0) ? 1 : 0; 7132} 7133#endif 7134 7135/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */ 7136/* $Revision: 1.3 $ */ 7137/* $Date: 2006/03/31 14:18:44 $ */ 7138 7139/* End: bn_mp_set.c */ 7140 7141/* Start: bn_mp_set_int.c */ 7142#include <tommath.h> 7143#ifdef BN_MP_SET_INT_C 7144/* LibTomMath, multiple-precision integer library -- Tom St Denis 7145 * 7146 * LibTomMath is a library that provides multiple-precision 7147 * integer arithmetic as well as number theoretic functionality. 7148 * 7149 * The library was designed directly after the MPI library by 7150 * Michael Fromberger but has been written from scratch with 7151 * additional optimizations in place. 7152 * 7153 * The library is free for all purposes without any express 7154 * guarantee it works. 7155 * 7156 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7157 */ 7158 7159/* set a 32-bit const */ 7160int mp_set_int (mp_int * a, unsigned long b) 7161{ 7162 int x, res; 7163 7164 mp_zero (a); 7165 7166 /* set four bits at a time */ 7167 for (x = 0; x < 8; x++) { 7168 /* shift the number up four bits */ 7169 if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { 7170 return res; 7171 } 7172 7173 /* OR in the top four bits of the source */ 7174 a->dp[0] |= (b >> 28) & 15; 7175 7176 /* shift the source up to the next four bits */ 7177 b <<= 4; 7178 7179 /* ensure that digits are not clamped off */ 7180 a->used += 1; 7181 } 7182 mp_clamp (a); 7183 return MP_OKAY; 7184} 7185#endif 7186 7187/* $Source: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */ 7188/* $Revision: 1.3 $ */ 7189/* $Date: 2006/03/31 14:18:44 $ */ 7190 7191/* End: bn_mp_set_int.c */ 7192 7193/* Start: bn_mp_shrink.c */ 7194#include <tommath.h> 7195#ifdef BN_MP_SHRINK_C 7196/* LibTomMath, multiple-precision integer library -- Tom St Denis 7197 * 7198 * LibTomMath is a library that provides multiple-precision 7199 * integer arithmetic as well as number theoretic functionality. 7200 * 7201 * The library was designed directly after the MPI library by 7202 * Michael Fromberger but has been written from scratch with 7203 * additional optimizations in place. 7204 * 7205 * The library is free for all purposes without any express 7206 * guarantee it works. 7207 * 7208 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7209 */ 7210 7211/* shrink a bignum */ 7212int mp_shrink (mp_int * a) 7213{ 7214 mp_digit *tmp; 7215 if (a->alloc != a->used && a->used > 0) { 7216 if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { 7217 return MP_MEM; 7218 } 7219 a->dp = tmp; 7220 a->alloc = a->used; 7221 } 7222 return MP_OKAY; 7223} 7224#endif 7225 7226/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */ 7227/* $Revision: 1.3 $ */ 7228/* $Date: 2006/03/31 14:18:44 $ */ 7229 7230/* End: bn_mp_shrink.c */ 7231 7232/* Start: bn_mp_signed_bin_size.c */ 7233#include <tommath.h> 7234#ifdef BN_MP_SIGNED_BIN_SIZE_C 7235/* LibTomMath, multiple-precision integer library -- Tom St Denis 7236 * 7237 * LibTomMath is a library that provides multiple-precision 7238 * integer arithmetic as well as number theoretic functionality. 7239 * 7240 * The library was designed directly after the MPI library by 7241 * Michael Fromberger but has been written from scratch with 7242 * additional optimizations in place. 7243 * 7244 * The library is free for all purposes without any express 7245 * guarantee it works. 7246 * 7247 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7248 */ 7249 7250/* get the size for an signed equivalent */ 7251int mp_signed_bin_size (mp_int * a) 7252{ 7253 return 1 + mp_unsigned_bin_size (a); 7254} 7255#endif 7256 7257/* $Source: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */ 7258/* $Revision: 1.3 $ */ 7259/* $Date: 2006/03/31 14:18:44 $ */ 7260 7261/* End: bn_mp_signed_bin_size.c */ 7262 7263/* Start: bn_mp_sqr.c */ 7264#include <tommath.h> 7265#ifdef BN_MP_SQR_C 7266/* LibTomMath, multiple-precision integer library -- Tom St Denis 7267 * 7268 * LibTomMath is a library that provides multiple-precision 7269 * integer arithmetic as well as number theoretic functionality. 7270 * 7271 * The library was designed directly after the MPI library by 7272 * Michael Fromberger but has been written from scratch with 7273 * additional optimizations in place. 7274 * 7275 * The library is free for all purposes without any express 7276 * guarantee it works. 7277 * 7278 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7279 */ 7280 7281/* computes b = a*a */ 7282int 7283mp_sqr (mp_int * a, mp_int * b) 7284{ 7285 int res; 7286 7287#ifdef BN_MP_TOOM_SQR_C 7288 /* use Toom-Cook? */ 7289 if (a->used >= TOOM_SQR_CUTOFF) { 7290 res = mp_toom_sqr(a, b); 7291 /* Karatsuba? */ 7292 } else 7293#endif 7294#ifdef BN_MP_KARATSUBA_SQR_C 7295if (a->used >= KARATSUBA_SQR_CUTOFF) { 7296 res = mp_karatsuba_sqr (a, b); 7297 } else 7298#endif 7299 { 7300#ifdef BN_FAST_S_MP_SQR_C 7301 /* can we use the fast comba multiplier? */ 7302 if ((a->used * 2 + 1) < MP_WARRAY && 7303 a->used < 7304 (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { 7305 res = fast_s_mp_sqr (a, b); 7306 } else 7307#endif 7308#ifdef BN_S_MP_SQR_C 7309 res = s_mp_sqr (a, b); 7310#else 7311 res = MP_VAL; 7312#endif 7313 } 7314 b->sign = MP_ZPOS; 7315 return res; 7316} 7317#endif 7318 7319/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */ 7320/* $Revision: 1.3 $ */ 7321/* $Date: 2006/03/31 14:18:44 $ */ 7322 7323/* End: bn_mp_sqr.c */ 7324 7325/* Start: bn_mp_sqrmod.c */ 7326#include <tommath.h> 7327#ifdef BN_MP_SQRMOD_C 7328/* LibTomMath, multiple-precision integer library -- Tom St Denis 7329 * 7330 * LibTomMath is a library that provides multiple-precision 7331 * integer arithmetic as well as number theoretic functionality. 7332 * 7333 * The library was designed directly after the MPI library by 7334 * Michael Fromberger but has been written from scratch with 7335 * additional optimizations in place. 7336 * 7337 * The library is free for all purposes without any express 7338 * guarantee it works. 7339 * 7340 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7341 */ 7342 7343/* c = a * a (mod b) */ 7344int 7345mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) 7346{ 7347 int res; 7348 mp_int t; 7349 7350 if ((res = mp_init (&t)) != MP_OKAY) { 7351 return res; 7352 } 7353 7354 if ((res = mp_sqr (a, &t)) != MP_OKAY) { 7355 mp_clear (&t); 7356 return res; 7357 } 7358 res = mp_mod (&t, b, c); 7359 mp_clear (&t); 7360 return res; 7361} 7362#endif 7363 7364/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */ 7365/* $Revision: 1.3 $ */ 7366/* $Date: 2006/03/31 14:18:44 $ */ 7367 7368/* End: bn_mp_sqrmod.c */ 7369 7370/* Start: bn_mp_sqrt.c */ 7371#include <tommath.h> 7372#ifdef BN_MP_SQRT_C 7373/* LibTomMath, multiple-precision integer library -- Tom St Denis 7374 * 7375 * LibTomMath is a library that provides multiple-precision 7376 * integer arithmetic as well as number theoretic functionality. 7377 * 7378 * The library was designed directly after the MPI library by 7379 * Michael Fromberger but has been written from scratch with 7380 * additional optimizations in place. 7381 * 7382 * The library is free for all purposes without any express 7383 * guarantee it works. 7384 * 7385 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7386 */ 7387 7388/* this function is less generic than mp_n_root, simpler and faster */ 7389int mp_sqrt(mp_int *arg, mp_int *ret) 7390{ 7391 int res; 7392 mp_int t1,t2; 7393 7394 /* must be positive */ 7395 if (arg->sign == MP_NEG) { 7396 return MP_VAL; 7397 } 7398 7399 /* easy out */ 7400 if (mp_iszero(arg) == MP_YES) { 7401 mp_zero(ret); 7402 return MP_OKAY; 7403 } 7404 7405 if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { 7406 return res; 7407 } 7408 7409 if ((res = mp_init(&t2)) != MP_OKAY) { 7410 goto E2; 7411 } 7412 7413 /* First approx. (not very bad for large arg) */ 7414 mp_rshd (&t1,t1.used/2); 7415 7416 /* t1 > 0 */ 7417 if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { 7418 goto E1; 7419 } 7420 if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { 7421 goto E1; 7422 } 7423 if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { 7424 goto E1; 7425 } 7426 /* And now t1 > sqrt(arg) */ 7427 do { 7428 if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { 7429 goto E1; 7430 } 7431 if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { 7432 goto E1; 7433 } 7434 if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { 7435 goto E1; 7436 } 7437 /* t1 >= sqrt(arg) >= t2 at this point */ 7438 } while (mp_cmp_mag(&t1,&t2) == MP_GT); 7439 7440 mp_exch(&t1,ret); 7441 7442E1: mp_clear(&t2); 7443E2: mp_clear(&t1); 7444 return res; 7445} 7446 7447#endif 7448 7449/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */ 7450/* $Revision: 1.3 $ */ 7451/* $Date: 2006/03/31 14:18:44 $ */ 7452 7453/* End: bn_mp_sqrt.c */ 7454 7455/* Start: bn_mp_sub.c */ 7456#include <tommath.h> 7457#ifdef BN_MP_SUB_C 7458/* LibTomMath, multiple-precision integer library -- Tom St Denis 7459 * 7460 * LibTomMath is a library that provides multiple-precision 7461 * integer arithmetic as well as number theoretic functionality. 7462 * 7463 * The library was designed directly after the MPI library by 7464 * Michael Fromberger but has been written from scratch with 7465 * additional optimizations in place. 7466 * 7467 * The library is free for all purposes without any express 7468 * guarantee it works. 7469 * 7470 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7471 */ 7472 7473/* high level subtraction (handles signs) */ 7474int 7475mp_sub (mp_int * a, mp_int * b, mp_int * c) 7476{ 7477 int sa, sb, res; 7478 7479 sa = a->sign; 7480 sb = b->sign; 7481 7482 if (sa != sb) { 7483 /* subtract a negative from a positive, OR */ 7484 /* subtract a positive from a negative. */ 7485 /* In either case, ADD their magnitudes, */ 7486 /* and use the sign of the first number. */ 7487 c->sign = sa; 7488 res = s_mp_add (a, b, c); 7489 } else { 7490 /* subtract a positive from a positive, OR */ 7491 /* subtract a negative from a negative. */ 7492 /* First, take the difference between their */ 7493 /* magnitudes, then... */ 7494 if (mp_cmp_mag (a, b) != MP_LT) { 7495 /* Copy the sign from the first */ 7496 c->sign = sa; 7497 /* The first has a larger or equal magnitude */ 7498 res = s_mp_sub (a, b, c); 7499 } else { 7500 /* The result has the *opposite* sign from */ 7501 /* the first number. */ 7502 c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; 7503 /* The second has a larger magnitude */ 7504 res = s_mp_sub (b, a, c); 7505 } 7506 } 7507 return res; 7508} 7509 7510#endif 7511 7512/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */ 7513/* $Revision: 1.3 $ */ 7514/* $Date: 2006/03/31 14:18:44 $ */ 7515 7516/* End: bn_mp_sub.c */ 7517 7518/* Start: bn_mp_sub_d.c */ 7519#include <tommath.h> 7520#ifdef BN_MP_SUB_D_C 7521/* LibTomMath, multiple-precision integer library -- Tom St Denis 7522 * 7523 * LibTomMath is a library that provides multiple-precision 7524 * integer arithmetic as well as number theoretic functionality. 7525 * 7526 * The library was designed directly after the MPI library by 7527 * Michael Fromberger but has been written from scratch with 7528 * additional optimizations in place. 7529 * 7530 * The library is free for all purposes without any express 7531 * guarantee it works. 7532 * 7533 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7534 */ 7535 7536/* single digit subtraction */ 7537int 7538mp_sub_d (mp_int * a, mp_digit b, mp_int * c) 7539{ 7540 mp_digit *tmpa, *tmpc, mu; 7541 int res, ix, oldused; 7542 7543 /* grow c as required */ 7544 if (c->alloc < a->used + 1) { 7545 if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { 7546 return res; 7547 } 7548 } 7549 7550 /* if a is negative just do an unsigned 7551 * addition [with fudged signs] 7552 */ 7553 if (a->sign == MP_NEG) { 7554 a->sign = MP_ZPOS; 7555 res = mp_add_d(a, b, c); 7556 a->sign = c->sign = MP_NEG; 7557 7558 /* clamp */ 7559 mp_clamp(c); 7560 7561 return res; 7562 } 7563 7564 /* setup regs */ 7565 oldused = c->used; 7566 tmpa = a->dp; 7567 tmpc = c->dp; 7568 7569 /* if a <= b simply fix the single digit */ 7570 if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { 7571 if (a->used == 1) { 7572 *tmpc++ = b - *tmpa; 7573 } else { 7574 *tmpc++ = b; 7575 } 7576 ix = 1; 7577 7578 /* negative/1digit */ 7579 c->sign = MP_NEG; 7580 c->used = 1; 7581 } else { 7582 /* positive/size */ 7583 c->sign = MP_ZPOS; 7584 c->used = a->used; 7585 7586 /* subtract first digit */ 7587 *tmpc = *tmpa++ - b; 7588 mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); 7589 *tmpc++ &= MP_MASK; 7590 7591 /* handle rest of the digits */ 7592 for (ix = 1; ix < a->used; ix++) { 7593 *tmpc = *tmpa++ - mu; 7594 mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); 7595 *tmpc++ &= MP_MASK; 7596 } 7597 } 7598 7599 /* zero excess digits */ 7600 while (ix++ < oldused) { 7601 *tmpc++ = 0; 7602 } 7603 mp_clamp(c); 7604 return MP_OKAY; 7605} 7606 7607#endif 7608 7609/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */ 7610/* $Revision: 1.5 $ */ 7611/* $Date: 2006/03/31 14:18:44 $ */ 7612 7613/* End: bn_mp_sub_d.c */ 7614 7615/* Start: bn_mp_submod.c */ 7616#include <tommath.h> 7617#ifdef BN_MP_SUBMOD_C 7618/* LibTomMath, multiple-precision integer library -- Tom St Denis 7619 * 7620 * LibTomMath is a library that provides multiple-precision 7621 * integer arithmetic as well as number theoretic functionality. 7622 * 7623 * The library was designed directly after the MPI library by 7624 * Michael Fromberger but has been written from scratch with 7625 * additional optimizations in place. 7626 * 7627 * The library is free for all purposes without any express 7628 * guarantee it works. 7629 * 7630 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7631 */ 7632 7633/* d = a - b (mod c) */ 7634int 7635mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) 7636{ 7637 int res; 7638 mp_int t; 7639 7640 7641 if ((res = mp_init (&t)) != MP_OKAY) { 7642 return res; 7643 } 7644 7645 if ((res = mp_sub (a, b, &t)) != MP_OKAY) { 7646 mp_clear (&t); 7647 return res; 7648 } 7649 res = mp_mod (&t, c, d); 7650 mp_clear (&t); 7651 return res; 7652} 7653#endif 7654 7655/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */ 7656/* $Revision: 1.3 $ */ 7657/* $Date: 2006/03/31 14:18:44 $ */ 7658 7659/* End: bn_mp_submod.c */ 7660 7661/* Start: bn_mp_to_signed_bin.c */ 7662#include <tommath.h> 7663#ifdef BN_MP_TO_SIGNED_BIN_C 7664/* LibTomMath, multiple-precision integer library -- Tom St Denis 7665 * 7666 * LibTomMath is a library that provides multiple-precision 7667 * integer arithmetic as well as number theoretic functionality. 7668 * 7669 * The library was designed directly after the MPI library by 7670 * Michael Fromberger but has been written from scratch with 7671 * additional optimizations in place. 7672 * 7673 * The library is free for all purposes without any express 7674 * guarantee it works. 7675 * 7676 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7677 */ 7678 7679/* store in signed [big endian] format */ 7680int mp_to_signed_bin (mp_int * a, unsigned char *b) 7681{ 7682 int res; 7683 7684 if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) { 7685 return res; 7686 } 7687 b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1); 7688 return MP_OKAY; 7689} 7690#endif 7691 7692/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */ 7693/* $Revision: 1.3 $ */ 7694/* $Date: 2006/03/31 14:18:44 $ */ 7695 7696/* End: bn_mp_to_signed_bin.c */ 7697 7698/* Start: bn_mp_to_signed_bin_n.c */ 7699#include <tommath.h> 7700#ifdef BN_MP_TO_SIGNED_BIN_N_C 7701/* LibTomMath, multiple-precision integer library -- Tom St Denis 7702 * 7703 * LibTomMath is a library that provides multiple-precision 7704 * integer arithmetic as well as number theoretic functionality. 7705 * 7706 * The library was designed directly after the MPI library by 7707 * Michael Fromberger but has been written from scratch with 7708 * additional optimizations in place. 7709 * 7710 * The library is free for all purposes without any express 7711 * guarantee it works. 7712 * 7713 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7714 */ 7715 7716/* store in signed [big endian] format */ 7717int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) 7718{ 7719 if (*outlen < (unsigned long)mp_signed_bin_size(a)) { 7720 return MP_VAL; 7721 } 7722 *outlen = mp_signed_bin_size(a); 7723 return mp_to_signed_bin(a, b); 7724} 7725#endif 7726 7727/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */ 7728/* $Revision: 1.3 $ */ 7729/* $Date: 2006/03/31 14:18:44 $ */ 7730 7731/* End: bn_mp_to_signed_bin_n.c */ 7732 7733/* Start: bn_mp_to_unsigned_bin.c */ 7734#include <tommath.h> 7735#ifdef BN_MP_TO_UNSIGNED_BIN_C 7736/* LibTomMath, multiple-precision integer library -- Tom St Denis 7737 * 7738 * LibTomMath is a library that provides multiple-precision 7739 * integer arithmetic as well as number theoretic functionality. 7740 * 7741 * The library was designed directly after the MPI library by 7742 * Michael Fromberger but has been written from scratch with 7743 * additional optimizations in place. 7744 * 7745 * The library is free for all purposes without any express 7746 * guarantee it works. 7747 * 7748 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7749 */ 7750 7751/* store in unsigned [big endian] format */ 7752int mp_to_unsigned_bin (mp_int * a, unsigned char *b) 7753{ 7754 int x, res; 7755 mp_int t; 7756 7757 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 7758 return res; 7759 } 7760 7761 x = 0; 7762 while (mp_iszero (&t) == 0) { 7763#ifndef MP_8BIT 7764 b[x++] = (unsigned char) (t.dp[0] & 255); 7765#else 7766 b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); 7767#endif 7768 if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { 7769 mp_clear (&t); 7770 return res; 7771 } 7772 } 7773 bn_reverse (b, x); 7774 mp_clear (&t); 7775 return MP_OKAY; 7776} 7777#endif 7778 7779/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */ 7780/* $Revision: 1.3 $ */ 7781/* $Date: 2006/03/31 14:18:44 $ */ 7782 7783/* End: bn_mp_to_unsigned_bin.c */ 7784 7785/* Start: bn_mp_to_unsigned_bin_n.c */ 7786#include <tommath.h> 7787#ifdef BN_MP_TO_UNSIGNED_BIN_N_C 7788/* LibTomMath, multiple-precision integer library -- Tom St Denis 7789 * 7790 * LibTomMath is a library that provides multiple-precision 7791 * integer arithmetic as well as number theoretic functionality. 7792 * 7793 * The library was designed directly after the MPI library by 7794 * Michael Fromberger but has been written from scratch with 7795 * additional optimizations in place. 7796 * 7797 * The library is free for all purposes without any express 7798 * guarantee it works. 7799 * 7800 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7801 */ 7802 7803/* store in unsigned [big endian] format */ 7804int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) 7805{ 7806 if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) { 7807 return MP_VAL; 7808 } 7809 *outlen = mp_unsigned_bin_size(a); 7810 return mp_to_unsigned_bin(a, b); 7811} 7812#endif 7813 7814/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */ 7815/* $Revision: 1.3 $ */ 7816/* $Date: 2006/03/31 14:18:44 $ */ 7817 7818/* End: bn_mp_to_unsigned_bin_n.c */ 7819 7820/* Start: bn_mp_toom_mul.c */ 7821#include <tommath.h> 7822#ifdef BN_MP_TOOM_MUL_C 7823/* LibTomMath, multiple-precision integer library -- Tom St Denis 7824 * 7825 * LibTomMath is a library that provides multiple-precision 7826 * integer arithmetic as well as number theoretic functionality. 7827 * 7828 * The library was designed directly after the MPI library by 7829 * Michael Fromberger but has been written from scratch with 7830 * additional optimizations in place. 7831 * 7832 * The library is free for all purposes without any express 7833 * guarantee it works. 7834 * 7835 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 7836 */ 7837 7838/* multiplication using the Toom-Cook 3-way algorithm 7839 * 7840 * Much more complicated than Karatsuba but has a lower 7841 * asymptotic running time of O(N**1.464). This algorithm is 7842 * only particularly useful on VERY large inputs 7843 * (we're talking 1000s of digits here...). 7844*/ 7845int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) 7846{ 7847 mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; 7848 int res, B; 7849 7850 /* init temps */ 7851 if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 7852 &a0, &a1, &a2, &b0, &b1, 7853 &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { 7854 return res; 7855 } 7856 7857 /* B */ 7858 B = MIN(a->used, b->used) / 3; 7859 7860 /* a = a2 * B**2 + a1 * B + a0 */ 7861 if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { 7862 goto ERR; 7863 } 7864 7865 if ((res = mp_copy(a, &a1)) != MP_OKAY) { 7866 goto ERR; 7867 } 7868 mp_rshd(&a1, B); 7869 mp_mod_2d(&a1, DIGIT_BIT * B, &a1); 7870 7871 if ((res = mp_copy(a, &a2)) != MP_OKAY) { 7872 goto ERR; 7873 } 7874 mp_rshd(&a2, B*2); 7875 7876 /* b = b2 * B**2 + b1 * B + b0 */ 7877 if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { 7878 goto ERR; 7879 } 7880 7881 if ((res = mp_copy(b, &b1)) != MP_OKAY) { 7882 goto ERR; 7883 } 7884 mp_rshd(&b1, B); 7885 mp_mod_2d(&b1, DIGIT_BIT * B, &b1); 7886 7887 if ((res = mp_copy(b, &b2)) != MP_OKAY) { 7888 goto ERR; 7889 } 7890 mp_rshd(&b2, B*2); 7891 7892 /* w0 = a0*b0 */ 7893 if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { 7894 goto ERR; 7895 } 7896 7897 /* w4 = a2 * b2 */ 7898 if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { 7899 goto ERR; 7900 } 7901 7902 /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ 7903 if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { 7904 goto ERR; 7905 } 7906 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { 7907 goto ERR; 7908 } 7909 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { 7910 goto ERR; 7911 } 7912 if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { 7913 goto ERR; 7914 } 7915 7916 if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { 7917 goto ERR; 7918 } 7919 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { 7920 goto ERR; 7921 } 7922 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { 7923 goto ERR; 7924 } 7925 if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { 7926 goto ERR; 7927 } 7928 7929 if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { 7930 goto ERR; 7931 } 7932 7933 /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ 7934 if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { 7935 goto ERR; 7936 } 7937 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { 7938 goto ERR; 7939 } 7940 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { 7941 goto ERR; 7942 } 7943 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { 7944 goto ERR; 7945 } 7946 7947 if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { 7948 goto ERR; 7949 } 7950 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { 7951 goto ERR; 7952 } 7953 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { 7954 goto ERR; 7955 } 7956 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { 7957 goto ERR; 7958 } 7959 7960 if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { 7961 goto ERR; 7962 } 7963 7964 7965 /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ 7966 if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { 7967 goto ERR; 7968 } 7969 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { 7970 goto ERR; 7971 } 7972 if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { 7973 goto ERR; 7974 } 7975 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { 7976 goto ERR; 7977 } 7978 if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { 7979 goto ERR; 7980 } 7981 7982 /* now solve the matrix 7983 7984 0 0 0 0 1 7985 1 2 4 8 16 7986 1 1 1 1 1 7987 16 8 4 2 1 7988 1 0 0 0 0 7989 7990 using 12 subtractions, 4 shifts, 7991 2 small divisions and 1 small multiplication 7992 */ 7993 7994 /* r1 - r4 */ 7995 if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { 7996 goto ERR; 7997 } 7998 /* r3 - r0 */ 7999 if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { 8000 goto ERR; 8001 } 8002 /* r1/2 */ 8003 if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { 8004 goto ERR; 8005 } 8006 /* r3/2 */ 8007 if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { 8008 goto ERR; 8009 } 8010 /* r2 - r0 - r4 */ 8011 if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { 8012 goto ERR; 8013 } 8014 if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { 8015 goto ERR; 8016 } 8017 /* r1 - r2 */ 8018 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { 8019 goto ERR; 8020 } 8021 /* r3 - r2 */ 8022 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { 8023 goto ERR; 8024 } 8025 /* r1 - 8r0 */ 8026 if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { 8027 goto ERR; 8028 } 8029 if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { 8030 goto ERR; 8031 } 8032 /* r3 - 8r4 */ 8033 if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { 8034 goto ERR; 8035 } 8036 if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { 8037 goto ERR; 8038 } 8039 /* 3r2 - r1 - r3 */ 8040 if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { 8041 goto ERR; 8042 } 8043 if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { 8044 goto ERR; 8045 } 8046 if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { 8047 goto ERR; 8048 } 8049 /* r1 - r2 */ 8050 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { 8051 goto ERR; 8052 } 8053 /* r3 - r2 */ 8054 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { 8055 goto ERR; 8056 } 8057 /* r1/3 */ 8058 if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { 8059 goto ERR; 8060 } 8061 /* r3/3 */ 8062 if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { 8063 goto ERR; 8064 } 8065 8066 /* at this point shift W[n] by B*n */ 8067 if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { 8068 goto ERR; 8069 } 8070 if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { 8071 goto ERR; 8072 } 8073 if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { 8074 goto ERR; 8075 } 8076 if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { 8077 goto ERR; 8078 } 8079 8080 if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { 8081 goto ERR; 8082 } 8083 if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { 8084 goto ERR; 8085 } 8086 if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { 8087 goto ERR; 8088 } 8089 if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { 8090 goto ERR; 8091 } 8092 8093ERR: 8094 mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 8095 &a0, &a1, &a2, &b0, &b1, 8096 &b2, &tmp1, &tmp2, NULL); 8097 return res; 8098} 8099 8100#endif 8101 8102/* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */ 8103/* $Revision: 1.3 $ */ 8104/* $Date: 2006/03/31 14:18:44 $ */ 8105 8106/* End: bn_mp_toom_mul.c */ 8107 8108/* Start: bn_mp_toom_sqr.c */ 8109#include <tommath.h> 8110#ifdef BN_MP_TOOM_SQR_C 8111/* LibTomMath, multiple-precision integer library -- Tom St Denis 8112 * 8113 * LibTomMath is a library that provides multiple-precision 8114 * integer arithmetic as well as number theoretic functionality. 8115 * 8116 * The library was designed directly after the MPI library by 8117 * Michael Fromberger but has been written from scratch with 8118 * additional optimizations in place. 8119 * 8120 * The library is free for all purposes without any express 8121 * guarantee it works. 8122 * 8123 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8124 */ 8125 8126/* squaring using Toom-Cook 3-way algorithm */ 8127int 8128mp_toom_sqr(mp_int *a, mp_int *b) 8129{ 8130 mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; 8131 int res, B; 8132 8133 /* init temps */ 8134 if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { 8135 return res; 8136 } 8137 8138 /* B */ 8139 B = a->used / 3; 8140 8141 /* a = a2 * B**2 + a1 * B + a0 */ 8142 if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { 8143 goto ERR; 8144 } 8145 8146 if ((res = mp_copy(a, &a1)) != MP_OKAY) { 8147 goto ERR; 8148 } 8149 mp_rshd(&a1, B); 8150 mp_mod_2d(&a1, DIGIT_BIT * B, &a1); 8151 8152 if ((res = mp_copy(a, &a2)) != MP_OKAY) { 8153 goto ERR; 8154 } 8155 mp_rshd(&a2, B*2); 8156 8157 /* w0 = a0*a0 */ 8158 if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { 8159 goto ERR; 8160 } 8161 8162 /* w4 = a2 * a2 */ 8163 if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { 8164 goto ERR; 8165 } 8166 8167 /* w1 = (a2 + 2(a1 + 2a0))**2 */ 8168 if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { 8169 goto ERR; 8170 } 8171 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { 8172 goto ERR; 8173 } 8174 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { 8175 goto ERR; 8176 } 8177 if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { 8178 goto ERR; 8179 } 8180 8181 if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { 8182 goto ERR; 8183 } 8184 8185 /* w3 = (a0 + 2(a1 + 2a2))**2 */ 8186 if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { 8187 goto ERR; 8188 } 8189 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { 8190 goto ERR; 8191 } 8192 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { 8193 goto ERR; 8194 } 8195 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { 8196 goto ERR; 8197 } 8198 8199 if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { 8200 goto ERR; 8201 } 8202 8203 8204 /* w2 = (a2 + a1 + a0)**2 */ 8205 if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { 8206 goto ERR; 8207 } 8208 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { 8209 goto ERR; 8210 } 8211 if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { 8212 goto ERR; 8213 } 8214 8215 /* now solve the matrix 8216 8217 0 0 0 0 1 8218 1 2 4 8 16 8219 1 1 1 1 1 8220 16 8 4 2 1 8221 1 0 0 0 0 8222 8223 using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. 8224 */ 8225 8226 /* r1 - r4 */ 8227 if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { 8228 goto ERR; 8229 } 8230 /* r3 - r0 */ 8231 if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { 8232 goto ERR; 8233 } 8234 /* r1/2 */ 8235 if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { 8236 goto ERR; 8237 } 8238 /* r3/2 */ 8239 if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { 8240 goto ERR; 8241 } 8242 /* r2 - r0 - r4 */ 8243 if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { 8244 goto ERR; 8245 } 8246 if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { 8247 goto ERR; 8248 } 8249 /* r1 - r2 */ 8250 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { 8251 goto ERR; 8252 } 8253 /* r3 - r2 */ 8254 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { 8255 goto ERR; 8256 } 8257 /* r1 - 8r0 */ 8258 if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { 8259 goto ERR; 8260 } 8261 if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { 8262 goto ERR; 8263 } 8264 /* r3 - 8r4 */ 8265 if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { 8266 goto ERR; 8267 } 8268 if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { 8269 goto ERR; 8270 } 8271 /* 3r2 - r1 - r3 */ 8272 if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { 8273 goto ERR; 8274 } 8275 if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { 8276 goto ERR; 8277 } 8278 if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { 8279 goto ERR; 8280 } 8281 /* r1 - r2 */ 8282 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { 8283 goto ERR; 8284 } 8285 /* r3 - r2 */ 8286 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { 8287 goto ERR; 8288 } 8289 /* r1/3 */ 8290 if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { 8291 goto ERR; 8292 } 8293 /* r3/3 */ 8294 if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { 8295 goto ERR; 8296 } 8297 8298 /* at this point shift W[n] by B*n */ 8299 if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { 8300 goto ERR; 8301 } 8302 if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { 8303 goto ERR; 8304 } 8305 if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { 8306 goto ERR; 8307 } 8308 if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { 8309 goto ERR; 8310 } 8311 8312 if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { 8313 goto ERR; 8314 } 8315 if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { 8316 goto ERR; 8317 } 8318 if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { 8319 goto ERR; 8320 } 8321 if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { 8322 goto ERR; 8323 } 8324 8325ERR: 8326 mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); 8327 return res; 8328} 8329 8330#endif 8331 8332/* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */ 8333/* $Revision: 1.3 $ */ 8334/* $Date: 2006/03/31 14:18:44 $ */ 8335 8336/* End: bn_mp_toom_sqr.c */ 8337 8338/* Start: bn_mp_toradix.c */ 8339#include <tommath.h> 8340#ifdef BN_MP_TORADIX_C 8341/* LibTomMath, multiple-precision integer library -- Tom St Denis 8342 * 8343 * LibTomMath is a library that provides multiple-precision 8344 * integer arithmetic as well as number theoretic functionality. 8345 * 8346 * The library was designed directly after the MPI library by 8347 * Michael Fromberger but has been written from scratch with 8348 * additional optimizations in place. 8349 * 8350 * The library is free for all purposes without any express 8351 * guarantee it works. 8352 * 8353 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8354 */ 8355 8356/* stores a bignum as a ASCII string in a given radix (2..64) */ 8357int mp_toradix (mp_int * a, char *str, int radix) 8358{ 8359 int res, digs; 8360 mp_int t; 8361 mp_digit d; 8362 char *_s = str; 8363 8364 /* check range of the radix */ 8365 if (radix < 2 || radix > 64) { 8366 return MP_VAL; 8367 } 8368 8369 /* quick out if its zero */ 8370 if (mp_iszero(a) == 1) { 8371 *str++ = '0'; 8372 *str = '\0'; 8373 return MP_OKAY; 8374 } 8375 8376 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 8377 return res; 8378 } 8379 8380 /* if it is negative output a - */ 8381 if (t.sign == MP_NEG) { 8382 ++_s; 8383 *str++ = '-'; 8384 t.sign = MP_ZPOS; 8385 } 8386 8387 digs = 0; 8388 while (mp_iszero (&t) == 0) { 8389 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { 8390 mp_clear (&t); 8391 return res; 8392 } 8393 *str++ = mp_s_rmap[d]; 8394 ++digs; 8395 } 8396 8397 /* reverse the digits of the string. In this case _s points 8398 * to the first digit [exluding the sign] of the number] 8399 */ 8400 bn_reverse ((unsigned char *)_s, digs); 8401 8402 /* append a NULL so the string is properly terminated */ 8403 *str = '\0'; 8404 8405 mp_clear (&t); 8406 return MP_OKAY; 8407} 8408 8409#endif 8410 8411/* $Source: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */ 8412/* $Revision: 1.3 $ */ 8413/* $Date: 2006/03/31 14:18:44 $ */ 8414 8415/* End: bn_mp_toradix.c */ 8416 8417/* Start: bn_mp_toradix_n.c */ 8418#include <tommath.h> 8419#ifdef BN_MP_TORADIX_N_C 8420/* LibTomMath, multiple-precision integer library -- Tom St Denis 8421 * 8422 * LibTomMath is a library that provides multiple-precision 8423 * integer arithmetic as well as number theoretic functionality. 8424 * 8425 * The library was designed directly after the MPI library by 8426 * Michael Fromberger but has been written from scratch with 8427 * additional optimizations in place. 8428 * 8429 * The library is free for all purposes without any express 8430 * guarantee it works. 8431 * 8432 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8433 */ 8434 8435/* stores a bignum as a ASCII string in a given radix (2..64) 8436 * 8437 * Stores upto maxlen-1 chars and always a NULL byte 8438 */ 8439int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen) 8440{ 8441 int res, digs; 8442 mp_int t; 8443 mp_digit d; 8444 char *_s = str; 8445 8446 /* check range of the maxlen, radix */ 8447 if (maxlen < 2 || radix < 2 || radix > 64) { 8448 return MP_VAL; 8449 } 8450 8451 /* quick out if its zero */ 8452 if (mp_iszero(a) == MP_YES) { 8453 *str++ = '0'; 8454 *str = '\0'; 8455 return MP_OKAY; 8456 } 8457 8458 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 8459 return res; 8460 } 8461 8462 /* if it is negative output a - */ 8463 if (t.sign == MP_NEG) { 8464 /* we have to reverse our digits later... but not the - sign!! */ 8465 ++_s; 8466 8467 /* store the flag and mark the number as positive */ 8468 *str++ = '-'; 8469 t.sign = MP_ZPOS; 8470 8471 /* subtract a char */ 8472 --maxlen; 8473 } 8474 8475 digs = 0; 8476 while (mp_iszero (&t) == 0) { 8477 if (--maxlen < 1) { 8478 /* no more room */ 8479 break; 8480 } 8481 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { 8482 mp_clear (&t); 8483 return res; 8484 } 8485 *str++ = mp_s_rmap[d]; 8486 ++digs; 8487 } 8488 8489 /* reverse the digits of the string. In this case _s points 8490 * to the first digit [exluding the sign] of the number 8491 */ 8492 bn_reverse ((unsigned char *)_s, digs); 8493 8494 /* append a NULL so the string is properly terminated */ 8495 *str = '\0'; 8496 8497 mp_clear (&t); 8498 return MP_OKAY; 8499} 8500 8501#endif 8502 8503/* $Source: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */ 8504/* $Revision: 1.4 $ */ 8505/* $Date: 2006/03/31 14:18:44 $ */ 8506 8507/* End: bn_mp_toradix_n.c */ 8508 8509/* Start: bn_mp_unsigned_bin_size.c */ 8510#include <tommath.h> 8511#ifdef BN_MP_UNSIGNED_BIN_SIZE_C 8512/* LibTomMath, multiple-precision integer library -- Tom St Denis 8513 * 8514 * LibTomMath is a library that provides multiple-precision 8515 * integer arithmetic as well as number theoretic functionality. 8516 * 8517 * The library was designed directly after the MPI library by 8518 * Michael Fromberger but has been written from scratch with 8519 * additional optimizations in place. 8520 * 8521 * The library is free for all purposes without any express 8522 * guarantee it works. 8523 * 8524 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8525 */ 8526 8527/* get the size for an unsigned equivalent */ 8528int mp_unsigned_bin_size (mp_int * a) 8529{ 8530 int size = mp_count_bits (a); 8531 return (size / 8 + ((size & 7) != 0 ? 1 : 0)); 8532} 8533#endif 8534 8535/* $Source: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */ 8536/* $Revision: 1.3 $ */ 8537/* $Date: 2006/03/31 14:18:44 $ */ 8538 8539/* End: bn_mp_unsigned_bin_size.c */ 8540 8541/* Start: bn_mp_xor.c */ 8542#include <tommath.h> 8543#ifdef BN_MP_XOR_C 8544/* LibTomMath, multiple-precision integer library -- Tom St Denis 8545 * 8546 * LibTomMath is a library that provides multiple-precision 8547 * integer arithmetic as well as number theoretic functionality. 8548 * 8549 * The library was designed directly after the MPI library by 8550 * Michael Fromberger but has been written from scratch with 8551 * additional optimizations in place. 8552 * 8553 * The library is free for all purposes without any express 8554 * guarantee it works. 8555 * 8556 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8557 */ 8558 8559/* XOR two ints together */ 8560int 8561mp_xor (mp_int * a, mp_int * b, mp_int * c) 8562{ 8563 int res, ix, px; 8564 mp_int t, *x; 8565 8566 if (a->used > b->used) { 8567 if ((res = mp_init_copy (&t, a)) != MP_OKAY) { 8568 return res; 8569 } 8570 px = b->used; 8571 x = b; 8572 } else { 8573 if ((res = mp_init_copy (&t, b)) != MP_OKAY) { 8574 return res; 8575 } 8576 px = a->used; 8577 x = a; 8578 } 8579 8580 for (ix = 0; ix < px; ix++) { 8581 t.dp[ix] ^= x->dp[ix]; 8582 } 8583 mp_clamp (&t); 8584 mp_exch (c, &t); 8585 mp_clear (&t); 8586 return MP_OKAY; 8587} 8588#endif 8589 8590/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */ 8591/* $Revision: 1.3 $ */ 8592/* $Date: 2006/03/31 14:18:44 $ */ 8593 8594/* End: bn_mp_xor.c */ 8595 8596/* Start: bn_mp_zero.c */ 8597#include <tommath.h> 8598#ifdef BN_MP_ZERO_C 8599/* LibTomMath, multiple-precision integer library -- Tom St Denis 8600 * 8601 * LibTomMath is a library that provides multiple-precision 8602 * integer arithmetic as well as number theoretic functionality. 8603 * 8604 * The library was designed directly after the MPI library by 8605 * Michael Fromberger but has been written from scratch with 8606 * additional optimizations in place. 8607 * 8608 * The library is free for all purposes without any express 8609 * guarantee it works. 8610 * 8611 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8612 */ 8613 8614/* set to zero */ 8615void mp_zero (mp_int * a) 8616{ 8617 int n; 8618 mp_digit *tmp; 8619 8620 a->sign = MP_ZPOS; 8621 a->used = 0; 8622 8623 tmp = a->dp; 8624 for (n = 0; n < a->alloc; n++) { 8625 *tmp++ = 0; 8626 } 8627} 8628#endif 8629 8630/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */ 8631/* $Revision: 1.3 $ */ 8632/* $Date: 2006/03/31 14:18:44 $ */ 8633 8634/* End: bn_mp_zero.c */ 8635 8636/* Start: bn_prime_tab.c */ 8637#include <tommath.h> 8638#ifdef BN_PRIME_TAB_C 8639/* LibTomMath, multiple-precision integer library -- Tom St Denis 8640 * 8641 * LibTomMath is a library that provides multiple-precision 8642 * integer arithmetic as well as number theoretic functionality. 8643 * 8644 * The library was designed directly after the MPI library by 8645 * Michael Fromberger but has been written from scratch with 8646 * additional optimizations in place. 8647 * 8648 * The library is free for all purposes without any express 8649 * guarantee it works. 8650 * 8651 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8652 */ 8653const mp_digit ltm_prime_tab[] = { 8654 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 8655 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, 8656 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, 8657 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 8658#ifndef MP_8BIT 8659 0x0083, 8660 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, 8661 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, 8662 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, 8663 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, 8664 8665 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, 8666 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, 8667 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, 8668 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, 8669 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, 8670 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, 8671 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, 8672 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, 8673 8674 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, 8675 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, 8676 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, 8677 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, 8678 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, 8679 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, 8680 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, 8681 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, 8682 8683 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, 8684 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, 8685 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, 8686 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, 8687 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, 8688 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, 8689 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, 8690 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 8691#endif 8692}; 8693#endif 8694 8695/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */ 8696/* $Revision: 1.3 $ */ 8697/* $Date: 2006/03/31 14:18:44 $ */ 8698 8699/* End: bn_prime_tab.c */ 8700 8701/* Start: bn_reverse.c */ 8702#include <tommath.h> 8703#ifdef BN_REVERSE_C 8704/* LibTomMath, multiple-precision integer library -- Tom St Denis 8705 * 8706 * LibTomMath is a library that provides multiple-precision 8707 * integer arithmetic as well as number theoretic functionality. 8708 * 8709 * The library was designed directly after the MPI library by 8710 * Michael Fromberger but has been written from scratch with 8711 * additional optimizations in place. 8712 * 8713 * The library is free for all purposes without any express 8714 * guarantee it works. 8715 * 8716 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8717 */ 8718 8719/* reverse an array, used for radix code */ 8720void 8721bn_reverse (unsigned char *s, int len) 8722{ 8723 int ix, iy; 8724 unsigned char t; 8725 8726 ix = 0; 8727 iy = len - 1; 8728 while (ix < iy) { 8729 t = s[ix]; 8730 s[ix] = s[iy]; 8731 s[iy] = t; 8732 ++ix; 8733 --iy; 8734 } 8735} 8736#endif 8737 8738/* $Source: /cvs/libtom/libtommath/bn_reverse.c,v $ */ 8739/* $Revision: 1.3 $ */ 8740/* $Date: 2006/03/31 14:18:44 $ */ 8741 8742/* End: bn_reverse.c */ 8743 8744/* Start: bn_s_mp_add.c */ 8745#include <tommath.h> 8746#ifdef BN_S_MP_ADD_C 8747/* LibTomMath, multiple-precision integer library -- Tom St Denis 8748 * 8749 * LibTomMath is a library that provides multiple-precision 8750 * integer arithmetic as well as number theoretic functionality. 8751 * 8752 * The library was designed directly after the MPI library by 8753 * Michael Fromberger but has been written from scratch with 8754 * additional optimizations in place. 8755 * 8756 * The library is free for all purposes without any express 8757 * guarantee it works. 8758 * 8759 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8760 */ 8761 8762/* low level addition, based on HAC pp.594, Algorithm 14.7 */ 8763int 8764s_mp_add (mp_int * a, mp_int * b, mp_int * c) 8765{ 8766 mp_int *x; 8767 int olduse, res, min, max; 8768 8769 /* find sizes, we let |a| <= |b| which means we have to sort 8770 * them. "x" will point to the input with the most digits 8771 */ 8772 if (a->used > b->used) { 8773 min = b->used; 8774 max = a->used; 8775 x = a; 8776 } else { 8777 min = a->used; 8778 max = b->used; 8779 x = b; 8780 } 8781 8782 /* init result */ 8783 if (c->alloc < max + 1) { 8784 if ((res = mp_grow (c, max + 1)) != MP_OKAY) { 8785 return res; 8786 } 8787 } 8788 8789 /* get old used digit count and set new one */ 8790 olduse = c->used; 8791 c->used = max + 1; 8792 8793 { 8794 register mp_digit u, *tmpa, *tmpb, *tmpc; 8795 register int i; 8796 8797 /* alias for digit pointers */ 8798 8799 /* first input */ 8800 tmpa = a->dp; 8801 8802 /* second input */ 8803 tmpb = b->dp; 8804 8805 /* destination */ 8806 tmpc = c->dp; 8807 8808 /* zero the carry */ 8809 u = 0; 8810 for (i = 0; i < min; i++) { 8811 /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ 8812 *tmpc = *tmpa++ + *tmpb++ + u; 8813 8814 /* U = carry bit of T[i] */ 8815 u = *tmpc >> ((mp_digit)DIGIT_BIT); 8816 8817 /* take away carry bit from T[i] */ 8818 *tmpc++ &= MP_MASK; 8819 } 8820 8821 /* now copy higher words if any, that is in A+B 8822 * if A or B has more digits add those in 8823 */ 8824 if (min != max) { 8825 for (; i < max; i++) { 8826 /* T[i] = X[i] + U */ 8827 *tmpc = x->dp[i] + u; 8828 8829 /* U = carry bit of T[i] */ 8830 u = *tmpc >> ((mp_digit)DIGIT_BIT); 8831 8832 /* take away carry bit from T[i] */ 8833 *tmpc++ &= MP_MASK; 8834 } 8835 } 8836 8837 /* add carry */ 8838 *tmpc++ = u; 8839 8840 /* clear digits above oldused */ 8841 for (i = c->used; i < olduse; i++) { 8842 *tmpc++ = 0; 8843 } 8844 } 8845 8846 mp_clamp (c); 8847 return MP_OKAY; 8848} 8849#endif 8850 8851/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */ 8852/* $Revision: 1.3 $ */ 8853/* $Date: 2006/03/31 14:18:44 $ */ 8854 8855/* End: bn_s_mp_add.c */ 8856 8857/* Start: bn_s_mp_exptmod.c */ 8858#include <tommath.h> 8859#ifdef BN_S_MP_EXPTMOD_C 8860/* LibTomMath, multiple-precision integer library -- Tom St Denis 8861 * 8862 * LibTomMath is a library that provides multiple-precision 8863 * integer arithmetic as well as number theoretic functionality. 8864 * 8865 * The library was designed directly after the MPI library by 8866 * Michael Fromberger but has been written from scratch with 8867 * additional optimizations in place. 8868 * 8869 * The library is free for all purposes without any express 8870 * guarantee it works. 8871 * 8872 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 8873 */ 8874#ifdef MP_LOW_MEM 8875 #define TAB_SIZE 32 8876#else 8877 #define TAB_SIZE 256 8878#endif 8879 8880int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) 8881{ 8882 mp_int M[TAB_SIZE], res, mu; 8883 mp_digit buf; 8884 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; 8885 int (*redux)(mp_int*,mp_int*,mp_int*); 8886 8887 /* find window size */ 8888 x = mp_count_bits (X); 8889 if (x <= 7) { 8890 winsize = 2; 8891 } else if (x <= 36) { 8892 winsize = 3; 8893 } else if (x <= 140) { 8894 winsize = 4; 8895 } else if (x <= 450) { 8896 winsize = 5; 8897 } else if (x <= 1303) { 8898 winsize = 6; 8899 } else if (x <= 3529) { 8900 winsize = 7; 8901 } else { 8902 winsize = 8; 8903 } 8904 8905#ifdef MP_LOW_MEM 8906 if (winsize > 5) { 8907 winsize = 5; 8908 } 8909#endif 8910 8911 /* init M array */ 8912 /* init first cell */ 8913 if ((err = mp_init(&M[1])) != MP_OKAY) { 8914 return err; 8915 } 8916 8917 /* now init the second half of the array */ 8918 for (x = 1<<(winsize-1); x < (1 << winsize); x++) { 8919 if ((err = mp_init(&M[x])) != MP_OKAY) { 8920 for (y = 1<<(winsize-1); y < x; y++) { 8921 mp_clear (&M[y]); 8922 } 8923 mp_clear(&M[1]); 8924 return err; 8925 } 8926 } 8927 8928 /* create mu, used for Barrett reduction */ 8929 if ((err = mp_init (&mu)) != MP_OKAY) { 8930 goto LBL_M; 8931 } 8932 8933 if (redmode == 0) { 8934 if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { 8935 goto LBL_MU; 8936 } 8937 redux = mp_reduce; 8938 } else { 8939 if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { 8940 goto LBL_MU; 8941 } 8942 redux = mp_reduce_2k_l; 8943 } 8944 8945 /* create M table 8946 * 8947 * The M table contains powers of the base, 8948 * e.g. M[x] = G**x mod P 8949 * 8950 * The first half of the table is not 8951 * computed though accept for M[0] and M[1] 8952 */ 8953 if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { 8954 goto LBL_MU; 8955 } 8956 8957 /* compute the value at M[1<<(winsize-1)] by squaring 8958 * M[1] (winsize-1) times 8959 */ 8960 if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { 8961 goto LBL_MU; 8962 } 8963 8964 for (x = 0; x < (winsize - 1); x++) { 8965 /* square it */ 8966 if ((err = mp_sqr (&M[1 << (winsize - 1)], 8967 &M[1 << (winsize - 1)])) != MP_OKAY) { 8968 goto LBL_MU; 8969 } 8970 8971 /* reduce modulo P */ 8972 if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { 8973 goto LBL_MU; 8974 } 8975 } 8976 8977 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) 8978 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) 8979 */ 8980 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { 8981 if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { 8982 goto LBL_MU; 8983 } 8984 if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { 8985 goto LBL_MU; 8986 } 8987 } 8988 8989 /* setup result */ 8990 if ((err = mp_init (&res)) != MP_OKAY) { 8991 goto LBL_MU; 8992 } 8993 mp_set (&res, 1); 8994 8995 /* set initial mode and bit cnt */ 8996 mode = 0; 8997 bitcnt = 1; 8998 buf = 0; 8999 digidx = X->used - 1; 9000 bitcpy = 0; 9001 bitbuf = 0; 9002 9003 for (;;) { 9004 /* grab next digit as required */ 9005 if (--bitcnt == 0) { 9006 /* if digidx == -1 we are out of digits */ 9007 if (digidx == -1) { 9008 break; 9009 } 9010 /* read next digit and reset the bitcnt */ 9011 buf = X->dp[digidx--]; 9012 bitcnt = (int) DIGIT_BIT; 9013 } 9014 9015 /* grab the next msb from the exponent */ 9016 y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; 9017 buf <<= (mp_digit)1; 9018 9019 /* if the bit is zero and mode == 0 then we ignore it 9020 * These represent the leading zero bits before the first 1 bit 9021 * in the exponent. Technically this opt is not required but it 9022 * does lower the # of trivial squaring/reductions used 9023 */ 9024 if (mode == 0 && y == 0) { 9025 continue; 9026 } 9027 9028 /* if the bit is zero and mode == 1 then we square */ 9029 if (mode == 1 && y == 0) { 9030 if ((err = mp_sqr (&res, &res)) != MP_OKAY) { 9031 goto LBL_RES; 9032 } 9033 if ((err = redux (&res, P, &mu)) != MP_OKAY) { 9034 goto LBL_RES; 9035 } 9036 continue; 9037 } 9038 9039 /* else we add it to the window */ 9040 bitbuf |= (y << (winsize - ++bitcpy)); 9041 mode = 2; 9042 9043 if (bitcpy == winsize) { 9044 /* ok window is filled so square as required and multiply */ 9045 /* square first */ 9046 for (x = 0; x < winsize; x++) { 9047 if ((err = mp_sqr (&res, &res)) != MP_OKAY) { 9048 goto LBL_RES; 9049 } 9050 if ((err = redux (&res, P, &mu)) != MP_OKAY) { 9051 goto LBL_RES; 9052 } 9053 } 9054 9055 /* then multiply */ 9056 if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { 9057 goto LBL_RES; 9058 } 9059 if ((err = redux (&res, P, &mu)) != MP_OKAY) { 9060 goto LBL_RES; 9061 } 9062 9063 /* empty window and reset */ 9064 bitcpy = 0; 9065 bitbuf = 0; 9066 mode = 1; 9067 } 9068 } 9069 9070 /* if bits remain then square/multiply */ 9071 if (mode == 2 && bitcpy > 0) { 9072 /* square then multiply if the bit is set */ 9073 for (x = 0; x < bitcpy; x++) { 9074 if ((err = mp_sqr (&res, &res)) != MP_OKAY) { 9075 goto LBL_RES; 9076 } 9077 if ((err = redux (&res, P, &mu)) != MP_OKAY) { 9078 goto LBL_RES; 9079 } 9080 9081 bitbuf <<= 1; 9082 if ((bitbuf & (1 << winsize)) != 0) { 9083 /* then multiply */ 9084 if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { 9085 goto LBL_RES; 9086 } 9087 if ((err = redux (&res, P, &mu)) != MP_OKAY) { 9088 goto LBL_RES; 9089 } 9090 } 9091 } 9092 } 9093 9094 mp_exch (&res, Y); 9095 err = MP_OKAY; 9096LBL_RES:mp_clear (&res); 9097LBL_MU:mp_clear (&mu); 9098LBL_M: 9099 mp_clear(&M[1]); 9100 for (x = 1<<(winsize-1); x < (1 << winsize); x++) { 9101 mp_clear (&M[x]); 9102 } 9103 return err; 9104} 9105#endif 9106 9107/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */ 9108/* $Revision: 1.4 $ */ 9109/* $Date: 2006/03/31 14:18:44 $ */ 9110 9111/* End: bn_s_mp_exptmod.c */ 9112 9113/* Start: bn_s_mp_mul_digs.c */ 9114#include <tommath.h> 9115#ifdef BN_S_MP_MUL_DIGS_C 9116/* LibTomMath, multiple-precision integer library -- Tom St Denis 9117 * 9118 * LibTomMath is a library that provides multiple-precision 9119 * integer arithmetic as well as number theoretic functionality. 9120 * 9121 * The library was designed directly after the MPI library by 9122 * Michael Fromberger but has been written from scratch with 9123 * additional optimizations in place. 9124 * 9125 * The library is free for all purposes without any express 9126 * guarantee it works. 9127 * 9128 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 9129 */ 9130 9131/* multiplies |a| * |b| and only computes upto digs digits of result 9132 * HAC pp. 595, Algorithm 14.12 Modified so you can control how 9133 * many digits of output are created. 9134 */ 9135int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) 9136{ 9137 mp_int t; 9138 int res, pa, pb, ix, iy; 9139 mp_digit u; 9140 mp_word r; 9141 mp_digit tmpx, *tmpt, *tmpy; 9142 9143 /* can we use the fast multiplier? */ 9144 if (((digs) < MP_WARRAY) && 9145 MIN (a->used, b->used) < 9146 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { 9147 return fast_s_mp_mul_digs (a, b, c, digs); 9148 } 9149 9150 if ((res = mp_init_size (&t, digs)) != MP_OKAY) { 9151 return res; 9152 } 9153 t.used = digs; 9154 9155 /* compute the digits of the product directly */ 9156 pa = a->used; 9157 for (ix = 0; ix < pa; ix++) { 9158 /* set the carry to zero */ 9159 u = 0; 9160 9161 /* limit ourselves to making digs digits of output */ 9162 pb = MIN (b->used, digs - ix); 9163 9164 /* setup some aliases */ 9165 /* copy of the digit from a used within the nested loop */ 9166 tmpx = a->dp[ix]; 9167 9168 /* an alias for the destination shifted ix places */ 9169 tmpt = t.dp + ix; 9170 9171 /* an alias for the digits of b */ 9172 tmpy = b->dp; 9173 9174 /* compute the columns of the output and propagate the carry */ 9175 for (iy = 0; iy < pb; iy++) { 9176 /* compute the column as a mp_word */ 9177 r = ((mp_word)*tmpt) + 9178 ((mp_word)tmpx) * ((mp_word)*tmpy++) + 9179 ((mp_word) u); 9180 9181 /* the new column is the lower part of the result */ 9182 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); 9183 9184 /* get the carry word from the result */ 9185 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); 9186 } 9187 /* set carry if it is placed below digs */ 9188 if (ix + iy < digs) { 9189 *tmpt = u; 9190 } 9191 } 9192 9193 mp_clamp (&t); 9194 mp_exch (&t, c); 9195 9196 mp_clear (&t); 9197 return MP_OKAY; 9198} 9199#endif 9200 9201/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */ 9202/* $Revision: 1.3 $ */ 9203/* $Date: 2006/03/31 14:18:44 $ */ 9204 9205/* End: bn_s_mp_mul_digs.c */ 9206 9207/* Start: bn_s_mp_mul_high_digs.c */ 9208#include <tommath.h> 9209#ifdef BN_S_MP_MUL_HIGH_DIGS_C 9210/* LibTomMath, multiple-precision integer library -- Tom St Denis 9211 * 9212 * LibTomMath is a library that provides multiple-precision 9213 * integer arithmetic as well as number theoretic functionality. 9214 * 9215 * The library was designed directly after the MPI library by 9216 * Michael Fromberger but has been written from scratch with 9217 * additional optimizations in place. 9218 * 9219 * The library is free for all purposes without any express 9220 * guarantee it works. 9221 * 9222 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 9223 */ 9224 9225/* multiplies |a| * |b| and does not compute the lower digs digits 9226 * [meant to get the higher part of the product] 9227 */ 9228int 9229s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) 9230{ 9231 mp_int t; 9232 int res, pa, pb, ix, iy; 9233 mp_digit u; 9234 mp_word r; 9235 mp_digit tmpx, *tmpt, *tmpy; 9236 9237 /* can we use the fast multiplier? */ 9238#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C 9239 if (((a->used + b->used + 1) < MP_WARRAY) 9240 && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { 9241 return fast_s_mp_mul_high_digs (a, b, c, digs); 9242 } 9243#endif 9244 9245 if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { 9246 return res; 9247 } 9248 t.used = a->used + b->used + 1; 9249 9250 pa = a->used; 9251 pb = b->used; 9252 for (ix = 0; ix < pa; ix++) { 9253 /* clear the carry */ 9254 u = 0; 9255 9256 /* left hand side of A[ix] * B[iy] */ 9257 tmpx = a->dp[ix]; 9258 9259 /* alias to the address of where the digits will be stored */ 9260 tmpt = &(t.dp[digs]); 9261 9262 /* alias for where to read the right hand side from */ 9263 tmpy = b->dp + (digs - ix); 9264 9265 for (iy = digs - ix; iy < pb; iy++) { 9266 /* calculate the double precision result */ 9267 r = ((mp_word)*tmpt) + 9268 ((mp_word)tmpx) * ((mp_word)*tmpy++) + 9269 ((mp_word) u); 9270 9271 /* get the lower part */ 9272 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); 9273 9274 /* carry the carry */ 9275 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); 9276 } 9277 *tmpt = u; 9278 } 9279 mp_clamp (&t); 9280 mp_exch (&t, c); 9281 mp_clear (&t); 9282 return MP_OKAY; 9283} 9284#endif 9285 9286/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */ 9287/* $Revision: 1.3 $ */ 9288/* $Date: 2006/03/31 14:18:44 $ */ 9289 9290/* End: bn_s_mp_mul_high_digs.c */ 9291 9292/* Start: bn_s_mp_sqr.c */ 9293#include <tommath.h> 9294#ifdef BN_S_MP_SQR_C 9295/* LibTomMath, multiple-precision integer library -- Tom St Denis 9296 * 9297 * LibTomMath is a library that provides multiple-precision 9298 * integer arithmetic as well as number theoretic functionality. 9299 * 9300 * The library was designed directly after the MPI library by 9301 * Michael Fromberger but has been written from scratch with 9302 * additional optimizations in place. 9303 * 9304 * The library is free for all purposes without any express 9305 * guarantee it works. 9306 * 9307 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 9308 */ 9309 9310/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ 9311int s_mp_sqr (mp_int * a, mp_int * b) 9312{ 9313 mp_int t; 9314 int res, ix, iy, pa; 9315 mp_word r; 9316 mp_digit u, tmpx, *tmpt; 9317 9318 pa = a->used; 9319 if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { 9320 return res; 9321 } 9322 9323 /* default used is maximum possible size */ 9324 t.used = 2*pa + 1; 9325 9326 for (ix = 0; ix < pa; ix++) { 9327 /* first calculate the digit at 2*ix */ 9328 /* calculate double precision result */ 9329 r = ((mp_word) t.dp[2*ix]) + 9330 ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); 9331 9332 /* store lower part in result */ 9333 t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); 9334 9335 /* get the carry */ 9336 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); 9337 9338 /* left hand side of A[ix] * A[iy] */ 9339 tmpx = a->dp[ix]; 9340 9341 /* alias for where to store the results */ 9342 tmpt = t.dp + (2*ix + 1); 9343 9344 for (iy = ix + 1; iy < pa; iy++) { 9345 /* first calculate the product */ 9346 r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); 9347 9348 /* now calculate the double precision result, note we use 9349 * addition instead of *2 since it's easier to optimize 9350 */ 9351 r = ((mp_word) *tmpt) + r + r + ((mp_word) u); 9352 9353 /* store lower part */ 9354 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); 9355 9356 /* get carry */ 9357 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); 9358 } 9359 /* propagate upwards */ 9360 while (u != ((mp_digit) 0)) { 9361 r = ((mp_word) *tmpt) + ((mp_word) u); 9362 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); 9363 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); 9364 } 9365 } 9366 9367 mp_clamp (&t); 9368 mp_exch (&t, b); 9369 mp_clear (&t); 9370 return MP_OKAY; 9371} 9372#endif 9373 9374/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */ 9375/* $Revision: 1.3 $ */ 9376/* $Date: 2006/03/31 14:18:44 $ */ 9377 9378/* End: bn_s_mp_sqr.c */ 9379 9380/* Start: bn_s_mp_sub.c */ 9381#include <tommath.h> 9382#ifdef BN_S_MP_SUB_C 9383/* LibTomMath, multiple-precision integer library -- Tom St Denis 9384 * 9385 * LibTomMath is a library that provides multiple-precision 9386 * integer arithmetic as well as number theoretic functionality. 9387 * 9388 * The library was designed directly after the MPI library by 9389 * Michael Fromberger but has been written from scratch with 9390 * additional optimizations in place. 9391 * 9392 * The library is free for all purposes without any express 9393 * guarantee it works. 9394 * 9395 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 9396 */ 9397 9398/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ 9399int 9400s_mp_sub (mp_int * a, mp_int * b, mp_int * c) 9401{ 9402 int olduse, res, min, max; 9403 9404 /* find sizes */ 9405 min = b->used; 9406 max = a->used; 9407 9408 /* init result */ 9409 if (c->alloc < max) { 9410 if ((res = mp_grow (c, max)) != MP_OKAY) { 9411 return res; 9412 } 9413 } 9414 olduse = c->used; 9415 c->used = max; 9416 9417 { 9418 register mp_digit u, *tmpa, *tmpb, *tmpc; 9419 register int i; 9420 9421 /* alias for digit pointers */ 9422 tmpa = a->dp; 9423 tmpb = b->dp; 9424 tmpc = c->dp; 9425 9426 /* set carry to zero */ 9427 u = 0; 9428 for (i = 0; i < min; i++) { 9429 /* T[i] = A[i] - B[i] - U */ 9430 *tmpc = *tmpa++ - *tmpb++ - u; 9431 9432 /* U = carry bit of T[i] 9433 * Note this saves performing an AND operation since 9434 * if a carry does occur it will propagate all the way to the 9435 * MSB. As a result a single shift is enough to get the carry 9436 */ 9437 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); 9438 9439 /* Clear carry from T[i] */ 9440 *tmpc++ &= MP_MASK; 9441 } 9442 9443 /* now copy higher words if any, e.g. if A has more digits than B */ 9444 for (; i < max; i++) { 9445 /* T[i] = A[i] - U */ 9446 *tmpc = *tmpa++ - u; 9447 9448 /* U = carry bit of T[i] */ 9449 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); 9450 9451 /* Clear carry from T[i] */ 9452 *tmpc++ &= MP_MASK; 9453 } 9454 9455 /* clear digits above used (since we may not have grown result above) */ 9456 for (i = c->used; i < olduse; i++) { 9457 *tmpc++ = 0; 9458 } 9459 } 9460 9461 mp_clamp (c); 9462 return MP_OKAY; 9463} 9464 9465#endif 9466 9467/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */ 9468/* $Revision: 1.3 $ */ 9469/* $Date: 2006/03/31 14:18:44 $ */ 9470 9471/* End: bn_s_mp_sub.c */ 9472 9473/* Start: bncore.c */ 9474#include <tommath.h> 9475#ifdef BNCORE_C 9476/* LibTomMath, multiple-precision integer library -- Tom St Denis 9477 * 9478 * LibTomMath is a library that provides multiple-precision 9479 * integer arithmetic as well as number theoretic functionality. 9480 * 9481 * The library was designed directly after the MPI library by 9482 * Michael Fromberger but has been written from scratch with 9483 * additional optimizations in place. 9484 * 9485 * The library is free for all purposes without any express 9486 * guarantee it works. 9487 * 9488 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 9489 */ 9490 9491/* Known optimal configurations 9492 9493 CPU /Compiler /MUL CUTOFF/SQR CUTOFF 9494------------------------------------------------------------- 9495 Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-) 9496 AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35 9497 9498*/ 9499 9500int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */ 9501 KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */ 9502 9503 TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */ 9504 TOOM_SQR_CUTOFF = 400; 9505#endif 9506 9507/* $Source: /cvs/libtom/libtommath/bncore.c,v $ */ 9508/* $Revision: 1.4 $ */ 9509/* $Date: 2006/03/31 14:18:44 $ */ 9510 9511/* End: bncore.c */ 9512 9513 9514/* EOF */ 9515