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