security/nss/lib/freebl/mpi/mpi.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * mpi.c
michael@0 3 *
michael@0 4 * Arbitrary precision integer arithmetic library
michael@0 5 *
michael@0 6 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 7 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 9
michael@0 10 #include "mpi-priv.h"
michael@0 11 #if defined(OSF1)
michael@0 12 #include <c_asm.h>
michael@0 13 #endif
michael@0 14
michael@0 15 #if defined(__arm__) && \
michael@0 16 ((defined(__thumb__) && !defined(__thumb2__)) || defined(__ARM_ARCH_3__))
michael@0 17 /* 16-bit thumb or ARM v3 doesn't work inlined assember version */
michael@0 18 #undef MP_ASSEMBLY_MULTIPLY
michael@0 19 #undef MP_ASSEMBLY_SQUARE
michael@0 20 #endif
michael@0 21
michael@0 22 #if MP_LOGTAB
michael@0 23 /*
michael@0 24 A table of the logs of 2 for various bases (the 0 and 1 entries of
michael@0 25 this table are meaningless and should not be referenced).
michael@0 26
michael@0 27 This table is used to compute output lengths for the mp_toradix()
michael@0 28 function. Since a number n in radix r takes up about log_r(n)
michael@0 29 digits, we estimate the output size by taking the least integer
michael@0 30 greater than log_r(n), where:
michael@0 31
michael@0 32 log_r(n) = log_2(n) * log_r(2)
michael@0 33
michael@0 34 This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
michael@0 35 which are the output bases supported.
michael@0 36 */
michael@0 37 #include "logtab.h"
michael@0 38 #endif
michael@0 39
michael@0 40 /* {{{ Constant strings */
michael@0 41
michael@0 42 /* Constant strings returned by mp_strerror() */
michael@0 43 static const char *mp_err_string[] = {
michael@0 44 "unknown result code", /* say what? */
michael@0 45 "boolean true", /* MP_OKAY, MP_YES */
michael@0 46 "boolean false", /* MP_NO */
michael@0 47 "out of memory", /* MP_MEM */
michael@0 48 "argument out of range", /* MP_RANGE */
michael@0 49 "invalid input parameter", /* MP_BADARG */
michael@0 50 "result is undefined" /* MP_UNDEF */
michael@0 51 };
michael@0 52
michael@0 53 /* Value to digit maps for radix conversion */
michael@0 54
michael@0 55 /* s_dmap_1 - standard digits and letters */
michael@0 56 static const char *s_dmap_1 =
michael@0 57 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
michael@0 58
michael@0 59 /* }}} */
michael@0 60
michael@0 61 unsigned long mp_allocs;
michael@0 62 unsigned long mp_frees;
michael@0 63 unsigned long mp_copies;
michael@0 64
michael@0 65 /* {{{ Default precision manipulation */
michael@0 66
michael@0 67 /* Default precision for newly created mp_int's */
michael@0 68 static mp_size s_mp_defprec = MP_DEFPREC;
michael@0 69
michael@0 70 mp_size mp_get_prec(void)
michael@0 71 {
michael@0 72 return s_mp_defprec;
michael@0 73
michael@0 74 } /* end mp_get_prec() */
michael@0 75
michael@0 76 void mp_set_prec(mp_size prec)
michael@0 77 {
michael@0 78 if(prec == 0)
michael@0 79 s_mp_defprec = MP_DEFPREC;
michael@0 80 else
michael@0 81 s_mp_defprec = prec;
michael@0 82
michael@0 83 } /* end mp_set_prec() */
michael@0 84
michael@0 85 /* }}} */
michael@0 86
michael@0 87 /*------------------------------------------------------------------------*/
michael@0 88 /* {{{ mp_init(mp) */
michael@0 89
michael@0 90 /*
michael@0 91 mp_init(mp)
michael@0 92
michael@0 93 Initialize a new zero-valued mp_int. Returns MP_OKAY if successful,
michael@0 94 MP_MEM if memory could not be allocated for the structure.
michael@0 95 */
michael@0 96
michael@0 97 mp_err mp_init(mp_int *mp)
michael@0 98 {
michael@0 99 return mp_init_size(mp, s_mp_defprec);
michael@0 100
michael@0 101 } /* end mp_init() */
michael@0 102
michael@0 103 /* }}} */
michael@0 104
michael@0 105 /* {{{ mp_init_size(mp, prec) */
michael@0 106
michael@0 107 /*
michael@0 108 mp_init_size(mp, prec)
michael@0 109
michael@0 110 Initialize a new zero-valued mp_int with at least the given
michael@0 111 precision; returns MP_OKAY if successful, or MP_MEM if memory could
michael@0 112 not be allocated for the structure.
michael@0 113 */
michael@0 114
michael@0 115 mp_err mp_init_size(mp_int *mp, mp_size prec)
michael@0 116 {
michael@0 117 ARGCHK(mp != NULL && prec > 0, MP_BADARG);
michael@0 118
michael@0 119 prec = MP_ROUNDUP(prec, s_mp_defprec);
michael@0 120 if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL)
michael@0 121 return MP_MEM;
michael@0 122
michael@0 123 SIGN(mp) = ZPOS;
michael@0 124 USED(mp) = 1;
michael@0 125 ALLOC(mp) = prec;
michael@0 126
michael@0 127 return MP_OKAY;
michael@0 128
michael@0 129 } /* end mp_init_size() */
michael@0 130
michael@0 131 /* }}} */
michael@0 132
michael@0 133 /* {{{ mp_init_copy(mp, from) */
michael@0 134
michael@0 135 /*
michael@0 136 mp_init_copy(mp, from)
michael@0 137
michael@0 138 Initialize mp as an exact copy of from. Returns MP_OKAY if
michael@0 139 successful, MP_MEM if memory could not be allocated for the new
michael@0 140 structure.
michael@0 141 */
michael@0 142
michael@0 143 mp_err mp_init_copy(mp_int *mp, const mp_int *from)
michael@0 144 {
michael@0 145 ARGCHK(mp != NULL && from != NULL, MP_BADARG);
michael@0 146
michael@0 147 if(mp == from)
michael@0 148 return MP_OKAY;
michael@0 149
michael@0 150 if((DIGITS(mp) = s_mp_alloc(ALLOC(from), sizeof(mp_digit))) == NULL)
michael@0 151 return MP_MEM;
michael@0 152
michael@0 153 s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
michael@0 154 USED(mp) = USED(from);
michael@0 155 ALLOC(mp) = ALLOC(from);
michael@0 156 SIGN(mp) = SIGN(from);
michael@0 157
michael@0 158 return MP_OKAY;
michael@0 159
michael@0 160 } /* end mp_init_copy() */
michael@0 161
michael@0 162 /* }}} */
michael@0 163
michael@0 164 /* {{{ mp_copy(from, to) */
michael@0 165
michael@0 166 /*
michael@0 167 mp_copy(from, to)
michael@0 168
michael@0 169 Copies the mp_int 'from' to the mp_int 'to'. It is presumed that
michael@0 170 'to' has already been initialized (if not, use mp_init_copy()
michael@0 171 instead). If 'from' and 'to' are identical, nothing happens.
michael@0 172 */
michael@0 173
michael@0 174 mp_err mp_copy(const mp_int *from, mp_int *to)
michael@0 175 {
michael@0 176 ARGCHK(from != NULL && to != NULL, MP_BADARG);
michael@0 177
michael@0 178 if(from == to)
michael@0 179 return MP_OKAY;
michael@0 180
michael@0 181 { /* copy */
michael@0 182 mp_digit *tmp;
michael@0 183
michael@0 184 /*
michael@0 185 If the allocated buffer in 'to' already has enough space to hold
michael@0 186 all the used digits of 'from', we'll re-use it to avoid hitting
michael@0 187 the memory allocater more than necessary; otherwise, we'd have
michael@0 188 to grow anyway, so we just allocate a hunk and make the copy as
michael@0 189 usual
michael@0 190 */
michael@0 191 if(ALLOC(to) >= USED(from)) {
michael@0 192 s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
michael@0 193 s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
michael@0 194
michael@0 195 } else {
michael@0 196 if((tmp = s_mp_alloc(ALLOC(from), sizeof(mp_digit))) == NULL)
michael@0 197 return MP_MEM;
michael@0 198
michael@0 199 s_mp_copy(DIGITS(from), tmp, USED(from));
michael@0 200
michael@0 201 if(DIGITS(to) != NULL) {
michael@0 202 #if MP_CRYPTO
michael@0 203 s_mp_setz(DIGITS(to), ALLOC(to));
michael@0 204 #endif
michael@0 205 s_mp_free(DIGITS(to));
michael@0 206 }
michael@0 207
michael@0 208 DIGITS(to) = tmp;
michael@0 209 ALLOC(to) = ALLOC(from);
michael@0 210 }
michael@0 211
michael@0 212 /* Copy the precision and sign from the original */
michael@0 213 USED(to) = USED(from);
michael@0 214 SIGN(to) = SIGN(from);
michael@0 215 } /* end copy */
michael@0 216
michael@0 217 return MP_OKAY;
michael@0 218
michael@0 219 } /* end mp_copy() */
michael@0 220
michael@0 221 /* }}} */
michael@0 222
michael@0 223 /* {{{ mp_exch(mp1, mp2) */
michael@0 224
michael@0 225 /*
michael@0 226 mp_exch(mp1, mp2)
michael@0 227
michael@0 228 Exchange mp1 and mp2 without allocating any intermediate memory
michael@0 229 (well, unless you count the stack space needed for this call and the
michael@0 230 locals it creates...). This cannot fail.
michael@0 231 */
michael@0 232
michael@0 233 void mp_exch(mp_int *mp1, mp_int *mp2)
michael@0 234 {
michael@0 235 #if MP_ARGCHK == 2
michael@0 236 assert(mp1 != NULL && mp2 != NULL);
michael@0 237 #else
michael@0 238 if(mp1 == NULL || mp2 == NULL)
michael@0 239 return;
michael@0 240 #endif
michael@0 241
michael@0 242 s_mp_exch(mp1, mp2);
michael@0 243
michael@0 244 } /* end mp_exch() */
michael@0 245
michael@0 246 /* }}} */
michael@0 247
michael@0 248 /* {{{ mp_clear(mp) */
michael@0 249
michael@0 250 /*
michael@0 251 mp_clear(mp)
michael@0 252
michael@0 253 Release the storage used by an mp_int, and void its fields so that
michael@0 254 if someone calls mp_clear() again for the same int later, we won't
michael@0 255 get tollchocked.
michael@0 256 */
michael@0 257
michael@0 258 void mp_clear(mp_int *mp)
michael@0 259 {
michael@0 260 if(mp == NULL)
michael@0 261 return;
michael@0 262
michael@0 263 if(DIGITS(mp) != NULL) {
michael@0 264 #if MP_CRYPTO
michael@0 265 s_mp_setz(DIGITS(mp), ALLOC(mp));
michael@0 266 #endif
michael@0 267 s_mp_free(DIGITS(mp));
michael@0 268 DIGITS(mp) = NULL;
michael@0 269 }
michael@0 270
michael@0 271 USED(mp) = 0;
michael@0 272 ALLOC(mp) = 0;
michael@0 273
michael@0 274 } /* end mp_clear() */
michael@0 275
michael@0 276 /* }}} */
michael@0 277
michael@0 278 /* {{{ mp_zero(mp) */
michael@0 279
michael@0 280 /*
michael@0 281 mp_zero(mp)
michael@0 282
michael@0 283 Set mp to zero. Does not change the allocated size of the structure,
michael@0 284 and therefore cannot fail (except on a bad argument, which we ignore)
michael@0 285 */
michael@0 286 void mp_zero(mp_int *mp)
michael@0 287 {
michael@0 288 if(mp == NULL)
michael@0 289 return;
michael@0 290
michael@0 291 s_mp_setz(DIGITS(mp), ALLOC(mp));
michael@0 292 USED(mp) = 1;
michael@0 293 SIGN(mp) = ZPOS;
michael@0 294
michael@0 295 } /* end mp_zero() */
michael@0 296
michael@0 297 /* }}} */
michael@0 298
michael@0 299 /* {{{ mp_set(mp, d) */
michael@0 300
michael@0 301 void mp_set(mp_int *mp, mp_digit d)
michael@0 302 {
michael@0 303 if(mp == NULL)
michael@0 304 return;
michael@0 305
michael@0 306 mp_zero(mp);
michael@0 307 DIGIT(mp, 0) = d;
michael@0 308
michael@0 309 } /* end mp_set() */
michael@0 310
michael@0 311 /* }}} */
michael@0 312
michael@0 313 /* {{{ mp_set_int(mp, z) */
michael@0 314
michael@0 315 mp_err mp_set_int(mp_int *mp, long z)
michael@0 316 {
michael@0 317 int ix;
michael@0 318 unsigned long v = labs(z);
michael@0 319 mp_err res;
michael@0 320
michael@0 321 ARGCHK(mp != NULL, MP_BADARG);
michael@0 322
michael@0 323 mp_zero(mp);
michael@0 324 if(z == 0)
michael@0 325 return MP_OKAY; /* shortcut for zero */
michael@0 326
michael@0 327 if (sizeof v <= sizeof(mp_digit)) {
michael@0 328 DIGIT(mp,0) = v;
michael@0 329 } else {
michael@0 330 for (ix = sizeof(long) - 1; ix >= 0; ix--) {
michael@0 331 if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
michael@0 332 return res;
michael@0 333
michael@0 334 res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
michael@0 335 if (res != MP_OKAY)
michael@0 336 return res;
michael@0 337 }
michael@0 338 }
michael@0 339 if(z < 0)
michael@0 340 SIGN(mp) = NEG;
michael@0 341
michael@0 342 return MP_OKAY;
michael@0 343
michael@0 344 } /* end mp_set_int() */
michael@0 345
michael@0 346 /* }}} */
michael@0 347
michael@0 348 /* {{{ mp_set_ulong(mp, z) */
michael@0 349
michael@0 350 mp_err mp_set_ulong(mp_int *mp, unsigned long z)
michael@0 351 {
michael@0 352 int ix;
michael@0 353 mp_err res;
michael@0 354
michael@0 355 ARGCHK(mp != NULL, MP_BADARG);
michael@0 356
michael@0 357 mp_zero(mp);
michael@0 358 if(z == 0)
michael@0 359 return MP_OKAY; /* shortcut for zero */
michael@0 360
michael@0 361 if (sizeof z <= sizeof(mp_digit)) {
michael@0 362 DIGIT(mp,0) = z;
michael@0 363 } else {
michael@0 364 for (ix = sizeof(long) - 1; ix >= 0; ix--) {
michael@0 365 if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
michael@0 366 return res;
michael@0 367
michael@0 368 res = s_mp_add_d(mp, (mp_digit)((z >> (ix * CHAR_BIT)) & UCHAR_MAX));
michael@0 369 if (res != MP_OKAY)
michael@0 370 return res;
michael@0 371 }
michael@0 372 }
michael@0 373 return MP_OKAY;
michael@0 374 } /* end mp_set_ulong() */
michael@0 375
michael@0 376 /* }}} */
michael@0 377
michael@0 378 /*------------------------------------------------------------------------*/
michael@0 379 /* {{{ Digit arithmetic */
michael@0 380
michael@0 381 /* {{{ mp_add_d(a, d, b) */
michael@0 382
michael@0 383 /*
michael@0 384 mp_add_d(a, d, b)
michael@0 385
michael@0 386 Compute the sum b = a + d, for a single digit d. Respects the sign of
michael@0 387 its primary addend (single digits are unsigned anyway).
michael@0 388 */
michael@0 389
michael@0 390 mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b)
michael@0 391 {
michael@0 392 mp_int tmp;
michael@0 393 mp_err res;
michael@0 394
michael@0 395 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 396
michael@0 397 if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
michael@0 398 return res;
michael@0 399
michael@0 400 if(SIGN(&tmp) == ZPOS) {
michael@0 401 if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
michael@0 402 goto CLEANUP;
michael@0 403 } else if(s_mp_cmp_d(&tmp, d) >= 0) {
michael@0 404 if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
michael@0 405 goto CLEANUP;
michael@0 406 } else {
michael@0 407 mp_neg(&tmp, &tmp);
michael@0 408
michael@0 409 DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
michael@0 410 }
michael@0 411
michael@0 412 if(s_mp_cmp_d(&tmp, 0) == 0)
michael@0 413 SIGN(&tmp) = ZPOS;
michael@0 414
michael@0 415 s_mp_exch(&tmp, b);
michael@0 416
michael@0 417 CLEANUP:
michael@0 418 mp_clear(&tmp);
michael@0 419 return res;
michael@0 420
michael@0 421 } /* end mp_add_d() */
michael@0 422
michael@0 423 /* }}} */
michael@0 424
michael@0 425 /* {{{ mp_sub_d(a, d, b) */
michael@0 426
michael@0 427 /*
michael@0 428 mp_sub_d(a, d, b)
michael@0 429
michael@0 430 Compute the difference b = a - d, for a single digit d. Respects the
michael@0 431 sign of its subtrahend (single digits are unsigned anyway).
michael@0 432 */
michael@0 433
michael@0 434 mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b)
michael@0 435 {
michael@0 436 mp_int tmp;
michael@0 437 mp_err res;
michael@0 438
michael@0 439 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 440
michael@0 441 if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
michael@0 442 return res;
michael@0 443
michael@0 444 if(SIGN(&tmp) == NEG) {
michael@0 445 if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
michael@0 446 goto CLEANUP;
michael@0 447 } else if(s_mp_cmp_d(&tmp, d) >= 0) {
michael@0 448 if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
michael@0 449 goto CLEANUP;
michael@0 450 } else {
michael@0 451 mp_neg(&tmp, &tmp);
michael@0 452
michael@0 453 DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
michael@0 454 SIGN(&tmp) = NEG;
michael@0 455 }
michael@0 456
michael@0 457 if(s_mp_cmp_d(&tmp, 0) == 0)
michael@0 458 SIGN(&tmp) = ZPOS;
michael@0 459
michael@0 460 s_mp_exch(&tmp, b);
michael@0 461
michael@0 462 CLEANUP:
michael@0 463 mp_clear(&tmp);
michael@0 464 return res;
michael@0 465
michael@0 466 } /* end mp_sub_d() */
michael@0 467
michael@0 468 /* }}} */
michael@0 469
michael@0 470 /* {{{ mp_mul_d(a, d, b) */
michael@0 471
michael@0 472 /*
michael@0 473 mp_mul_d(a, d, b)
michael@0 474
michael@0 475 Compute the product b = a * d, for a single digit d. Respects the sign
michael@0 476 of its multiplicand (single digits are unsigned anyway)
michael@0 477 */
michael@0 478
michael@0 479 mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b)
michael@0 480 {
michael@0 481 mp_err res;
michael@0 482
michael@0 483 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 484
michael@0 485 if(d == 0) {
michael@0 486 mp_zero(b);
michael@0 487 return MP_OKAY;
michael@0 488 }
michael@0 489
michael@0 490 if((res = mp_copy(a, b)) != MP_OKAY)
michael@0 491 return res;
michael@0 492
michael@0 493 res = s_mp_mul_d(b, d);
michael@0 494
michael@0 495 return res;
michael@0 496
michael@0 497 } /* end mp_mul_d() */
michael@0 498
michael@0 499 /* }}} */
michael@0 500
michael@0 501 /* {{{ mp_mul_2(a, c) */
michael@0 502
michael@0 503 mp_err mp_mul_2(const mp_int *a, mp_int *c)
michael@0 504 {
michael@0 505 mp_err res;
michael@0 506
michael@0 507 ARGCHK(a != NULL && c != NULL, MP_BADARG);
michael@0 508
michael@0 509 if((res = mp_copy(a, c)) != MP_OKAY)
michael@0 510 return res;
michael@0 511
michael@0 512 return s_mp_mul_2(c);
michael@0 513
michael@0 514 } /* end mp_mul_2() */
michael@0 515
michael@0 516 /* }}} */
michael@0 517
michael@0 518 /* {{{ mp_div_d(a, d, q, r) */
michael@0 519
michael@0 520 /*
michael@0 521 mp_div_d(a, d, q, r)
michael@0 522
michael@0 523 Compute the quotient q = a / d and remainder r = a mod d, for a
michael@0 524 single digit d. Respects the sign of its divisor (single digits are
michael@0 525 unsigned anyway).
michael@0 526 */
michael@0 527
michael@0 528 mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
michael@0 529 {
michael@0 530 mp_err res;
michael@0 531 mp_int qp;
michael@0 532 mp_digit rem;
michael@0 533 int pow;
michael@0 534
michael@0 535 ARGCHK(a != NULL, MP_BADARG);
michael@0 536
michael@0 537 if(d == 0)
michael@0 538 return MP_RANGE;
michael@0 539
michael@0 540 /* Shortcut for powers of two ... */
michael@0 541 if((pow = s_mp_ispow2d(d)) >= 0) {
michael@0 542 mp_digit mask;
michael@0 543
michael@0 544 mask = ((mp_digit)1 << pow) - 1;
michael@0 545 rem = DIGIT(a, 0) & mask;
michael@0 546
michael@0 547 if(q) {
michael@0 548 mp_copy(a, q);
michael@0 549 s_mp_div_2d(q, pow);
michael@0 550 }
michael@0 551
michael@0 552 if(r)
michael@0 553 *r = rem;
michael@0 554
michael@0 555 return MP_OKAY;
michael@0 556 }
michael@0 557
michael@0 558 if((res = mp_init_copy(&qp, a)) != MP_OKAY)
michael@0 559 return res;
michael@0 560
michael@0 561 res = s_mp_div_d(&qp, d, &rem);
michael@0 562
michael@0 563 if(s_mp_cmp_d(&qp, 0) == 0)
michael@0 564 SIGN(q) = ZPOS;
michael@0 565
michael@0 566 if(r)
michael@0 567 *r = rem;
michael@0 568
michael@0 569 if(q)
michael@0 570 s_mp_exch(&qp, q);
michael@0 571
michael@0 572 mp_clear(&qp);
michael@0 573 return res;
michael@0 574
michael@0 575 } /* end mp_div_d() */
michael@0 576
michael@0 577 /* }}} */
michael@0 578
michael@0 579 /* {{{ mp_div_2(a, c) */
michael@0 580
michael@0 581 /*
michael@0 582 mp_div_2(a, c)
michael@0 583
michael@0 584 Compute c = a / 2, disregarding the remainder.
michael@0 585 */
michael@0 586
michael@0 587 mp_err mp_div_2(const mp_int *a, mp_int *c)
michael@0 588 {
michael@0 589 mp_err res;
michael@0 590
michael@0 591 ARGCHK(a != NULL && c != NULL, MP_BADARG);
michael@0 592
michael@0 593 if((res = mp_copy(a, c)) != MP_OKAY)
michael@0 594 return res;
michael@0 595
michael@0 596 s_mp_div_2(c);
michael@0 597
michael@0 598 return MP_OKAY;
michael@0 599
michael@0 600 } /* end mp_div_2() */
michael@0 601
michael@0 602 /* }}} */
michael@0 603
michael@0 604 /* {{{ mp_expt_d(a, d, b) */
michael@0 605
michael@0 606 mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c)
michael@0 607 {
michael@0 608 mp_int s, x;
michael@0 609 mp_err res;
michael@0 610
michael@0 611 ARGCHK(a != NULL && c != NULL, MP_BADARG);
michael@0 612
michael@0 613 if((res = mp_init(&s)) != MP_OKAY)
michael@0 614 return res;
michael@0 615 if((res = mp_init_copy(&x, a)) != MP_OKAY)
michael@0 616 goto X;
michael@0 617
michael@0 618 DIGIT(&s, 0) = 1;
michael@0 619
michael@0 620 while(d != 0) {
michael@0 621 if(d & 1) {
michael@0 622 if((res = s_mp_mul(&s, &x)) != MP_OKAY)
michael@0 623 goto CLEANUP;
michael@0 624 }
michael@0 625
michael@0 626 d /= 2;
michael@0 627
michael@0 628 if((res = s_mp_sqr(&x)) != MP_OKAY)
michael@0 629 goto CLEANUP;
michael@0 630 }
michael@0 631
michael@0 632 s_mp_exch(&s, c);
michael@0 633
michael@0 634 CLEANUP:
michael@0 635 mp_clear(&x);
michael@0 636 X:
michael@0 637 mp_clear(&s);
michael@0 638
michael@0 639 return res;
michael@0 640
michael@0 641 } /* end mp_expt_d() */
michael@0 642
michael@0 643 /* }}} */
michael@0 644
michael@0 645 /* }}} */
michael@0 646
michael@0 647 /*------------------------------------------------------------------------*/
michael@0 648 /* {{{ Full arithmetic */
michael@0 649
michael@0 650 /* {{{ mp_abs(a, b) */
michael@0 651
michael@0 652 /*
michael@0 653 mp_abs(a, b)
michael@0 654
michael@0 655 Compute b = |a|. 'a' and 'b' may be identical.
michael@0 656 */
michael@0 657
michael@0 658 mp_err mp_abs(const mp_int *a, mp_int *b)
michael@0 659 {
michael@0 660 mp_err res;
michael@0 661
michael@0 662 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 663
michael@0 664 if((res = mp_copy(a, b)) != MP_OKAY)
michael@0 665 return res;
michael@0 666
michael@0 667 SIGN(b) = ZPOS;
michael@0 668
michael@0 669 return MP_OKAY;
michael@0 670
michael@0 671 } /* end mp_abs() */
michael@0 672
michael@0 673 /* }}} */
michael@0 674
michael@0 675 /* {{{ mp_neg(a, b) */
michael@0 676
michael@0 677 /*
michael@0 678 mp_neg(a, b)
michael@0 679
michael@0 680 Compute b = -a. 'a' and 'b' may be identical.
michael@0 681 */
michael@0 682
michael@0 683 mp_err mp_neg(const mp_int *a, mp_int *b)
michael@0 684 {
michael@0 685 mp_err res;
michael@0 686
michael@0 687 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 688
michael@0 689 if((res = mp_copy(a, b)) != MP_OKAY)
michael@0 690 return res;
michael@0 691
michael@0 692 if(s_mp_cmp_d(b, 0) == MP_EQ)
michael@0 693 SIGN(b) = ZPOS;
michael@0 694 else
michael@0 695 SIGN(b) = (SIGN(b) == NEG) ? ZPOS : NEG;
michael@0 696
michael@0 697 return MP_OKAY;
michael@0 698
michael@0 699 } /* end mp_neg() */
michael@0 700
michael@0 701 /* }}} */
michael@0 702
michael@0 703 /* {{{ mp_add(a, b, c) */
michael@0 704
michael@0 705 /*
michael@0 706 mp_add(a, b, c)
michael@0 707
michael@0 708 Compute c = a + b. All parameters may be identical.
michael@0 709 */
michael@0 710
michael@0 711 mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c)
michael@0 712 {
michael@0 713 mp_err res;
michael@0 714
michael@0 715 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 716
michael@0 717 if(SIGN(a) == SIGN(b)) { /* same sign: add values, keep sign */
michael@0 718 MP_CHECKOK( s_mp_add_3arg(a, b, c) );
michael@0 719 } else if(s_mp_cmp(a, b) >= 0) { /* different sign: |a| >= |b| */
michael@0 720 MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
michael@0 721 } else { /* different sign: |a| < |b| */
michael@0 722 MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
michael@0 723 }
michael@0 724
michael@0 725 if (s_mp_cmp_d(c, 0) == MP_EQ)
michael@0 726 SIGN(c) = ZPOS;
michael@0 727
michael@0 728 CLEANUP:
michael@0 729 return res;
michael@0 730
michael@0 731 } /* end mp_add() */
michael@0 732
michael@0 733 /* }}} */
michael@0 734
michael@0 735 /* {{{ mp_sub(a, b, c) */
michael@0 736
michael@0 737 /*
michael@0 738 mp_sub(a, b, c)
michael@0 739
michael@0 740 Compute c = a - b. All parameters may be identical.
michael@0 741 */
michael@0 742
michael@0 743 mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
michael@0 744 {
michael@0 745 mp_err res;
michael@0 746 int magDiff;
michael@0 747
michael@0 748 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 749
michael@0 750 if (a == b) {
michael@0 751 mp_zero(c);
michael@0 752 return MP_OKAY;
michael@0 753 }
michael@0 754
michael@0 755 if (MP_SIGN(a) != MP_SIGN(b)) {
michael@0 756 MP_CHECKOK( s_mp_add_3arg(a, b, c) );
michael@0 757 } else if (!(magDiff = s_mp_cmp(a, b))) {
michael@0 758 mp_zero(c);
michael@0 759 res = MP_OKAY;
michael@0 760 } else if (magDiff > 0) {
michael@0 761 MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
michael@0 762 } else {
michael@0 763 MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
michael@0 764 MP_SIGN(c) = !MP_SIGN(a);
michael@0 765 }
michael@0 766
michael@0 767 if (s_mp_cmp_d(c, 0) == MP_EQ)
michael@0 768 MP_SIGN(c) = MP_ZPOS;
michael@0 769
michael@0 770 CLEANUP:
michael@0 771 return res;
michael@0 772
michael@0 773 } /* end mp_sub() */
michael@0 774
michael@0 775 /* }}} */
michael@0 776
michael@0 777 /* {{{ mp_mul(a, b, c) */
michael@0 778
michael@0 779 /*
michael@0 780 mp_mul(a, b, c)
michael@0 781
michael@0 782 Compute c = a * b. All parameters may be identical.
michael@0 783 */
michael@0 784 mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int * c)
michael@0 785 {
michael@0 786 mp_digit *pb;
michael@0 787 mp_int tmp;
michael@0 788 mp_err res;
michael@0 789 mp_size ib;
michael@0 790 mp_size useda, usedb;
michael@0 791
michael@0 792 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 793
michael@0 794 if (a == c) {
michael@0 795 if ((res = mp_init_copy(&tmp, a)) != MP_OKAY)
michael@0 796 return res;
michael@0 797 if (a == b)
michael@0 798 b = &tmp;
michael@0 799 a = &tmp;
michael@0 800 } else if (b == c) {
michael@0 801 if ((res = mp_init_copy(&tmp, b)) != MP_OKAY)
michael@0 802 return res;
michael@0 803 b = &tmp;
michael@0 804 } else {
michael@0 805 MP_DIGITS(&tmp) = 0;
michael@0 806 }
michael@0 807
michael@0 808 if (MP_USED(a) < MP_USED(b)) {
michael@0 809 const mp_int *xch = b; /* switch a and b, to do fewer outer loops */
michael@0 810 b = a;
michael@0 811 a = xch;
michael@0 812 }
michael@0 813
michael@0 814 MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
michael@0 815 if((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY)
michael@0 816 goto CLEANUP;
michael@0 817
michael@0 818 #ifdef NSS_USE_COMBA
michael@0 819 if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
michael@0 820 if (MP_USED(a) == 4) {
michael@0 821 s_mp_mul_comba_4(a, b, c);
michael@0 822 goto CLEANUP;
michael@0 823 }
michael@0 824 if (MP_USED(a) == 8) {
michael@0 825 s_mp_mul_comba_8(a, b, c);
michael@0 826 goto CLEANUP;
michael@0 827 }
michael@0 828 if (MP_USED(a) == 16) {
michael@0 829 s_mp_mul_comba_16(a, b, c);
michael@0 830 goto CLEANUP;
michael@0 831 }
michael@0 832 if (MP_USED(a) == 32) {
michael@0 833 s_mp_mul_comba_32(a, b, c);
michael@0 834 goto CLEANUP;
michael@0 835 }
michael@0 836 }
michael@0 837 #endif
michael@0 838
michael@0 839 pb = MP_DIGITS(b);
michael@0 840 s_mpv_mul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
michael@0 841
michael@0 842 /* Outer loop: Digits of b */
michael@0 843 useda = MP_USED(a);
michael@0 844 usedb = MP_USED(b);
michael@0 845 for (ib = 1; ib < usedb; ib++) {
michael@0 846 mp_digit b_i = *pb++;
michael@0 847
michael@0 848 /* Inner product: Digits of a */
michael@0 849 if (b_i)
michael@0 850 s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
michael@0 851 else
michael@0 852 MP_DIGIT(c, ib + useda) = b_i;
michael@0 853 }
michael@0 854
michael@0 855 s_mp_clamp(c);
michael@0 856
michael@0 857 if(SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ)
michael@0 858 SIGN(c) = ZPOS;
michael@0 859 else
michael@0 860 SIGN(c) = NEG;
michael@0 861
michael@0 862 CLEANUP:
michael@0 863 mp_clear(&tmp);
michael@0 864 return res;
michael@0 865 } /* end mp_mul() */
michael@0 866
michael@0 867 /* }}} */
michael@0 868
michael@0 869 /* {{{ mp_sqr(a, sqr) */
michael@0 870
michael@0 871 #if MP_SQUARE
michael@0 872 /*
michael@0 873 Computes the square of a. This can be done more
michael@0 874 efficiently than a general multiplication, because many of the
michael@0 875 computation steps are redundant when squaring. The inner product
michael@0 876 step is a bit more complicated, but we save a fair number of
michael@0 877 iterations of the multiplication loop.
michael@0 878 */
michael@0 879
michael@0 880 /* sqr = a^2; Caller provides both a and tmp; */
michael@0 881 mp_err mp_sqr(const mp_int *a, mp_int *sqr)
michael@0 882 {
michael@0 883 mp_digit *pa;
michael@0 884 mp_digit d;
michael@0 885 mp_err res;
michael@0 886 mp_size ix;
michael@0 887 mp_int tmp;
michael@0 888 int count;
michael@0 889
michael@0 890 ARGCHK(a != NULL && sqr != NULL, MP_BADARG);
michael@0 891
michael@0 892 if (a == sqr) {
michael@0 893 if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
michael@0 894 return res;
michael@0 895 a = &tmp;
michael@0 896 } else {
michael@0 897 DIGITS(&tmp) = 0;
michael@0 898 res = MP_OKAY;
michael@0 899 }
michael@0 900
michael@0 901 ix = 2 * MP_USED(a);
michael@0 902 if (ix > MP_ALLOC(sqr)) {
michael@0 903 MP_USED(sqr) = 1;
michael@0 904 MP_CHECKOK( s_mp_grow(sqr, ix) );
michael@0 905 }
michael@0 906 MP_USED(sqr) = ix;
michael@0 907 MP_DIGIT(sqr, 0) = 0;
michael@0 908
michael@0 909 #ifdef NSS_USE_COMBA
michael@0 910 if (IS_POWER_OF_2(MP_USED(a))) {
michael@0 911 if (MP_USED(a) == 4) {
michael@0 912 s_mp_sqr_comba_4(a, sqr);
michael@0 913 goto CLEANUP;
michael@0 914 }
michael@0 915 if (MP_USED(a) == 8) {
michael@0 916 s_mp_sqr_comba_8(a, sqr);
michael@0 917 goto CLEANUP;
michael@0 918 }
michael@0 919 if (MP_USED(a) == 16) {
michael@0 920 s_mp_sqr_comba_16(a, sqr);
michael@0 921 goto CLEANUP;
michael@0 922 }
michael@0 923 if (MP_USED(a) == 32) {
michael@0 924 s_mp_sqr_comba_32(a, sqr);
michael@0 925 goto CLEANUP;
michael@0 926 }
michael@0 927 }
michael@0 928 #endif
michael@0 929
michael@0 930 pa = MP_DIGITS(a);
michael@0 931 count = MP_USED(a) - 1;
michael@0 932 if (count > 0) {
michael@0 933 d = *pa++;
michael@0 934 s_mpv_mul_d(pa, count, d, MP_DIGITS(sqr) + 1);
michael@0 935 for (ix = 3; --count > 0; ix += 2) {
michael@0 936 d = *pa++;
michael@0 937 s_mpv_mul_d_add(pa, count, d, MP_DIGITS(sqr) + ix);
michael@0 938 } /* for(ix ...) */
michael@0 939 MP_DIGIT(sqr, MP_USED(sqr)-1) = 0; /* above loop stopped short of this. */
michael@0 940
michael@0 941 /* now sqr *= 2 */
michael@0 942 s_mp_mul_2(sqr);
michael@0 943 } else {
michael@0 944 MP_DIGIT(sqr, 1) = 0;
michael@0 945 }
michael@0 946
michael@0 947 /* now add the squares of the digits of a to sqr. */
michael@0 948 s_mpv_sqr_add_prop(MP_DIGITS(a), MP_USED(a), MP_DIGITS(sqr));
michael@0 949
michael@0 950 SIGN(sqr) = ZPOS;
michael@0 951 s_mp_clamp(sqr);
michael@0 952
michael@0 953 CLEANUP:
michael@0 954 mp_clear(&tmp);
michael@0 955 return res;
michael@0 956
michael@0 957 } /* end mp_sqr() */
michael@0 958 #endif
michael@0 959
michael@0 960 /* }}} */
michael@0 961
michael@0 962 /* {{{ mp_div(a, b, q, r) */
michael@0 963
michael@0 964 /*
michael@0 965 mp_div(a, b, q, r)
michael@0 966
michael@0 967 Compute q = a / b and r = a mod b. Input parameters may be re-used
michael@0 968 as output parameters. If q or r is NULL, that portion of the
michael@0 969 computation will be discarded (although it will still be computed)
michael@0 970 */
michael@0 971 mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r)
michael@0 972 {
michael@0 973 mp_err res;
michael@0 974 mp_int *pQ, *pR;
michael@0 975 mp_int qtmp, rtmp, btmp;
michael@0 976 int cmp;
michael@0 977 mp_sign signA;
michael@0 978 mp_sign signB;
michael@0 979
michael@0 980 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 981
michael@0 982 signA = MP_SIGN(a);
michael@0 983 signB = MP_SIGN(b);
michael@0 984
michael@0 985 if(mp_cmp_z(b) == MP_EQ)
michael@0 986 return MP_RANGE;
michael@0 987
michael@0 988 DIGITS(&qtmp) = 0;
michael@0 989 DIGITS(&rtmp) = 0;
michael@0 990 DIGITS(&btmp) = 0;
michael@0 991
michael@0 992 /* Set up some temporaries... */
michael@0 993 if (!r || r == a || r == b) {
michael@0 994 MP_CHECKOK( mp_init_copy(&rtmp, a) );
michael@0 995 pR = &rtmp;
michael@0 996 } else {
michael@0 997 MP_CHECKOK( mp_copy(a, r) );
michael@0 998 pR = r;
michael@0 999 }
michael@0 1000
michael@0 1001 if (!q || q == a || q == b) {
michael@0 1002 MP_CHECKOK( mp_init_size(&qtmp, MP_USED(a)) );
michael@0 1003 pQ = &qtmp;
michael@0 1004 } else {
michael@0 1005 MP_CHECKOK( s_mp_pad(q, MP_USED(a)) );
michael@0 1006 pQ = q;
michael@0 1007 mp_zero(pQ);
michael@0 1008 }
michael@0 1009
michael@0 1010 /*
michael@0 1011 If |a| <= |b|, we can compute the solution without division;
michael@0 1012 otherwise, we actually do the work required.
michael@0 1013 */
michael@0 1014 if ((cmp = s_mp_cmp(a, b)) <= 0) {
michael@0 1015 if (cmp) {
michael@0 1016 /* r was set to a above. */
michael@0 1017 mp_zero(pQ);
michael@0 1018 } else {
michael@0 1019 mp_set(pQ, 1);
michael@0 1020 mp_zero(pR);
michael@0 1021 }
michael@0 1022 } else {
michael@0 1023 MP_CHECKOK( mp_init_copy(&btmp, b) );
michael@0 1024 MP_CHECKOK( s_mp_div(pR, &btmp, pQ) );
michael@0 1025 }
michael@0 1026
michael@0 1027 /* Compute the signs for the output */
michael@0 1028 MP_SIGN(pR) = signA; /* Sr = Sa */
michael@0 1029 /* Sq = ZPOS if Sa == Sb */ /* Sq = NEG if Sa != Sb */
michael@0 1030 MP_SIGN(pQ) = (signA == signB) ? ZPOS : NEG;
michael@0 1031
michael@0 1032 if(s_mp_cmp_d(pQ, 0) == MP_EQ)
michael@0 1033 SIGN(pQ) = ZPOS;
michael@0 1034 if(s_mp_cmp_d(pR, 0) == MP_EQ)
michael@0 1035 SIGN(pR) = ZPOS;
michael@0 1036
michael@0 1037 /* Copy output, if it is needed */
michael@0 1038 if(q && q != pQ)
michael@0 1039 s_mp_exch(pQ, q);
michael@0 1040
michael@0 1041 if(r && r != pR)
michael@0 1042 s_mp_exch(pR, r);
michael@0 1043
michael@0 1044 CLEANUP:
michael@0 1045 mp_clear(&btmp);
michael@0 1046 mp_clear(&rtmp);
michael@0 1047 mp_clear(&qtmp);
michael@0 1048
michael@0 1049 return res;
michael@0 1050
michael@0 1051 } /* end mp_div() */
michael@0 1052
michael@0 1053 /* }}} */
michael@0 1054
michael@0 1055 /* {{{ mp_div_2d(a, d, q, r) */
michael@0 1056
michael@0 1057 mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r)
michael@0 1058 {
michael@0 1059 mp_err res;
michael@0 1060
michael@0 1061 ARGCHK(a != NULL, MP_BADARG);
michael@0 1062
michael@0 1063 if(q) {
michael@0 1064 if((res = mp_copy(a, q)) != MP_OKAY)
michael@0 1065 return res;
michael@0 1066 }
michael@0 1067 if(r) {
michael@0 1068 if((res = mp_copy(a, r)) != MP_OKAY)
michael@0 1069 return res;
michael@0 1070 }
michael@0 1071 if(q) {
michael@0 1072 s_mp_div_2d(q, d);
michael@0 1073 }
michael@0 1074 if(r) {
michael@0 1075 s_mp_mod_2d(r, d);
michael@0 1076 }
michael@0 1077
michael@0 1078 return MP_OKAY;
michael@0 1079
michael@0 1080 } /* end mp_div_2d() */
michael@0 1081
michael@0 1082 /* }}} */
michael@0 1083
michael@0 1084 /* {{{ mp_expt(a, b, c) */
michael@0 1085
michael@0 1086 /*
michael@0 1087 mp_expt(a, b, c)
michael@0 1088
michael@0 1089 Compute c = a ** b, that is, raise a to the b power. Uses a
michael@0 1090 standard iterative square-and-multiply technique.
michael@0 1091 */
michael@0 1092
michael@0 1093 mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
michael@0 1094 {
michael@0 1095 mp_int s, x;
michael@0 1096 mp_err res;
michael@0 1097 mp_digit d;
michael@0 1098 int dig, bit;
michael@0 1099
michael@0 1100 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 1101
michael@0 1102 if(mp_cmp_z(b) < 0)
michael@0 1103 return MP_RANGE;
michael@0 1104
michael@0 1105 if((res = mp_init(&s)) != MP_OKAY)
michael@0 1106 return res;
michael@0 1107
michael@0 1108 mp_set(&s, 1);
michael@0 1109
michael@0 1110 if((res = mp_init_copy(&x, a)) != MP_OKAY)
michael@0 1111 goto X;
michael@0 1112
michael@0 1113 /* Loop over low-order digits in ascending order */
michael@0 1114 for(dig = 0; dig < (USED(b) - 1); dig++) {
michael@0 1115 d = DIGIT(b, dig);
michael@0 1116
michael@0 1117 /* Loop over bits of each non-maximal digit */
michael@0 1118 for(bit = 0; bit < DIGIT_BIT; bit++) {
michael@0 1119 if(d & 1) {
michael@0 1120 if((res = s_mp_mul(&s, &x)) != MP_OKAY)
michael@0 1121 goto CLEANUP;
michael@0 1122 }
michael@0 1123
michael@0 1124 d >>= 1;
michael@0 1125
michael@0 1126 if((res = s_mp_sqr(&x)) != MP_OKAY)
michael@0 1127 goto CLEANUP;
michael@0 1128 }
michael@0 1129 }
michael@0 1130
michael@0 1131 /* Consider now the last digit... */
michael@0 1132 d = DIGIT(b, dig);
michael@0 1133
michael@0 1134 while(d) {
michael@0 1135 if(d & 1) {
michael@0 1136 if((res = s_mp_mul(&s, &x)) != MP_OKAY)
michael@0 1137 goto CLEANUP;
michael@0 1138 }
michael@0 1139
michael@0 1140 d >>= 1;
michael@0 1141
michael@0 1142 if((res = s_mp_sqr(&x)) != MP_OKAY)
michael@0 1143 goto CLEANUP;
michael@0 1144 }
michael@0 1145
michael@0 1146 if(mp_iseven(b))
michael@0 1147 SIGN(&s) = SIGN(a);
michael@0 1148
michael@0 1149 res = mp_copy(&s, c);
michael@0 1150
michael@0 1151 CLEANUP:
michael@0 1152 mp_clear(&x);
michael@0 1153 X:
michael@0 1154 mp_clear(&s);
michael@0 1155
michael@0 1156 return res;
michael@0 1157
michael@0 1158 } /* end mp_expt() */
michael@0 1159
michael@0 1160 /* }}} */
michael@0 1161
michael@0 1162 /* {{{ mp_2expt(a, k) */
michael@0 1163
michael@0 1164 /* Compute a = 2^k */
michael@0 1165
michael@0 1166 mp_err mp_2expt(mp_int *a, mp_digit k)
michael@0 1167 {
michael@0 1168 ARGCHK(a != NULL, MP_BADARG);
michael@0 1169
michael@0 1170 return s_mp_2expt(a, k);
michael@0 1171
michael@0 1172 } /* end mp_2expt() */
michael@0 1173
michael@0 1174 /* }}} */
michael@0 1175
michael@0 1176 /* {{{ mp_mod(a, m, c) */
michael@0 1177
michael@0 1178 /*
michael@0 1179 mp_mod(a, m, c)
michael@0 1180
michael@0 1181 Compute c = a (mod m). Result will always be 0 <= c < m.
michael@0 1182 */
michael@0 1183
michael@0 1184 mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c)
michael@0 1185 {
michael@0 1186 mp_err res;
michael@0 1187 int mag;
michael@0 1188
michael@0 1189 ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
michael@0 1190
michael@0 1191 if(SIGN(m) == NEG)
michael@0 1192 return MP_RANGE;
michael@0 1193
michael@0 1194 /*
michael@0 1195 If |a| > m, we need to divide to get the remainder and take the
michael@0 1196 absolute value.
michael@0 1197
michael@0 1198 If |a| < m, we don't need to do any division, just copy and adjust
michael@0 1199 the sign (if a is negative).
michael@0 1200
michael@0 1201 If |a| == m, we can simply set the result to zero.
michael@0 1202
michael@0 1203 This order is intended to minimize the average path length of the
michael@0 1204 comparison chain on common workloads -- the most frequent cases are
michael@0 1205 that |a| != m, so we do those first.
michael@0 1206 */
michael@0 1207 if((mag = s_mp_cmp(a, m)) > 0) {
michael@0 1208 if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
michael@0 1209 return res;
michael@0 1210
michael@0 1211 if(SIGN(c) == NEG) {
michael@0 1212 if((res = mp_add(c, m, c)) != MP_OKAY)
michael@0 1213 return res;
michael@0 1214 }
michael@0 1215
michael@0 1216 } else if(mag < 0) {
michael@0 1217 if((res = mp_copy(a, c)) != MP_OKAY)
michael@0 1218 return res;
michael@0 1219
michael@0 1220 if(mp_cmp_z(a) < 0) {
michael@0 1221 if((res = mp_add(c, m, c)) != MP_OKAY)
michael@0 1222 return res;
michael@0 1223
michael@0 1224 }
michael@0 1225
michael@0 1226 } else {
michael@0 1227 mp_zero(c);
michael@0 1228
michael@0 1229 }
michael@0 1230
michael@0 1231 return MP_OKAY;
michael@0 1232
michael@0 1233 } /* end mp_mod() */
michael@0 1234
michael@0 1235 /* }}} */
michael@0 1236
michael@0 1237 /* {{{ mp_mod_d(a, d, c) */
michael@0 1238
michael@0 1239 /*
michael@0 1240 mp_mod_d(a, d, c)
michael@0 1241
michael@0 1242 Compute c = a (mod d). Result will always be 0 <= c < d
michael@0 1243 */
michael@0 1244 mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c)
michael@0 1245 {
michael@0 1246 mp_err res;
michael@0 1247 mp_digit rem;
michael@0 1248
michael@0 1249 ARGCHK(a != NULL && c != NULL, MP_BADARG);
michael@0 1250
michael@0 1251 if(s_mp_cmp_d(a, d) > 0) {
michael@0 1252 if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
michael@0 1253 return res;
michael@0 1254
michael@0 1255 } else {
michael@0 1256 if(SIGN(a) == NEG)
michael@0 1257 rem = d - DIGIT(a, 0);
michael@0 1258 else
michael@0 1259 rem = DIGIT(a, 0);
michael@0 1260 }
michael@0 1261
michael@0 1262 if(c)
michael@0 1263 *c = rem;
michael@0 1264
michael@0 1265 return MP_OKAY;
michael@0 1266
michael@0 1267 } /* end mp_mod_d() */
michael@0 1268
michael@0 1269 /* }}} */
michael@0 1270
michael@0 1271 /* {{{ mp_sqrt(a, b) */
michael@0 1272
michael@0 1273 /*
michael@0 1274 mp_sqrt(a, b)
michael@0 1275
michael@0 1276 Compute the integer square root of a, and store the result in b.
michael@0 1277 Uses an integer-arithmetic version of Newton's iterative linear
michael@0 1278 approximation technique to determine this value; the result has the
michael@0 1279 following two properties:
michael@0 1280
michael@0 1281 b^2 <= a
michael@0 1282 (b+1)^2 >= a
michael@0 1283
michael@0 1284 It is a range error to pass a negative value.
michael@0 1285 */
michael@0 1286 mp_err mp_sqrt(const mp_int *a, mp_int *b)
michael@0 1287 {
michael@0 1288 mp_int x, t;
michael@0 1289 mp_err res;
michael@0 1290 mp_size used;
michael@0 1291
michael@0 1292 ARGCHK(a != NULL && b != NULL, MP_BADARG);
michael@0 1293
michael@0 1294 /* Cannot take square root of a negative value */
michael@0 1295 if(SIGN(a) == NEG)
michael@0 1296 return MP_RANGE;
michael@0 1297
michael@0 1298 /* Special cases for zero and one, trivial */
michael@0 1299 if(mp_cmp_d(a, 1) <= 0)
michael@0 1300 return mp_copy(a, b);
michael@0 1301
michael@0 1302 /* Initialize the temporaries we'll use below */
michael@0 1303 if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
michael@0 1304 return res;
michael@0 1305
michael@0 1306 /* Compute an initial guess for the iteration as a itself */
michael@0 1307 if((res = mp_init_copy(&x, a)) != MP_OKAY)
michael@0 1308 goto X;
michael@0 1309
michael@0 1310 used = MP_USED(&x);
michael@0 1311 if (used > 1) {
michael@0 1312 s_mp_rshd(&x, used / 2);
michael@0 1313 }
michael@0 1314
michael@0 1315 for(;;) {
michael@0 1316 /* t = (x * x) - a */
michael@0 1317 mp_copy(&x, &t); /* can't fail, t is big enough for original x */
michael@0 1318 if((res = mp_sqr(&t, &t)) != MP_OKAY ||
michael@0 1319 (res = mp_sub(&t, a, &t)) != MP_OKAY)
michael@0 1320 goto CLEANUP;
michael@0 1321
michael@0 1322 /* t = t / 2x */
michael@0 1323 s_mp_mul_2(&x);
michael@0 1324 if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
michael@0 1325 goto CLEANUP;
michael@0 1326 s_mp_div_2(&x);
michael@0 1327
michael@0 1328 /* Terminate the loop, if the quotient is zero */
michael@0 1329 if(mp_cmp_z(&t) == MP_EQ)
michael@0 1330 break;
michael@0 1331
michael@0 1332 /* x = x - t */
michael@0 1333 if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
michael@0 1334 goto CLEANUP;
michael@0 1335
michael@0 1336 }
michael@0 1337
michael@0 1338 /* Copy result to output parameter */
michael@0 1339 mp_sub_d(&x, 1, &x);
michael@0 1340 s_mp_exch(&x, b);
michael@0 1341
michael@0 1342 CLEANUP:
michael@0 1343 mp_clear(&x);
michael@0 1344 X:
michael@0 1345 mp_clear(&t);
michael@0 1346
michael@0 1347 return res;
michael@0 1348
michael@0 1349 } /* end mp_sqrt() */
michael@0 1350
michael@0 1351 /* }}} */
michael@0 1352
michael@0 1353 /* }}} */
michael@0 1354
michael@0 1355 /*------------------------------------------------------------------------*/
michael@0 1356 /* {{{ Modular arithmetic */
michael@0 1357
michael@0 1358 #if MP_MODARITH
michael@0 1359 /* {{{ mp_addmod(a, b, m, c) */
michael@0 1360
michael@0 1361 /*
michael@0 1362 mp_addmod(a, b, m, c)
michael@0 1363
michael@0 1364 Compute c = (a + b) mod m
michael@0 1365 */
michael@0 1366
michael@0 1367 mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
michael@0 1368 {
michael@0 1369 mp_err res;
michael@0 1370
michael@0 1371 ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
michael@0 1372
michael@0 1373 if((res = mp_add(a, b, c)) != MP_OKAY)
michael@0 1374 return res;
michael@0 1375 if((res = mp_mod(c, m, c)) != MP_OKAY)
michael@0 1376 return res;
michael@0 1377
michael@0 1378 return MP_OKAY;
michael@0 1379
michael@0 1380 }
michael@0 1381
michael@0 1382 /* }}} */
michael@0 1383
michael@0 1384 /* {{{ mp_submod(a, b, m, c) */
michael@0 1385
michael@0 1386 /*
michael@0 1387 mp_submod(a, b, m, c)
michael@0 1388
michael@0 1389 Compute c = (a - b) mod m
michael@0 1390 */
michael@0 1391
michael@0 1392 mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
michael@0 1393 {
michael@0 1394 mp_err res;
michael@0 1395
michael@0 1396 ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
michael@0 1397
michael@0 1398 if((res = mp_sub(a, b, c)) != MP_OKAY)
michael@0 1399 return res;
michael@0 1400 if((res = mp_mod(c, m, c)) != MP_OKAY)
michael@0 1401 return res;
michael@0 1402
michael@0 1403 return MP_OKAY;
michael@0 1404
michael@0 1405 }
michael@0 1406
michael@0 1407 /* }}} */
michael@0 1408
michael@0 1409 /* {{{ mp_mulmod(a, b, m, c) */
michael@0 1410
michael@0 1411 /*
michael@0 1412 mp_mulmod(a, b, m, c)
michael@0 1413
michael@0 1414 Compute c = (a * b) mod m
michael@0 1415 */
michael@0 1416
michael@0 1417 mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
michael@0 1418 {
michael@0 1419 mp_err res;
michael@0 1420
michael@0 1421 ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
michael@0 1422
michael@0 1423 if((res = mp_mul(a, b, c)) != MP_OKAY)
michael@0 1424 return res;
michael@0 1425 if((res = mp_mod(c, m, c)) != MP_OKAY)
michael@0 1426 return res;
michael@0 1427
michael@0 1428 return MP_OKAY;
michael@0 1429
michael@0 1430 }
michael@0 1431
michael@0 1432 /* }}} */
michael@0 1433
michael@0 1434 /* {{{ mp_sqrmod(a, m, c) */
michael@0 1435
michael@0 1436 #if MP_SQUARE
michael@0 1437 mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c)
michael@0 1438 {
michael@0 1439 mp_err res;
michael@0 1440
michael@0 1441 ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
michael@0 1442
michael@0 1443 if((res = mp_sqr(a, c)) != MP_OKAY)
michael@0 1444 return res;
michael@0 1445 if((res = mp_mod(c, m, c)) != MP_OKAY)
michael@0 1446 return res;
michael@0 1447
michael@0 1448 return MP_OKAY;
michael@0 1449
michael@0 1450 } /* end mp_sqrmod() */
michael@0 1451 #endif
michael@0 1452
michael@0 1453 /* }}} */
michael@0 1454
michael@0 1455 /* {{{ s_mp_exptmod(a, b, m, c) */
michael@0 1456
michael@0 1457 /*
michael@0 1458 s_mp_exptmod(a, b, m, c)
michael@0 1459
michael@0 1460 Compute c = (a ** b) mod m. Uses a standard square-and-multiply
michael@0 1461 method with modular reductions at each step. (This is basically the
michael@0 1462 same code as mp_expt(), except for the addition of the reductions)
michael@0 1463
michael@0 1464 The modular reductions are done using Barrett's algorithm (see
michael@0 1465 s_mp_reduce() below for details)
michael@0 1466 */
michael@0 1467
michael@0 1468 mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
michael@0 1469 {
michael@0 1470 mp_int s, x, mu;
michael@0 1471 mp_err res;
michael@0 1472 mp_digit d;
michael@0 1473 int dig, bit;
michael@0 1474
michael@0 1475 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 1476
michael@0 1477 if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
michael@0 1478 return MP_RANGE;
michael@0 1479
michael@0 1480 if((res = mp_init(&s)) != MP_OKAY)
michael@0 1481 return res;
michael@0 1482 if((res = mp_init_copy(&x, a)) != MP_OKAY ||
michael@0 1483 (res = mp_mod(&x, m, &x)) != MP_OKAY)
michael@0 1484 goto X;
michael@0 1485 if((res = mp_init(&mu)) != MP_OKAY)
michael@0 1486 goto MU;
michael@0 1487
michael@0 1488 mp_set(&s, 1);
michael@0 1489
michael@0 1490 /* mu = b^2k / m */
michael@0 1491 s_mp_add_d(&mu, 1);
michael@0 1492 s_mp_lshd(&mu, 2 * USED(m));
michael@0 1493 if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
michael@0 1494 goto CLEANUP;
michael@0 1495
michael@0 1496 /* Loop over digits of b in ascending order, except highest order */
michael@0 1497 for(dig = 0; dig < (USED(b) - 1); dig++) {
michael@0 1498 d = DIGIT(b, dig);
michael@0 1499
michael@0 1500 /* Loop over the bits of the lower-order digits */
michael@0 1501 for(bit = 0; bit < DIGIT_BIT; bit++) {
michael@0 1502 if(d & 1) {
michael@0 1503 if((res = s_mp_mul(&s, &x)) != MP_OKAY)
michael@0 1504 goto CLEANUP;
michael@0 1505 if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
michael@0 1506 goto CLEANUP;
michael@0 1507 }
michael@0 1508
michael@0 1509 d >>= 1;
michael@0 1510
michael@0 1511 if((res = s_mp_sqr(&x)) != MP_OKAY)
michael@0 1512 goto CLEANUP;
michael@0 1513 if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
michael@0 1514 goto CLEANUP;
michael@0 1515 }
michael@0 1516 }
michael@0 1517
michael@0 1518 /* Now do the last digit... */
michael@0 1519 d = DIGIT(b, dig);
michael@0 1520
michael@0 1521 while(d) {
michael@0 1522 if(d & 1) {
michael@0 1523 if((res = s_mp_mul(&s, &x)) != MP_OKAY)
michael@0 1524 goto CLEANUP;
michael@0 1525 if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
michael@0 1526 goto CLEANUP;
michael@0 1527 }
michael@0 1528
michael@0 1529 d >>= 1;
michael@0 1530
michael@0 1531 if((res = s_mp_sqr(&x)) != MP_OKAY)
michael@0 1532 goto CLEANUP;
michael@0 1533 if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
michael@0 1534 goto CLEANUP;
michael@0 1535 }
michael@0 1536
michael@0 1537 s_mp_exch(&s, c);
michael@0 1538
michael@0 1539 CLEANUP:
michael@0 1540 mp_clear(&mu);
michael@0 1541 MU:
michael@0 1542 mp_clear(&x);
michael@0 1543 X:
michael@0 1544 mp_clear(&s);
michael@0 1545
michael@0 1546 return res;
michael@0 1547
michael@0 1548 } /* end s_mp_exptmod() */
michael@0 1549
michael@0 1550 /* }}} */
michael@0 1551
michael@0 1552 /* {{{ mp_exptmod_d(a, d, m, c) */
michael@0 1553
michael@0 1554 mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
michael@0 1555 {
michael@0 1556 mp_int s, x;
michael@0 1557 mp_err res;
michael@0 1558
michael@0 1559 ARGCHK(a != NULL && c != NULL, MP_BADARG);
michael@0 1560
michael@0 1561 if((res = mp_init(&s)) != MP_OKAY)
michael@0 1562 return res;
michael@0 1563 if((res = mp_init_copy(&x, a)) != MP_OKAY)
michael@0 1564 goto X;
michael@0 1565
michael@0 1566 mp_set(&s, 1);
michael@0 1567
michael@0 1568 while(d != 0) {
michael@0 1569 if(d & 1) {
michael@0 1570 if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
michael@0 1571 (res = mp_mod(&s, m, &s)) != MP_OKAY)
michael@0 1572 goto CLEANUP;
michael@0 1573 }
michael@0 1574
michael@0 1575 d /= 2;
michael@0 1576
michael@0 1577 if((res = s_mp_sqr(&x)) != MP_OKAY ||
michael@0 1578 (res = mp_mod(&x, m, &x)) != MP_OKAY)
michael@0 1579 goto CLEANUP;
michael@0 1580 }
michael@0 1581
michael@0 1582 s_mp_exch(&s, c);
michael@0 1583
michael@0 1584 CLEANUP:
michael@0 1585 mp_clear(&x);
michael@0 1586 X:
michael@0 1587 mp_clear(&s);
michael@0 1588
michael@0 1589 return res;
michael@0 1590
michael@0 1591 } /* end mp_exptmod_d() */
michael@0 1592
michael@0 1593 /* }}} */
michael@0 1594 #endif /* if MP_MODARITH */
michael@0 1595
michael@0 1596 /* }}} */
michael@0 1597
michael@0 1598 /*------------------------------------------------------------------------*/
michael@0 1599 /* {{{ Comparison functions */
michael@0 1600
michael@0 1601 /* {{{ mp_cmp_z(a) */
michael@0 1602
michael@0 1603 /*
michael@0 1604 mp_cmp_z(a)
michael@0 1605
michael@0 1606 Compare a <=> 0. Returns <0 if a<0, 0 if a=0, >0 if a>0.
michael@0 1607 */
michael@0 1608
michael@0 1609 int mp_cmp_z(const mp_int *a)
michael@0 1610 {
michael@0 1611 if(SIGN(a) == NEG)
michael@0 1612 return MP_LT;
michael@0 1613 else if(USED(a) == 1 && DIGIT(a, 0) == 0)
michael@0 1614 return MP_EQ;
michael@0 1615 else
michael@0 1616 return MP_GT;
michael@0 1617
michael@0 1618 } /* end mp_cmp_z() */
michael@0 1619
michael@0 1620 /* }}} */
michael@0 1621
michael@0 1622 /* {{{ mp_cmp_d(a, d) */
michael@0 1623
michael@0 1624 /*
michael@0 1625 mp_cmp_d(a, d)
michael@0 1626
michael@0 1627 Compare a <=> d. Returns <0 if a<d, 0 if a=d, >0 if a>d
michael@0 1628 */
michael@0 1629
michael@0 1630 int mp_cmp_d(const mp_int *a, mp_digit d)
michael@0 1631 {
michael@0 1632 ARGCHK(a != NULL, MP_EQ);
michael@0 1633
michael@0 1634 if(SIGN(a) == NEG)
michael@0 1635 return MP_LT;
michael@0 1636
michael@0 1637 return s_mp_cmp_d(a, d);
michael@0 1638
michael@0 1639 } /* end mp_cmp_d() */
michael@0 1640
michael@0 1641 /* }}} */
michael@0 1642
michael@0 1643 /* {{{ mp_cmp(a, b) */
michael@0 1644
michael@0 1645 int mp_cmp(const mp_int *a, const mp_int *b)
michael@0 1646 {
michael@0 1647 ARGCHK(a != NULL && b != NULL, MP_EQ);
michael@0 1648
michael@0 1649 if(SIGN(a) == SIGN(b)) {
michael@0 1650 int mag;
michael@0 1651
michael@0 1652 if((mag = s_mp_cmp(a, b)) == MP_EQ)
michael@0 1653 return MP_EQ;
michael@0 1654
michael@0 1655 if(SIGN(a) == ZPOS)
michael@0 1656 return mag;
michael@0 1657 else
michael@0 1658 return -mag;
michael@0 1659
michael@0 1660 } else if(SIGN(a) == ZPOS) {
michael@0 1661 return MP_GT;
michael@0 1662 } else {
michael@0 1663 return MP_LT;
michael@0 1664 }
michael@0 1665
michael@0 1666 } /* end mp_cmp() */
michael@0 1667
michael@0 1668 /* }}} */
michael@0 1669
michael@0 1670 /* {{{ mp_cmp_mag(a, b) */
michael@0 1671
michael@0 1672 /*
michael@0 1673 mp_cmp_mag(a, b)
michael@0 1674
michael@0 1675 Compares |a| <=> |b|, and returns an appropriate comparison result
michael@0 1676 */
michael@0 1677
michael@0 1678 int mp_cmp_mag(mp_int *a, mp_int *b)
michael@0 1679 {
michael@0 1680 ARGCHK(a != NULL && b != NULL, MP_EQ);
michael@0 1681
michael@0 1682 return s_mp_cmp(a, b);
michael@0 1683
michael@0 1684 } /* end mp_cmp_mag() */
michael@0 1685
michael@0 1686 /* }}} */
michael@0 1687
michael@0 1688 /* {{{ mp_cmp_int(a, z) */
michael@0 1689
michael@0 1690 /*
michael@0 1691 This just converts z to an mp_int, and uses the existing comparison
michael@0 1692 routines. This is sort of inefficient, but it's not clear to me how
michael@0 1693 frequently this wil get used anyway. For small positive constants,
michael@0 1694 you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
michael@0 1695 */
michael@0 1696 int mp_cmp_int(const mp_int *a, long z)
michael@0 1697 {
michael@0 1698 mp_int tmp;
michael@0 1699 int out;
michael@0 1700
michael@0 1701 ARGCHK(a != NULL, MP_EQ);
michael@0 1702
michael@0 1703 mp_init(&tmp); mp_set_int(&tmp, z);
michael@0 1704 out = mp_cmp(a, &tmp);
michael@0 1705 mp_clear(&tmp);
michael@0 1706
michael@0 1707 return out;
michael@0 1708
michael@0 1709 } /* end mp_cmp_int() */
michael@0 1710
michael@0 1711 /* }}} */
michael@0 1712
michael@0 1713 /* {{{ mp_isodd(a) */
michael@0 1714
michael@0 1715 /*
michael@0 1716 mp_isodd(a)
michael@0 1717
michael@0 1718 Returns a true (non-zero) value if a is odd, false (zero) otherwise.
michael@0 1719 */
michael@0 1720 int mp_isodd(const mp_int *a)
michael@0 1721 {
michael@0 1722 ARGCHK(a != NULL, 0);
michael@0 1723
michael@0 1724 return (int)(DIGIT(a, 0) & 1);
michael@0 1725
michael@0 1726 } /* end mp_isodd() */
michael@0 1727
michael@0 1728 /* }}} */
michael@0 1729
michael@0 1730 /* {{{ mp_iseven(a) */
michael@0 1731
michael@0 1732 int mp_iseven(const mp_int *a)
michael@0 1733 {
michael@0 1734 return !mp_isodd(a);
michael@0 1735
michael@0 1736 } /* end mp_iseven() */
michael@0 1737
michael@0 1738 /* }}} */
michael@0 1739
michael@0 1740 /* }}} */
michael@0 1741
michael@0 1742 /*------------------------------------------------------------------------*/
michael@0 1743 /* {{{ Number theoretic functions */
michael@0 1744
michael@0 1745 #if MP_NUMTH
michael@0 1746 /* {{{ mp_gcd(a, b, c) */
michael@0 1747
michael@0 1748 /*
michael@0 1749 Like the old mp_gcd() function, except computes the GCD using the
michael@0 1750 binary algorithm due to Josef Stein in 1961 (via Knuth).
michael@0 1751 */
michael@0 1752 mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
michael@0 1753 {
michael@0 1754 mp_err res;
michael@0 1755 mp_int u, v, t;
michael@0 1756 mp_size k = 0;
michael@0 1757
michael@0 1758 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 1759
michael@0 1760 if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
michael@0 1761 return MP_RANGE;
michael@0 1762 if(mp_cmp_z(a) == MP_EQ) {
michael@0 1763 return mp_copy(b, c);
michael@0 1764 } else if(mp_cmp_z(b) == MP_EQ) {
michael@0 1765 return mp_copy(a, c);
michael@0 1766 }
michael@0 1767
michael@0 1768 if((res = mp_init(&t)) != MP_OKAY)
michael@0 1769 return res;
michael@0 1770 if((res = mp_init_copy(&u, a)) != MP_OKAY)
michael@0 1771 goto U;
michael@0 1772 if((res = mp_init_copy(&v, b)) != MP_OKAY)
michael@0 1773 goto V;
michael@0 1774
michael@0 1775 SIGN(&u) = ZPOS;
michael@0 1776 SIGN(&v) = ZPOS;
michael@0 1777
michael@0 1778 /* Divide out common factors of 2 until at least 1 of a, b is even */
michael@0 1779 while(mp_iseven(&u) && mp_iseven(&v)) {
michael@0 1780 s_mp_div_2(&u);
michael@0 1781 s_mp_div_2(&v);
michael@0 1782 ++k;
michael@0 1783 }
michael@0 1784
michael@0 1785 /* Initialize t */
michael@0 1786 if(mp_isodd(&u)) {
michael@0 1787 if((res = mp_copy(&v, &t)) != MP_OKAY)
michael@0 1788 goto CLEANUP;
michael@0 1789
michael@0 1790 /* t = -v */
michael@0 1791 if(SIGN(&v) == ZPOS)
michael@0 1792 SIGN(&t) = NEG;
michael@0 1793 else
michael@0 1794 SIGN(&t) = ZPOS;
michael@0 1795
michael@0 1796 } else {
michael@0 1797 if((res = mp_copy(&u, &t)) != MP_OKAY)
michael@0 1798 goto CLEANUP;
michael@0 1799
michael@0 1800 }
michael@0 1801
michael@0 1802 for(;;) {
michael@0 1803 while(mp_iseven(&t)) {
michael@0 1804 s_mp_div_2(&t);
michael@0 1805 }
michael@0 1806
michael@0 1807 if(mp_cmp_z(&t) == MP_GT) {
michael@0 1808 if((res = mp_copy(&t, &u)) != MP_OKAY)
michael@0 1809 goto CLEANUP;
michael@0 1810
michael@0 1811 } else {
michael@0 1812 if((res = mp_copy(&t, &v)) != MP_OKAY)
michael@0 1813 goto CLEANUP;
michael@0 1814
michael@0 1815 /* v = -t */
michael@0 1816 if(SIGN(&t) == ZPOS)
michael@0 1817 SIGN(&v) = NEG;
michael@0 1818 else
michael@0 1819 SIGN(&v) = ZPOS;
michael@0 1820 }
michael@0 1821
michael@0 1822 if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
michael@0 1823 goto CLEANUP;
michael@0 1824
michael@0 1825 if(s_mp_cmp_d(&t, 0) == MP_EQ)
michael@0 1826 break;
michael@0 1827 }
michael@0 1828
michael@0 1829 s_mp_2expt(&v, k); /* v = 2^k */
michael@0 1830 res = mp_mul(&u, &v, c); /* c = u * v */
michael@0 1831
michael@0 1832 CLEANUP:
michael@0 1833 mp_clear(&v);
michael@0 1834 V:
michael@0 1835 mp_clear(&u);
michael@0 1836 U:
michael@0 1837 mp_clear(&t);
michael@0 1838
michael@0 1839 return res;
michael@0 1840
michael@0 1841 } /* end mp_gcd() */
michael@0 1842
michael@0 1843 /* }}} */
michael@0 1844
michael@0 1845 /* {{{ mp_lcm(a, b, c) */
michael@0 1846
michael@0 1847 /* We compute the least common multiple using the rule:
michael@0 1848
michael@0 1849 ab = [a, b](a, b)
michael@0 1850
michael@0 1851 ... by computing the product, and dividing out the gcd.
michael@0 1852 */
michael@0 1853
michael@0 1854 mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
michael@0 1855 {
michael@0 1856 mp_int gcd, prod;
michael@0 1857 mp_err res;
michael@0 1858
michael@0 1859 ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
michael@0 1860
michael@0 1861 /* Set up temporaries */
michael@0 1862 if((res = mp_init(&gcd)) != MP_OKAY)
michael@0 1863 return res;
michael@0 1864 if((res = mp_init(&prod)) != MP_OKAY)
michael@0 1865 goto GCD;
michael@0 1866
michael@0 1867 if((res = mp_mul(a, b, &prod)) != MP_OKAY)
michael@0 1868 goto CLEANUP;
michael@0 1869 if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
michael@0 1870 goto CLEANUP;
michael@0 1871
michael@0 1872 res = mp_div(&prod, &gcd, c, NULL);
michael@0 1873
michael@0 1874 CLEANUP:
michael@0 1875 mp_clear(&prod);
michael@0 1876 GCD:
michael@0 1877 mp_clear(&gcd);
michael@0 1878
michael@0 1879 return res;
michael@0 1880
michael@0 1881 } /* end mp_lcm() */
michael@0 1882
michael@0 1883 /* }}} */
michael@0 1884
michael@0 1885 /* {{{ mp_xgcd(a, b, g, x, y) */
michael@0 1886
michael@0 1887 /*
michael@0 1888 mp_xgcd(a, b, g, x, y)
michael@0 1889
michael@0 1890 Compute g = (a, b) and values x and y satisfying Bezout's identity
michael@0 1891 (that is, ax + by = g). This uses the binary extended GCD algorithm
michael@0 1892 based on the Stein algorithm used for mp_gcd()
michael@0 1893 See algorithm 14.61 in Handbook of Applied Cryptogrpahy.
michael@0 1894 */
michael@0 1895
michael@0 1896 mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y)
michael@0 1897 {
michael@0 1898 mp_int gx, xc, yc, u, v, A, B, C, D;
michael@0 1899 mp_int *clean[9];
michael@0 1900 mp_err res;
michael@0 1901 int last = -1;
michael@0 1902
michael@0 1903 if(mp_cmp_z(b) == 0)
michael@0 1904 return MP_RANGE;
michael@0 1905
michael@0 1906 /* Initialize all these variables we need */
michael@0 1907 MP_CHECKOK( mp_init(&u) );
michael@0 1908 clean[++last] = &u;
michael@0 1909 MP_CHECKOK( mp_init(&v) );
michael@0 1910 clean[++last] = &v;
michael@0 1911 MP_CHECKOK( mp_init(&gx) );
michael@0 1912 clean[++last] = &gx;
michael@0 1913 MP_CHECKOK( mp_init(&A) );
michael@0 1914 clean[++last] = &A;
michael@0 1915 MP_CHECKOK( mp_init(&B) );
michael@0 1916 clean[++last] = &B;
michael@0 1917 MP_CHECKOK( mp_init(&C) );
michael@0 1918 clean[++last] = &C;
michael@0 1919 MP_CHECKOK( mp_init(&D) );
michael@0 1920 clean[++last] = &D;
michael@0 1921 MP_CHECKOK( mp_init_copy(&xc, a) );
michael@0 1922 clean[++last] = &xc;
michael@0 1923 mp_abs(&xc, &xc);
michael@0 1924 MP_CHECKOK( mp_init_copy(&yc, b) );
michael@0 1925 clean[++last] = &yc;
michael@0 1926 mp_abs(&yc, &yc);
michael@0 1927
michael@0 1928 mp_set(&gx, 1);
michael@0 1929
michael@0 1930 /* Divide by two until at least one of them is odd */
michael@0 1931 while(mp_iseven(&xc) && mp_iseven(&yc)) {
michael@0 1932 mp_size nx = mp_trailing_zeros(&xc);
michael@0 1933 mp_size ny = mp_trailing_zeros(&yc);
michael@0 1934 mp_size n = MP_MIN(nx, ny);
michael@0 1935 s_mp_div_2d(&xc,n);
michael@0 1936 s_mp_div_2d(&yc,n);
michael@0 1937 MP_CHECKOK( s_mp_mul_2d(&gx,n) );
michael@0 1938 }
michael@0 1939
michael@0 1940 mp_copy(&xc, &u);
michael@0 1941 mp_copy(&yc, &v);
michael@0 1942 mp_set(&A, 1); mp_set(&D, 1);
michael@0 1943
michael@0 1944 /* Loop through binary GCD algorithm */
michael@0 1945 do {
michael@0 1946 while(mp_iseven(&u)) {
michael@0 1947 s_mp_div_2(&u);
michael@0 1948
michael@0 1949 if(mp_iseven(&A) && mp_iseven(&B)) {
michael@0 1950 s_mp_div_2(&A); s_mp_div_2(&B);
michael@0 1951 } else {
michael@0 1952 MP_CHECKOK( mp_add(&A, &yc, &A) );
michael@0 1953 s_mp_div_2(&A);
michael@0 1954 MP_CHECKOK( mp_sub(&B, &xc, &B) );
michael@0 1955 s_mp_div_2(&B);
michael@0 1956 }
michael@0 1957 }
michael@0 1958
michael@0 1959 while(mp_iseven(&v)) {
michael@0 1960 s_mp_div_2(&v);
michael@0 1961
michael@0 1962 if(mp_iseven(&C) && mp_iseven(&D)) {
michael@0 1963 s_mp_div_2(&C); s_mp_div_2(&D);
michael@0 1964 } else {
michael@0 1965 MP_CHECKOK( mp_add(&C, &yc, &C) );
michael@0 1966 s_mp_div_2(&C);
michael@0 1967 MP_CHECKOK( mp_sub(&D, &xc, &D) );
michael@0 1968 s_mp_div_2(&D);
michael@0 1969 }
michael@0 1970 }
michael@0 1971
michael@0 1972 if(mp_cmp(&u, &v) >= 0) {
michael@0 1973 MP_CHECKOK( mp_sub(&u, &v, &u) );
michael@0 1974 MP_CHECKOK( mp_sub(&A, &C, &A) );
michael@0 1975 MP_CHECKOK( mp_sub(&B, &D, &B) );
michael@0 1976 } else {
michael@0 1977 MP_CHECKOK( mp_sub(&v, &u, &v) );
michael@0 1978 MP_CHECKOK( mp_sub(&C, &A, &C) );
michael@0 1979 MP_CHECKOK( mp_sub(&D, &B, &D) );
michael@0 1980 }
michael@0 1981 } while (mp_cmp_z(&u) != 0);
michael@0 1982
michael@0 1983 /* copy results to output */
michael@0 1984 if(x)
michael@0 1985 MP_CHECKOK( mp_copy(&C, x) );
michael@0 1986
michael@0 1987 if(y)
michael@0 1988 MP_CHECKOK( mp_copy(&D, y) );
michael@0 1989
michael@0 1990 if(g)
michael@0 1991 MP_CHECKOK( mp_mul(&gx, &v, g) );
michael@0 1992
michael@0 1993 CLEANUP:
michael@0 1994 while(last >= 0)
michael@0 1995 mp_clear(clean[last--]);
michael@0 1996
michael@0 1997 return res;
michael@0 1998
michael@0 1999 } /* end mp_xgcd() */
michael@0 2000
michael@0 2001 /* }}} */
michael@0 2002
michael@0 2003 mp_size mp_trailing_zeros(const mp_int *mp)
michael@0 2004 {
michael@0 2005 mp_digit d;
michael@0 2006 mp_size n = 0;
michael@0 2007 int ix;
michael@0 2008
michael@0 2009 if (!mp || !MP_DIGITS(mp) || !mp_cmp_z(mp))
michael@0 2010 return n;
michael@0 2011
michael@0 2012 for (ix = 0; !(d = MP_DIGIT(mp,ix)) && (ix < MP_USED(mp)); ++ix)
michael@0 2013 n += MP_DIGIT_BIT;
michael@0 2014 if (!d)
michael@0 2015 return 0; /* shouldn't happen, but ... */
michael@0 2016 #if !defined(MP_USE_UINT_DIGIT)
michael@0 2017 if (!(d & 0xffffffffU)) {
michael@0 2018 d >>= 32;
michael@0 2019 n += 32;
michael@0 2020 }
michael@0 2021 #endif
michael@0 2022 if (!(d & 0xffffU)) {
michael@0 2023 d >>= 16;
michael@0 2024 n += 16;
michael@0 2025 }
michael@0 2026 if (!(d & 0xffU)) {
michael@0 2027 d >>= 8;
michael@0 2028 n += 8;
michael@0 2029 }
michael@0 2030 if (!(d & 0xfU)) {
michael@0 2031 d >>= 4;
michael@0 2032 n += 4;
michael@0 2033 }
michael@0 2034 if (!(d & 0x3U)) {
michael@0 2035 d >>= 2;
michael@0 2036 n += 2;
michael@0 2037 }
michael@0 2038 if (!(d & 0x1U)) {
michael@0 2039 d >>= 1;
michael@0 2040 n += 1;
michael@0 2041 }
michael@0 2042 #if MP_ARGCHK == 2
michael@0 2043 assert(0 != (d & 1));
michael@0 2044 #endif
michael@0 2045 return n;
michael@0 2046 }
michael@0 2047
michael@0 2048 /* Given a and prime p, computes c and k such that a*c == 2**k (mod p).
michael@0 2049 ** Returns k (positive) or error (negative).
michael@0 2050 ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
michael@0 2051 ** by Richard Schroeppel (a.k.a. Captain Nemo).
michael@0 2052 */
michael@0 2053 mp_err s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
michael@0 2054 {
michael@0 2055 mp_err res;
michael@0 2056 mp_err k = 0;
michael@0 2057 mp_int d, f, g;
michael@0 2058
michael@0 2059 ARGCHK(a && p && c, MP_BADARG);
michael@0 2060
michael@0 2061 MP_DIGITS(&d) = 0;
michael@0 2062 MP_DIGITS(&f) = 0;
michael@0 2063 MP_DIGITS(&g) = 0;
michael@0 2064 MP_CHECKOK( mp_init(&d) );
michael@0 2065 MP_CHECKOK( mp_init_copy(&f, a) ); /* f = a */
michael@0 2066 MP_CHECKOK( mp_init_copy(&g, p) ); /* g = p */
michael@0 2067
michael@0 2068 mp_set(c, 1);
michael@0 2069 mp_zero(&d);
michael@0 2070
michael@0 2071 if (mp_cmp_z(&f) == 0) {
michael@0 2072 res = MP_UNDEF;
michael@0 2073 } else
michael@0 2074 for (;;) {
michael@0 2075 int diff_sign;
michael@0 2076 while (mp_iseven(&f)) {
michael@0 2077 mp_size n = mp_trailing_zeros(&f);
michael@0 2078 if (!n) {
michael@0 2079 res = MP_UNDEF;
michael@0 2080 goto CLEANUP;
michael@0 2081 }
michael@0 2082 s_mp_div_2d(&f, n);
michael@0 2083 MP_CHECKOK( s_mp_mul_2d(&d, n) );
michael@0 2084 k += n;
michael@0 2085 }
michael@0 2086 if (mp_cmp_d(&f, 1) == MP_EQ) { /* f == 1 */
michael@0 2087 res = k;
michael@0 2088 break;
michael@0 2089 }
michael@0 2090 diff_sign = mp_cmp(&f, &g);
michael@0 2091 if (diff_sign < 0) { /* f < g */
michael@0 2092 s_mp_exch(&f, &g);
michael@0 2093 s_mp_exch(c, &d);
michael@0 2094 } else if (diff_sign == 0) { /* f == g */
michael@0 2095 res = MP_UNDEF; /* a and p are not relatively prime */
michael@0 2096 break;
michael@0 2097 }
michael@0 2098 if ((MP_DIGIT(&f,0) % 4) == (MP_DIGIT(&g,0) % 4)) {
michael@0 2099 MP_CHECKOK( mp_sub(&f, &g, &f) ); /* f = f - g */
michael@0 2100 MP_CHECKOK( mp_sub(c, &d, c) ); /* c = c - d */
michael@0 2101 } else {
michael@0 2102 MP_CHECKOK( mp_add(&f, &g, &f) ); /* f = f + g */
michael@0 2103 MP_CHECKOK( mp_add(c, &d, c) ); /* c = c + d */
michael@0 2104 }
michael@0 2105 }
michael@0 2106 if (res >= 0) {
michael@0 2107 while (MP_SIGN(c) != MP_ZPOS) {
michael@0 2108 MP_CHECKOK( mp_add(c, p, c) );
michael@0 2109 }
michael@0 2110 res = k;
michael@0 2111 }
michael@0 2112
michael@0 2113 CLEANUP:
michael@0 2114 mp_clear(&d);
michael@0 2115 mp_clear(&f);
michael@0 2116 mp_clear(&g);
michael@0 2117 return res;
michael@0 2118 }
michael@0 2119
michael@0 2120 /* Compute T = (P ** -1) mod MP_RADIX. Also works for 16-bit mp_digits.
michael@0 2121 ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
michael@0 2122 ** by Richard Schroeppel (a.k.a. Captain Nemo).
michael@0 2123 */
michael@0 2124 mp_digit s_mp_invmod_radix(mp_digit P)
michael@0 2125 {
michael@0 2126 mp_digit T = P;
michael@0 2127 T *= 2 - (P * T);
michael@0 2128 T *= 2 - (P * T);
michael@0 2129 T *= 2 - (P * T);
michael@0 2130 T *= 2 - (P * T);
michael@0 2131 #if !defined(MP_USE_UINT_DIGIT)
michael@0 2132 T *= 2 - (P * T);
michael@0 2133 T *= 2 - (P * T);
michael@0 2134 #endif
michael@0 2135 return T;
michael@0 2136 }
michael@0 2137
michael@0 2138 /* Given c, k, and prime p, where a*c == 2**k (mod p),
michael@0 2139 ** Compute x = (a ** -1) mod p. This is similar to Montgomery reduction.
michael@0 2140 ** This technique from the paper "Fast Modular Reciprocals" (unpublished)
michael@0 2141 ** by Richard Schroeppel (a.k.a. Captain Nemo).
michael@0 2142 */
michael@0 2143 mp_err s_mp_fixup_reciprocal(const mp_int *c, const mp_int *p, int k, mp_int *x)
michael@0 2144 {
michael@0 2145 int k_orig = k;
michael@0 2146 mp_digit r;
michael@0 2147 mp_size ix;
michael@0 2148 mp_err res;
michael@0 2149
michael@0 2150 if (mp_cmp_z(c) < 0) { /* c < 0 */
michael@0 2151 MP_CHECKOK( mp_add(c, p, x) ); /* x = c + p */
michael@0 2152 } else {
michael@0 2153 MP_CHECKOK( mp_copy(c, x) ); /* x = c */
michael@0 2154 }
michael@0 2155
michael@0 2156 /* make sure x is large enough */
michael@0 2157 ix = MP_HOWMANY(k, MP_DIGIT_BIT) + MP_USED(p) + 1;
michael@0 2158 ix = MP_MAX(ix, MP_USED(x));
michael@0 2159 MP_CHECKOK( s_mp_pad(x, ix) );
michael@0 2160
michael@0 2161 r = 0 - s_mp_invmod_radix(MP_DIGIT(p,0));
michael@0 2162
michael@0 2163 for (ix = 0; k > 0; ix++) {
michael@0 2164 int j = MP_MIN(k, MP_DIGIT_BIT);
michael@0 2165 mp_digit v = r * MP_DIGIT(x, ix);
michael@0 2166 if (j < MP_DIGIT_BIT) {
michael@0 2167 v &= ((mp_digit)1 << j) - 1; /* v = v mod (2 ** j) */
michael@0 2168 }
michael@0 2169 s_mp_mul_d_add_offset(p, v, x, ix); /* x += p * v * (RADIX ** ix) */
michael@0 2170 k -= j;
michael@0 2171 }
michael@0 2172 s_mp_clamp(x);
michael@0 2173 s_mp_div_2d(x, k_orig);
michael@0 2174 res = MP_OKAY;
michael@0 2175
michael@0 2176 CLEANUP:
michael@0 2177 return res;
michael@0 2178 }
michael@0 2179
michael@0 2180 /* compute mod inverse using Schroeppel's method, only if m is odd */
michael@0 2181 mp_err s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
michael@0 2182 {
michael@0 2183 int k;
michael@0 2184 mp_err res;
michael@0 2185 mp_int x;
michael@0 2186
michael@0 2187 ARGCHK(a && m && c, MP_BADARG);
michael@0 2188
michael@0 2189 if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
michael@0 2190 return MP_RANGE;
michael@0 2191 if (mp_iseven(m))
michael@0 2192 return MP_UNDEF;
michael@0 2193
michael@0 2194 MP_DIGITS(&x) = 0;
michael@0 2195
michael@0 2196 if (a == c) {
michael@0 2197 if ((res = mp_init_copy(&x, a)) != MP_OKAY)
michael@0 2198 return res;
michael@0 2199 if (a == m)
michael@0 2200 m = &x;
michael@0 2201 a = &x;
michael@0 2202 } else if (m == c) {
michael@0 2203 if ((res = mp_init_copy(&x, m)) != MP_OKAY)
michael@0 2204 return res;
michael@0 2205 m = &x;
michael@0 2206 } else {
michael@0 2207 MP_DIGITS(&x) = 0;
michael@0 2208 }
michael@0 2209
michael@0 2210 MP_CHECKOK( s_mp_almost_inverse(a, m, c) );
michael@0 2211 k = res;
michael@0 2212 MP_CHECKOK( s_mp_fixup_reciprocal(c, m, k, c) );
michael@0 2213 CLEANUP:
michael@0 2214 mp_clear(&x);
michael@0 2215 return res;
michael@0 2216 }
michael@0 2217
michael@0 2218 /* Known good algorithm for computing modular inverse. But slow. */
michael@0 2219 mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
michael@0 2220 {
michael@0 2221 mp_int g, x;
michael@0 2222 mp_err res;
michael@0 2223
michael@0 2224 ARGCHK(a && m && c, MP_BADARG);
michael@0 2225
michael@0 2226 if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
michael@0 2227 return MP_RANGE;
michael@0 2228
michael@0 2229 MP_DIGITS(&g) = 0;
michael@0 2230 MP_DIGITS(&x) = 0;
michael@0 2231 MP_CHECKOK( mp_init(&x) );
michael@0 2232 MP_CHECKOK( mp_init(&g) );
michael@0 2233
michael@0 2234 MP_CHECKOK( mp_xgcd(a, m, &g, &x, NULL) );
michael@0 2235
michael@0 2236 if (mp_cmp_d(&g, 1) != MP_EQ) {
michael@0 2237 res = MP_UNDEF;
michael@0 2238 goto CLEANUP;
michael@0 2239 }
michael@0 2240
michael@0 2241 res = mp_mod(&x, m, c);
michael@0 2242 SIGN(c) = SIGN(a);
michael@0 2243
michael@0 2244 CLEANUP:
michael@0 2245 mp_clear(&x);
michael@0 2246 mp_clear(&g);
michael@0 2247
michael@0 2248 return res;
michael@0 2249 }
michael@0 2250
michael@0 2251 /* modular inverse where modulus is 2**k. */
michael@0 2252 /* c = a**-1 mod 2**k */
michael@0 2253 mp_err s_mp_invmod_2d(const mp_int *a, mp_size k, mp_int *c)
michael@0 2254 {
michael@0 2255 mp_err res;
michael@0 2256 mp_size ix = k + 4;
michael@0 2257 mp_int t0, t1, val, tmp, two2k;
michael@0 2258
michael@0 2259 static const mp_digit d2 = 2;
michael@0 2260 static const mp_int two = { MP_ZPOS, 1, 1, (mp_digit *)&d2 };
michael@0 2261
michael@0 2262 if (mp_iseven(a))
michael@0 2263 return MP_UNDEF;
michael@0 2264 if (k <= MP_DIGIT_BIT) {
michael@0 2265 mp_digit i = s_mp_invmod_radix(MP_DIGIT(a,0));
michael@0 2266 if (k < MP_DIGIT_BIT)
michael@0 2267 i &= ((mp_digit)1 << k) - (mp_digit)1;
michael@0 2268 mp_set(c, i);
michael@0 2269 return MP_OKAY;
michael@0 2270 }
michael@0 2271 MP_DIGITS(&t0) = 0;
michael@0 2272 MP_DIGITS(&t1) = 0;
michael@0 2273 MP_DIGITS(&val) = 0;
michael@0 2274 MP_DIGITS(&tmp) = 0;
michael@0 2275 MP_DIGITS(&two2k) = 0;
michael@0 2276 MP_CHECKOK( mp_init_copy(&val, a) );
michael@0 2277 s_mp_mod_2d(&val, k);
michael@0 2278 MP_CHECKOK( mp_init_copy(&t0, &val) );
michael@0 2279 MP_CHECKOK( mp_init_copy(&t1, &t0) );
michael@0 2280 MP_CHECKOK( mp_init(&tmp) );
michael@0 2281 MP_CHECKOK( mp_init(&two2k) );
michael@0 2282 MP_CHECKOK( s_mp_2expt(&two2k, k) );
michael@0 2283 do {
michael@0 2284 MP_CHECKOK( mp_mul(&val, &t1, &tmp) );
michael@0 2285 MP_CHECKOK( mp_sub(&two, &tmp, &tmp) );
michael@0 2286 MP_CHECKOK( mp_mul(&t1, &tmp, &t1) );
michael@0 2287 s_mp_mod_2d(&t1, k);
michael@0 2288 while (MP_SIGN(&t1) != MP_ZPOS) {
michael@0 2289 MP_CHECKOK( mp_add(&t1, &two2k, &t1) );
michael@0 2290 }
michael@0 2291 if (mp_cmp(&t1, &t0) == MP_EQ)
michael@0 2292 break;
michael@0 2293 MP_CHECKOK( mp_copy(&t1, &t0) );
michael@0 2294 } while (--ix > 0);
michael@0 2295 if (!ix) {
michael@0 2296 res = MP_UNDEF;
michael@0 2297 } else {
michael@0 2298 mp_exch(c, &t1);
michael@0 2299 }
michael@0 2300
michael@0 2301 CLEANUP:
michael@0 2302 mp_clear(&t0);
michael@0 2303 mp_clear(&t1);
michael@0 2304 mp_clear(&val);
michael@0 2305 mp_clear(&tmp);
michael@0 2306 mp_clear(&two2k);
michael@0 2307 return res;
michael@0 2308 }
michael@0 2309
michael@0 2310 mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
michael@0 2311 {
michael@0 2312 mp_err res;
michael@0 2313 mp_size k;
michael@0 2314 mp_int oddFactor, evenFactor; /* factors of the modulus */
michael@0 2315 mp_int oddPart, evenPart; /* parts to combine via CRT. */
michael@0 2316 mp_int C2, tmp1, tmp2;
michael@0 2317
michael@0 2318 /*static const mp_digit d1 = 1; */
michael@0 2319 /*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
michael@0 2320
michael@0 2321 if ((res = s_mp_ispow2(m)) >= 0) {
michael@0 2322 k = res;
michael@0 2323 return s_mp_invmod_2d(a, k, c);
michael@0 2324 }
michael@0 2325 MP_DIGITS(&oddFactor) = 0;
michael@0 2326 MP_DIGITS(&evenFactor) = 0;
michael@0 2327 MP_DIGITS(&oddPart) = 0;
michael@0 2328 MP_DIGITS(&evenPart) = 0;
michael@0 2329 MP_DIGITS(&C2) = 0;
michael@0 2330 MP_DIGITS(&tmp1) = 0;
michael@0 2331 MP_DIGITS(&tmp2) = 0;
michael@0 2332
michael@0 2333 MP_CHECKOK( mp_init_copy(&oddFactor, m) ); /* oddFactor = m */
michael@0 2334 MP_CHECKOK( mp_init(&evenFactor) );
michael@0 2335 MP_CHECKOK( mp_init(&oddPart) );
michael@0 2336 MP_CHECKOK( mp_init(&evenPart) );
michael@0 2337 MP_CHECKOK( mp_init(&C2) );
michael@0 2338 MP_CHECKOK( mp_init(&tmp1) );
michael@0 2339 MP_CHECKOK( mp_init(&tmp2) );
michael@0 2340
michael@0 2341 k = mp_trailing_zeros(m);
michael@0 2342 s_mp_div_2d(&oddFactor, k);
michael@0 2343 MP_CHECKOK( s_mp_2expt(&evenFactor, k) );
michael@0 2344
michael@0 2345 /* compute a**-1 mod oddFactor. */
michael@0 2346 MP_CHECKOK( s_mp_invmod_odd_m(a, &oddFactor, &oddPart) );
michael@0 2347 /* compute a**-1 mod evenFactor, where evenFactor == 2**k. */
michael@0 2348 MP_CHECKOK( s_mp_invmod_2d( a, k, &evenPart) );
michael@0 2349
michael@0 2350 /* Use Chinese Remainer theorem to compute a**-1 mod m. */
michael@0 2351 /* let m1 = oddFactor, v1 = oddPart,
michael@0 2352 * let m2 = evenFactor, v2 = evenPart.
michael@0 2353 */
michael@0 2354
michael@0 2355 /* Compute C2 = m1**-1 mod m2. */
michael@0 2356 MP_CHECKOK( s_mp_invmod_2d(&oddFactor, k, &C2) );
michael@0 2357
michael@0 2358 /* compute u = (v2 - v1)*C2 mod m2 */
michael@0 2359 MP_CHECKOK( mp_sub(&evenPart, &oddPart, &tmp1) );
michael@0 2360 MP_CHECKOK( mp_mul(&tmp1, &C2, &tmp2) );
michael@0 2361 s_mp_mod_2d(&tmp2, k);
michael@0 2362 while (MP_SIGN(&tmp2) != MP_ZPOS) {
michael@0 2363 MP_CHECKOK( mp_add(&tmp2, &evenFactor, &tmp2) );
michael@0 2364 }
michael@0 2365
michael@0 2366 /* compute answer = v1 + u*m1 */
michael@0 2367 MP_CHECKOK( mp_mul(&tmp2, &oddFactor, c) );
michael@0 2368 MP_CHECKOK( mp_add(&oddPart, c, c) );
michael@0 2369 /* not sure this is necessary, but it's low cost if not. */
michael@0 2370 MP_CHECKOK( mp_mod(c, m, c) );
michael@0 2371
michael@0 2372 CLEANUP:
michael@0 2373 mp_clear(&oddFactor);
michael@0 2374 mp_clear(&evenFactor);
michael@0 2375 mp_clear(&oddPart);
michael@0 2376 mp_clear(&evenPart);
michael@0 2377 mp_clear(&C2);
michael@0 2378 mp_clear(&tmp1);
michael@0 2379 mp_clear(&tmp2);
michael@0 2380 return res;
michael@0 2381 }
michael@0 2382
michael@0 2383
michael@0 2384 /* {{{ mp_invmod(a, m, c) */
michael@0 2385
michael@0 2386 /*
michael@0 2387 mp_invmod(a, m, c)
michael@0 2388
michael@0 2389 Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
michael@0 2390 This is equivalent to the question of whether (a, m) = 1. If not,
michael@0 2391 MP_UNDEF is returned, and there is no inverse.
michael@0 2392 */
michael@0 2393
michael@0 2394 mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
michael@0 2395 {
michael@0 2396
michael@0 2397 ARGCHK(a && m && c, MP_BADARG);
michael@0 2398
michael@0 2399 if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
michael@0 2400 return MP_RANGE;
michael@0 2401
michael@0 2402 if (mp_isodd(m)) {
michael@0 2403 return s_mp_invmod_odd_m(a, m, c);
michael@0 2404 }
michael@0 2405 if (mp_iseven(a))
michael@0 2406 return MP_UNDEF; /* not invertable */
michael@0 2407
michael@0 2408 return s_mp_invmod_even_m(a, m, c);
michael@0 2409
michael@0 2410 } /* end mp_invmod() */
michael@0 2411
michael@0 2412 /* }}} */
michael@0 2413 #endif /* if MP_NUMTH */
michael@0 2414
michael@0 2415 /* }}} */
michael@0 2416
michael@0 2417 /*------------------------------------------------------------------------*/
michael@0 2418 /* {{{ mp_print(mp, ofp) */
michael@0 2419
michael@0 2420 #if MP_IOFUNC
michael@0 2421 /*
michael@0 2422 mp_print(mp, ofp)
michael@0 2423
michael@0 2424 Print a textual representation of the given mp_int on the output
michael@0 2425 stream 'ofp'. Output is generated using the internal radix.
michael@0 2426 */
michael@0 2427
michael@0 2428 void mp_print(mp_int *mp, FILE *ofp)
michael@0 2429 {
michael@0 2430 int ix;
michael@0 2431
michael@0 2432 if(mp == NULL || ofp == NULL)
michael@0 2433 return;
michael@0 2434
michael@0 2435 fputc((SIGN(mp) == NEG) ? '-' : '+', ofp);
michael@0 2436
michael@0 2437 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 2438 fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
michael@0 2439 }
michael@0 2440
michael@0 2441 } /* end mp_print() */
michael@0 2442
michael@0 2443 #endif /* if MP_IOFUNC */
michael@0 2444
michael@0 2445 /* }}} */
michael@0 2446
michael@0 2447 /*------------------------------------------------------------------------*/
michael@0 2448 /* {{{ More I/O Functions */
michael@0 2449
michael@0 2450 /* {{{ mp_read_raw(mp, str, len) */
michael@0 2451
michael@0 2452 /*
michael@0 2453 mp_read_raw(mp, str, len)
michael@0 2454
michael@0 2455 Read in a raw value (base 256) into the given mp_int
michael@0 2456 */
michael@0 2457
michael@0 2458 mp_err mp_read_raw(mp_int *mp, char *str, int len)
michael@0 2459 {
michael@0 2460 int ix;
michael@0 2461 mp_err res;
michael@0 2462 unsigned char *ustr = (unsigned char *)str;
michael@0 2463
michael@0 2464 ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
michael@0 2465
michael@0 2466 mp_zero(mp);
michael@0 2467
michael@0 2468 /* Get sign from first byte */
michael@0 2469 if(ustr[0])
michael@0 2470 SIGN(mp) = NEG;
michael@0 2471 else
michael@0 2472 SIGN(mp) = ZPOS;
michael@0 2473
michael@0 2474 /* Read the rest of the digits */
michael@0 2475 for(ix = 1; ix < len; ix++) {
michael@0 2476 if((res = mp_mul_d(mp, 256, mp)) != MP_OKAY)
michael@0 2477 return res;
michael@0 2478 if((res = mp_add_d(mp, ustr[ix], mp)) != MP_OKAY)
michael@0 2479 return res;
michael@0 2480 }
michael@0 2481
michael@0 2482 return MP_OKAY;
michael@0 2483
michael@0 2484 } /* end mp_read_raw() */
michael@0 2485
michael@0 2486 /* }}} */
michael@0 2487
michael@0 2488 /* {{{ mp_raw_size(mp) */
michael@0 2489
michael@0 2490 int mp_raw_size(mp_int *mp)
michael@0 2491 {
michael@0 2492 ARGCHK(mp != NULL, 0);
michael@0 2493
michael@0 2494 return (USED(mp) * sizeof(mp_digit)) + 1;
michael@0 2495
michael@0 2496 } /* end mp_raw_size() */
michael@0 2497
michael@0 2498 /* }}} */
michael@0 2499
michael@0 2500 /* {{{ mp_toraw(mp, str) */
michael@0 2501
michael@0 2502 mp_err mp_toraw(mp_int *mp, char *str)
michael@0 2503 {
michael@0 2504 int ix, jx, pos = 1;
michael@0 2505
michael@0 2506 ARGCHK(mp != NULL && str != NULL, MP_BADARG);
michael@0 2507
michael@0 2508 str[0] = (char)SIGN(mp);
michael@0 2509
michael@0 2510 /* Iterate over each digit... */
michael@0 2511 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 2512 mp_digit d = DIGIT(mp, ix);
michael@0 2513
michael@0 2514 /* Unpack digit bytes, high order first */
michael@0 2515 for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
michael@0 2516 str[pos++] = (char)(d >> (jx * CHAR_BIT));
michael@0 2517 }
michael@0 2518 }
michael@0 2519
michael@0 2520 return MP_OKAY;
michael@0 2521
michael@0 2522 } /* end mp_toraw() */
michael@0 2523
michael@0 2524 /* }}} */
michael@0 2525
michael@0 2526 /* {{{ mp_read_radix(mp, str, radix) */
michael@0 2527
michael@0 2528 /*
michael@0 2529 mp_read_radix(mp, str, radix)
michael@0 2530
michael@0 2531 Read an integer from the given string, and set mp to the resulting
michael@0 2532 value. The input is presumed to be in base 10. Leading non-digit
michael@0 2533 characters are ignored, and the function reads until a non-digit
michael@0 2534 character or the end of the string.
michael@0 2535 */
michael@0 2536
michael@0 2537 mp_err mp_read_radix(mp_int *mp, const char *str, int radix)
michael@0 2538 {
michael@0 2539 int ix = 0, val = 0;
michael@0 2540 mp_err res;
michael@0 2541 mp_sign sig = ZPOS;
michael@0 2542
michael@0 2543 ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX,
michael@0 2544 MP_BADARG);
michael@0 2545
michael@0 2546 mp_zero(mp);
michael@0 2547
michael@0 2548 /* Skip leading non-digit characters until a digit or '-' or '+' */
michael@0 2549 while(str[ix] &&
michael@0 2550 (s_mp_tovalue(str[ix], radix) < 0) &&
michael@0 2551 str[ix] != '-' &&
michael@0 2552 str[ix] != '+') {
michael@0 2553 ++ix;
michael@0 2554 }
michael@0 2555
michael@0 2556 if(str[ix] == '-') {
michael@0 2557 sig = NEG;
michael@0 2558 ++ix;
michael@0 2559 } else if(str[ix] == '+') {
michael@0 2560 sig = ZPOS; /* this is the default anyway... */
michael@0 2561 ++ix;
michael@0 2562 }
michael@0 2563
michael@0 2564 while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
michael@0 2565 if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
michael@0 2566 return res;
michael@0 2567 if((res = s_mp_add_d(mp, val)) != MP_OKAY)
michael@0 2568 return res;
michael@0 2569 ++ix;
michael@0 2570 }
michael@0 2571
michael@0 2572 if(s_mp_cmp_d(mp, 0) == MP_EQ)
michael@0 2573 SIGN(mp) = ZPOS;
michael@0 2574 else
michael@0 2575 SIGN(mp) = sig;
michael@0 2576
michael@0 2577 return MP_OKAY;
michael@0 2578
michael@0 2579 } /* end mp_read_radix() */
michael@0 2580
michael@0 2581 mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix)
michael@0 2582 {
michael@0 2583 int radix = default_radix;
michael@0 2584 int cx;
michael@0 2585 mp_sign sig = ZPOS;
michael@0 2586 mp_err res;
michael@0 2587
michael@0 2588 /* Skip leading non-digit characters until a digit or '-' or '+' */
michael@0 2589 while ((cx = *str) != 0 &&
michael@0 2590 (s_mp_tovalue(cx, radix) < 0) &&
michael@0 2591 cx != '-' &&
michael@0 2592 cx != '+') {
michael@0 2593 ++str;
michael@0 2594 }
michael@0 2595
michael@0 2596 if (cx == '-') {
michael@0 2597 sig = NEG;
michael@0 2598 ++str;
michael@0 2599 } else if (cx == '+') {
michael@0 2600 sig = ZPOS; /* this is the default anyway... */
michael@0 2601 ++str;
michael@0 2602 }
michael@0 2603
michael@0 2604 if (str[0] == '0') {
michael@0 2605 if ((str[1] | 0x20) == 'x') {
michael@0 2606 radix = 16;
michael@0 2607 str += 2;
michael@0 2608 } else {
michael@0 2609 radix = 8;
michael@0 2610 str++;
michael@0 2611 }
michael@0 2612 }
michael@0 2613 res = mp_read_radix(a, str, radix);
michael@0 2614 if (res == MP_OKAY) {
michael@0 2615 MP_SIGN(a) = (s_mp_cmp_d(a, 0) == MP_EQ) ? ZPOS : sig;
michael@0 2616 }
michael@0 2617 return res;
michael@0 2618 }
michael@0 2619
michael@0 2620 /* }}} */
michael@0 2621
michael@0 2622 /* {{{ mp_radix_size(mp, radix) */
michael@0 2623
michael@0 2624 int mp_radix_size(mp_int *mp, int radix)
michael@0 2625 {
michael@0 2626 int bits;
michael@0 2627
michael@0 2628 if(!mp || radix < 2 || radix > MAX_RADIX)
michael@0 2629 return 0;
michael@0 2630
michael@0 2631 bits = USED(mp) * DIGIT_BIT - 1;
michael@0 2632
michael@0 2633 return s_mp_outlen(bits, radix);
michael@0 2634
michael@0 2635 } /* end mp_radix_size() */
michael@0 2636
michael@0 2637 /* }}} */
michael@0 2638
michael@0 2639 /* {{{ mp_toradix(mp, str, radix) */
michael@0 2640
michael@0 2641 mp_err mp_toradix(mp_int *mp, char *str, int radix)
michael@0 2642 {
michael@0 2643 int ix, pos = 0;
michael@0 2644
michael@0 2645 ARGCHK(mp != NULL && str != NULL, MP_BADARG);
michael@0 2646 ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
michael@0 2647
michael@0 2648 if(mp_cmp_z(mp) == MP_EQ) {
michael@0 2649 str[0] = '0';
michael@0 2650 str[1] = '\0';
michael@0 2651 } else {
michael@0 2652 mp_err res;
michael@0 2653 mp_int tmp;
michael@0 2654 mp_sign sgn;
michael@0 2655 mp_digit rem, rdx = (mp_digit)radix;
michael@0 2656 char ch;
michael@0 2657
michael@0 2658 if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
michael@0 2659 return res;
michael@0 2660
michael@0 2661 /* Save sign for later, and take absolute value */
michael@0 2662 sgn = SIGN(&tmp); SIGN(&tmp) = ZPOS;
michael@0 2663
michael@0 2664 /* Generate output digits in reverse order */
michael@0 2665 while(mp_cmp_z(&tmp) != 0) {
michael@0 2666 if((res = mp_div_d(&tmp, rdx, &tmp, &rem)) != MP_OKAY) {
michael@0 2667 mp_clear(&tmp);
michael@0 2668 return res;
michael@0 2669 }
michael@0 2670
michael@0 2671 /* Generate digits, use capital letters */
michael@0 2672 ch = s_mp_todigit(rem, radix, 0);
michael@0 2673
michael@0 2674 str[pos++] = ch;
michael@0 2675 }
michael@0 2676
michael@0 2677 /* Add - sign if original value was negative */
michael@0 2678 if(sgn == NEG)
michael@0 2679 str[pos++] = '-';
michael@0 2680
michael@0 2681 /* Add trailing NUL to end the string */
michael@0 2682 str[pos--] = '\0';
michael@0 2683
michael@0 2684 /* Reverse the digits and sign indicator */
michael@0 2685 ix = 0;
michael@0 2686 while(ix < pos) {
michael@0 2687 char tmp = str[ix];
michael@0 2688
michael@0 2689 str[ix] = str[pos];
michael@0 2690 str[pos] = tmp;
michael@0 2691 ++ix;
michael@0 2692 --pos;
michael@0 2693 }
michael@0 2694
michael@0 2695 mp_clear(&tmp);
michael@0 2696 }
michael@0 2697
michael@0 2698 return MP_OKAY;
michael@0 2699
michael@0 2700 } /* end mp_toradix() */
michael@0 2701
michael@0 2702 /* }}} */
michael@0 2703
michael@0 2704 /* {{{ mp_tovalue(ch, r) */
michael@0 2705
michael@0 2706 int mp_tovalue(char ch, int r)
michael@0 2707 {
michael@0 2708 return s_mp_tovalue(ch, r);
michael@0 2709
michael@0 2710 } /* end mp_tovalue() */
michael@0 2711
michael@0 2712 /* }}} */
michael@0 2713
michael@0 2714 /* }}} */
michael@0 2715
michael@0 2716 /* {{{ mp_strerror(ec) */
michael@0 2717
michael@0 2718 /*
michael@0 2719 mp_strerror(ec)
michael@0 2720
michael@0 2721 Return a string describing the meaning of error code 'ec'. The
michael@0 2722 string returned is allocated in static memory, so the caller should
michael@0 2723 not attempt to modify or free the memory associated with this
michael@0 2724 string.
michael@0 2725 */
michael@0 2726 const char *mp_strerror(mp_err ec)
michael@0 2727 {
michael@0 2728 int aec = (ec < 0) ? -ec : ec;
michael@0 2729
michael@0 2730 /* Code values are negative, so the senses of these comparisons
michael@0 2731 are accurate */
michael@0 2732 if(ec < MP_LAST_CODE || ec > MP_OKAY) {
michael@0 2733 return mp_err_string[0]; /* unknown error code */
michael@0 2734 } else {
michael@0 2735 return mp_err_string[aec + 1];
michael@0 2736 }
michael@0 2737
michael@0 2738 } /* end mp_strerror() */
michael@0 2739
michael@0 2740 /* }}} */
michael@0 2741
michael@0 2742 /*========================================================================*/
michael@0 2743 /*------------------------------------------------------------------------*/
michael@0 2744 /* Static function definitions (internal use only) */
michael@0 2745
michael@0 2746 /* {{{ Memory management */
michael@0 2747
michael@0 2748 /* {{{ s_mp_grow(mp, min) */
michael@0 2749
michael@0 2750 /* Make sure there are at least 'min' digits allocated to mp */
michael@0 2751 mp_err s_mp_grow(mp_int *mp, mp_size min)
michael@0 2752 {
michael@0 2753 if(min > ALLOC(mp)) {
michael@0 2754 mp_digit *tmp;
michael@0 2755
michael@0 2756 /* Set min to next nearest default precision block size */
michael@0 2757 min = MP_ROUNDUP(min, s_mp_defprec);
michael@0 2758
michael@0 2759 if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL)
michael@0 2760 return MP_MEM;
michael@0 2761
michael@0 2762 s_mp_copy(DIGITS(mp), tmp, USED(mp));
michael@0 2763
michael@0 2764 #if MP_CRYPTO
michael@0 2765 s_mp_setz(DIGITS(mp), ALLOC(mp));
michael@0 2766 #endif
michael@0 2767 s_mp_free(DIGITS(mp));
michael@0 2768 DIGITS(mp) = tmp;
michael@0 2769 ALLOC(mp) = min;
michael@0 2770 }
michael@0 2771
michael@0 2772 return MP_OKAY;
michael@0 2773
michael@0 2774 } /* end s_mp_grow() */
michael@0 2775
michael@0 2776 /* }}} */
michael@0 2777
michael@0 2778 /* {{{ s_mp_pad(mp, min) */
michael@0 2779
michael@0 2780 /* Make sure the used size of mp is at least 'min', growing if needed */
michael@0 2781 mp_err s_mp_pad(mp_int *mp, mp_size min)
michael@0 2782 {
michael@0 2783 if(min > USED(mp)) {
michael@0 2784 mp_err res;
michael@0 2785
michael@0 2786 /* Make sure there is room to increase precision */
michael@0 2787 if (min > ALLOC(mp)) {
michael@0 2788 if ((res = s_mp_grow(mp, min)) != MP_OKAY)
michael@0 2789 return res;
michael@0 2790 } else {
michael@0 2791 s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp));
michael@0 2792 }
michael@0 2793
michael@0 2794 /* Increase precision; should already be 0-filled */
michael@0 2795 USED(mp) = min;
michael@0 2796 }
michael@0 2797
michael@0 2798 return MP_OKAY;
michael@0 2799
michael@0 2800 } /* end s_mp_pad() */
michael@0 2801
michael@0 2802 /* }}} */
michael@0 2803
michael@0 2804 /* {{{ s_mp_setz(dp, count) */
michael@0 2805
michael@0 2806 #if MP_MACRO == 0
michael@0 2807 /* Set 'count' digits pointed to by dp to be zeroes */
michael@0 2808 void s_mp_setz(mp_digit *dp, mp_size count)
michael@0 2809 {
michael@0 2810 #if MP_MEMSET == 0
michael@0 2811 int ix;
michael@0 2812
michael@0 2813 for(ix = 0; ix < count; ix++)
michael@0 2814 dp[ix] = 0;
michael@0 2815 #else
michael@0 2816 memset(dp, 0, count * sizeof(mp_digit));
michael@0 2817 #endif
michael@0 2818
michael@0 2819 } /* end s_mp_setz() */
michael@0 2820 #endif
michael@0 2821
michael@0 2822 /* }}} */
michael@0 2823
michael@0 2824 /* {{{ s_mp_copy(sp, dp, count) */
michael@0 2825
michael@0 2826 #if MP_MACRO == 0
michael@0 2827 /* Copy 'count' digits from sp to dp */
michael@0 2828 void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count)
michael@0 2829 {
michael@0 2830 #if MP_MEMCPY == 0
michael@0 2831 int ix;
michael@0 2832
michael@0 2833 for(ix = 0; ix < count; ix++)
michael@0 2834 dp[ix] = sp[ix];
michael@0 2835 #else
michael@0 2836 memcpy(dp, sp, count * sizeof(mp_digit));
michael@0 2837 #endif
michael@0 2838 ++mp_copies;
michael@0 2839
michael@0 2840 } /* end s_mp_copy() */
michael@0 2841 #endif
michael@0 2842
michael@0 2843 /* }}} */
michael@0 2844
michael@0 2845 /* {{{ s_mp_alloc(nb, ni) */
michael@0 2846
michael@0 2847 #if MP_MACRO == 0
michael@0 2848 /* Allocate ni records of nb bytes each, and return a pointer to that */
michael@0 2849 void *s_mp_alloc(size_t nb, size_t ni)
michael@0 2850 {
michael@0 2851 ++mp_allocs;
michael@0 2852 return calloc(nb, ni);
michael@0 2853
michael@0 2854 } /* end s_mp_alloc() */
michael@0 2855 #endif
michael@0 2856
michael@0 2857 /* }}} */
michael@0 2858
michael@0 2859 /* {{{ s_mp_free(ptr) */
michael@0 2860
michael@0 2861 #if MP_MACRO == 0
michael@0 2862 /* Free the memory pointed to by ptr */
michael@0 2863 void s_mp_free(void *ptr)
michael@0 2864 {
michael@0 2865 if(ptr) {
michael@0 2866 ++mp_frees;
michael@0 2867 free(ptr);
michael@0 2868 }
michael@0 2869 } /* end s_mp_free() */
michael@0 2870 #endif
michael@0 2871
michael@0 2872 /* }}} */
michael@0 2873
michael@0 2874 /* {{{ s_mp_clamp(mp) */
michael@0 2875
michael@0 2876 #if MP_MACRO == 0
michael@0 2877 /* Remove leading zeroes from the given value */
michael@0 2878 void s_mp_clamp(mp_int *mp)
michael@0 2879 {
michael@0 2880 mp_size used = MP_USED(mp);
michael@0 2881 while (used > 1 && DIGIT(mp, used - 1) == 0)
michael@0 2882 --used;
michael@0 2883 MP_USED(mp) = used;
michael@0 2884 } /* end s_mp_clamp() */
michael@0 2885 #endif
michael@0 2886
michael@0 2887 /* }}} */
michael@0 2888
michael@0 2889 /* {{{ s_mp_exch(a, b) */
michael@0 2890
michael@0 2891 /* Exchange the data for a and b; (b, a) = (a, b) */
michael@0 2892 void s_mp_exch(mp_int *a, mp_int *b)
michael@0 2893 {
michael@0 2894 mp_int tmp;
michael@0 2895
michael@0 2896 tmp = *a;
michael@0 2897 *a = *b;
michael@0 2898 *b = tmp;
michael@0 2899
michael@0 2900 } /* end s_mp_exch() */
michael@0 2901
michael@0 2902 /* }}} */
michael@0 2903
michael@0 2904 /* }}} */
michael@0 2905
michael@0 2906 /* {{{ Arithmetic helpers */
michael@0 2907
michael@0 2908 /* {{{ s_mp_lshd(mp, p) */
michael@0 2909
michael@0 2910 /*
michael@0 2911 Shift mp leftward by p digits, growing if needed, and zero-filling
michael@0 2912 the in-shifted digits at the right end. This is a convenient
michael@0 2913 alternative to multiplication by powers of the radix
michael@0 2914 */
michael@0 2915
michael@0 2916 mp_err s_mp_lshd(mp_int *mp, mp_size p)
michael@0 2917 {
michael@0 2918 mp_err res;
michael@0 2919 mp_size pos;
michael@0 2920 int ix;
michael@0 2921
michael@0 2922 if(p == 0)
michael@0 2923 return MP_OKAY;
michael@0 2924
michael@0 2925 if (MP_USED(mp) == 1 && MP_DIGIT(mp, 0) == 0)
michael@0 2926 return MP_OKAY;
michael@0 2927
michael@0 2928 if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
michael@0 2929 return res;
michael@0 2930
michael@0 2931 pos = USED(mp) - 1;
michael@0 2932
michael@0 2933 /* Shift all the significant figures over as needed */
michael@0 2934 for(ix = pos - p; ix >= 0; ix--)
michael@0 2935 DIGIT(mp, ix + p) = DIGIT(mp, ix);
michael@0 2936
michael@0 2937 /* Fill the bottom digits with zeroes */
michael@0 2938 for(ix = 0; ix < p; ix++)
michael@0 2939 DIGIT(mp, ix) = 0;
michael@0 2940
michael@0 2941 return MP_OKAY;
michael@0 2942
michael@0 2943 } /* end s_mp_lshd() */
michael@0 2944
michael@0 2945 /* }}} */
michael@0 2946
michael@0 2947 /* {{{ s_mp_mul_2d(mp, d) */
michael@0 2948
michael@0 2949 /*
michael@0 2950 Multiply the integer by 2^d, where d is a number of bits. This
michael@0 2951 amounts to a bitwise shift of the value.
michael@0 2952 */
michael@0 2953 mp_err s_mp_mul_2d(mp_int *mp, mp_digit d)
michael@0 2954 {
michael@0 2955 mp_err res;
michael@0 2956 mp_digit dshift, bshift;
michael@0 2957 mp_digit mask;
michael@0 2958
michael@0 2959 ARGCHK(mp != NULL, MP_BADARG);
michael@0 2960
michael@0 2961 dshift = d / MP_DIGIT_BIT;
michael@0 2962 bshift = d % MP_DIGIT_BIT;
michael@0 2963 /* bits to be shifted out of the top word */
michael@0 2964 mask = ((mp_digit)~0 << (MP_DIGIT_BIT - bshift));
michael@0 2965 mask &= MP_DIGIT(mp, MP_USED(mp) - 1);
michael@0 2966
michael@0 2967 if (MP_OKAY != (res = s_mp_pad(mp, MP_USED(mp) + dshift + (mask != 0) )))
michael@0 2968 return res;
michael@0 2969
michael@0 2970 if (dshift && MP_OKAY != (res = s_mp_lshd(mp, dshift)))
michael@0 2971 return res;
michael@0 2972
michael@0 2973 if (bshift) {
michael@0 2974 mp_digit *pa = MP_DIGITS(mp);
michael@0 2975 mp_digit *alim = pa + MP_USED(mp);
michael@0 2976 mp_digit prev = 0;
michael@0 2977
michael@0 2978 for (pa += dshift; pa < alim; ) {
michael@0 2979 mp_digit x = *pa;
michael@0 2980 *pa++ = (x << bshift) | prev;
michael@0 2981 prev = x >> (DIGIT_BIT - bshift);
michael@0 2982 }
michael@0 2983 }
michael@0 2984
michael@0 2985 s_mp_clamp(mp);
michael@0 2986 return MP_OKAY;
michael@0 2987 } /* end s_mp_mul_2d() */
michael@0 2988
michael@0 2989 /* {{{ s_mp_rshd(mp, p) */
michael@0 2990
michael@0 2991 /*
michael@0 2992 Shift mp rightward by p digits. Maintains the invariant that
michael@0 2993 digits above the precision are all zero. Digits shifted off the
michael@0 2994 end are lost. Cannot fail.
michael@0 2995 */
michael@0 2996
michael@0 2997 void s_mp_rshd(mp_int *mp, mp_size p)
michael@0 2998 {
michael@0 2999 mp_size ix;
michael@0 3000 mp_digit *src, *dst;
michael@0 3001
michael@0 3002 if(p == 0)
michael@0 3003 return;
michael@0 3004
michael@0 3005 /* Shortcut when all digits are to be shifted off */
michael@0 3006 if(p >= USED(mp)) {
michael@0 3007 s_mp_setz(DIGITS(mp), ALLOC(mp));
michael@0 3008 USED(mp) = 1;
michael@0 3009 SIGN(mp) = ZPOS;
michael@0 3010 return;
michael@0 3011 }
michael@0 3012
michael@0 3013 /* Shift all the significant figures over as needed */
michael@0 3014 dst = MP_DIGITS(mp);
michael@0 3015 src = dst + p;
michael@0 3016 for (ix = USED(mp) - p; ix > 0; ix--)
michael@0 3017 *dst++ = *src++;
michael@0 3018
michael@0 3019 MP_USED(mp) -= p;
michael@0 3020 /* Fill the top digits with zeroes */
michael@0 3021 while (p-- > 0)
michael@0 3022 *dst++ = 0;
michael@0 3023
michael@0 3024 #if 0
michael@0 3025 /* Strip off any leading zeroes */
michael@0 3026 s_mp_clamp(mp);
michael@0 3027 #endif
michael@0 3028
michael@0 3029 } /* end s_mp_rshd() */
michael@0 3030
michael@0 3031 /* }}} */
michael@0 3032
michael@0 3033 /* {{{ s_mp_div_2(mp) */
michael@0 3034
michael@0 3035 /* Divide by two -- take advantage of radix properties to do it fast */
michael@0 3036 void s_mp_div_2(mp_int *mp)
michael@0 3037 {
michael@0 3038 s_mp_div_2d(mp, 1);
michael@0 3039
michael@0 3040 } /* end s_mp_div_2() */
michael@0 3041
michael@0 3042 /* }}} */
michael@0 3043
michael@0 3044 /* {{{ s_mp_mul_2(mp) */
michael@0 3045
michael@0 3046 mp_err s_mp_mul_2(mp_int *mp)
michael@0 3047 {
michael@0 3048 mp_digit *pd;
michael@0 3049 int ix, used;
michael@0 3050 mp_digit kin = 0;
michael@0 3051
michael@0 3052 /* Shift digits leftward by 1 bit */
michael@0 3053 used = MP_USED(mp);
michael@0 3054 pd = MP_DIGITS(mp);
michael@0 3055 for (ix = 0; ix < used; ix++) {
michael@0 3056 mp_digit d = *pd;
michael@0 3057 *pd++ = (d << 1) | kin;
michael@0 3058 kin = (d >> (DIGIT_BIT - 1));
michael@0 3059 }
michael@0 3060
michael@0 3061 /* Deal with rollover from last digit */
michael@0 3062 if (kin) {
michael@0 3063 if (ix >= ALLOC(mp)) {
michael@0 3064 mp_err res;
michael@0 3065 if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
michael@0 3066 return res;
michael@0 3067 }
michael@0 3068
michael@0 3069 DIGIT(mp, ix) = kin;
michael@0 3070 USED(mp) += 1;
michael@0 3071 }
michael@0 3072
michael@0 3073 return MP_OKAY;
michael@0 3074
michael@0 3075 } /* end s_mp_mul_2() */
michael@0 3076
michael@0 3077 /* }}} */
michael@0 3078
michael@0 3079 /* {{{ s_mp_mod_2d(mp, d) */
michael@0 3080
michael@0 3081 /*
michael@0 3082 Remainder the integer by 2^d, where d is a number of bits. This
michael@0 3083 amounts to a bitwise AND of the value, and does not require the full
michael@0 3084 division code
michael@0 3085 */
michael@0 3086 void s_mp_mod_2d(mp_int *mp, mp_digit d)
michael@0 3087 {
michael@0 3088 mp_size ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
michael@0 3089 mp_size ix;
michael@0 3090 mp_digit dmask;
michael@0 3091
michael@0 3092 if(ndig >= USED(mp))
michael@0 3093 return;
michael@0 3094
michael@0 3095 /* Flush all the bits above 2^d in its digit */
michael@0 3096 dmask = ((mp_digit)1 << nbit) - 1;
michael@0 3097 DIGIT(mp, ndig) &= dmask;
michael@0 3098
michael@0 3099 /* Flush all digits above the one with 2^d in it */
michael@0 3100 for(ix = ndig + 1; ix < USED(mp); ix++)
michael@0 3101 DIGIT(mp, ix) = 0;
michael@0 3102
michael@0 3103 s_mp_clamp(mp);
michael@0 3104
michael@0 3105 } /* end s_mp_mod_2d() */
michael@0 3106
michael@0 3107 /* }}} */
michael@0 3108
michael@0 3109 /* {{{ s_mp_div_2d(mp, d) */
michael@0 3110
michael@0 3111 /*
michael@0 3112 Divide the integer by 2^d, where d is a number of bits. This
michael@0 3113 amounts to a bitwise shift of the value, and does not require the
michael@0 3114 full division code (used in Barrett reduction, see below)
michael@0 3115 */
michael@0 3116 void s_mp_div_2d(mp_int *mp, mp_digit d)
michael@0 3117 {
michael@0 3118 int ix;
michael@0 3119 mp_digit save, next, mask;
michael@0 3120
michael@0 3121 s_mp_rshd(mp, d / DIGIT_BIT);
michael@0 3122 d %= DIGIT_BIT;
michael@0 3123 if (d) {
michael@0 3124 mask = ((mp_digit)1 << d) - 1;
michael@0 3125 save = 0;
michael@0 3126 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 3127 next = DIGIT(mp, ix) & mask;
michael@0 3128 DIGIT(mp, ix) = (DIGIT(mp, ix) >> d) | (save << (DIGIT_BIT - d));
michael@0 3129 save = next;
michael@0 3130 }
michael@0 3131 }
michael@0 3132 s_mp_clamp(mp);
michael@0 3133
michael@0 3134 } /* end s_mp_div_2d() */
michael@0 3135
michael@0 3136 /* }}} */
michael@0 3137
michael@0 3138 /* {{{ s_mp_norm(a, b, *d) */
michael@0 3139
michael@0 3140 /*
michael@0 3141 s_mp_norm(a, b, *d)
michael@0 3142
michael@0 3143 Normalize a and b for division, where b is the divisor. In order
michael@0 3144 that we might make good guesses for quotient digits, we want the
michael@0 3145 leading digit of b to be at least half the radix, which we
michael@0 3146 accomplish by multiplying a and b by a power of 2. The exponent
michael@0 3147 (shift count) is placed in *pd, so that the remainder can be shifted
michael@0 3148 back at the end of the division process.
michael@0 3149 */
michael@0 3150
michael@0 3151 mp_err s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
michael@0 3152 {
michael@0 3153 mp_digit d;
michael@0 3154 mp_digit mask;
michael@0 3155 mp_digit b_msd;
michael@0 3156 mp_err res = MP_OKAY;
michael@0 3157
michael@0 3158 d = 0;
michael@0 3159 mask = DIGIT_MAX & ~(DIGIT_MAX >> 1); /* mask is msb of digit */
michael@0 3160 b_msd = DIGIT(b, USED(b) - 1);
michael@0 3161 while (!(b_msd & mask)) {
michael@0 3162 b_msd <<= 1;
michael@0 3163 ++d;
michael@0 3164 }
michael@0 3165
michael@0 3166 if (d) {
michael@0 3167 MP_CHECKOK( s_mp_mul_2d(a, d) );
michael@0 3168 MP_CHECKOK( s_mp_mul_2d(b, d) );
michael@0 3169 }
michael@0 3170
michael@0 3171 *pd = d;
michael@0 3172 CLEANUP:
michael@0 3173 return res;
michael@0 3174
michael@0 3175 } /* end s_mp_norm() */
michael@0 3176
michael@0 3177 /* }}} */
michael@0 3178
michael@0 3179 /* }}} */
michael@0 3180
michael@0 3181 /* {{{ Primitive digit arithmetic */
michael@0 3182
michael@0 3183 /* {{{ s_mp_add_d(mp, d) */
michael@0 3184
michael@0 3185 /* Add d to |mp| in place */
michael@0 3186 mp_err s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */
michael@0 3187 {
michael@0 3188 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3189 mp_word w, k = 0;
michael@0 3190 mp_size ix = 1;
michael@0 3191
michael@0 3192 w = (mp_word)DIGIT(mp, 0) + d;
michael@0 3193 DIGIT(mp, 0) = ACCUM(w);
michael@0 3194 k = CARRYOUT(w);
michael@0 3195
michael@0 3196 while(ix < USED(mp) && k) {
michael@0 3197 w = (mp_word)DIGIT(mp, ix) + k;
michael@0 3198 DIGIT(mp, ix) = ACCUM(w);
michael@0 3199 k = CARRYOUT(w);
michael@0 3200 ++ix;
michael@0 3201 }
michael@0 3202
michael@0 3203 if(k != 0) {
michael@0 3204 mp_err res;
michael@0 3205
michael@0 3206 if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
michael@0 3207 return res;
michael@0 3208
michael@0 3209 DIGIT(mp, ix) = (mp_digit)k;
michael@0 3210 }
michael@0 3211
michael@0 3212 return MP_OKAY;
michael@0 3213 #else
michael@0 3214 mp_digit * pmp = MP_DIGITS(mp);
michael@0 3215 mp_digit sum, mp_i, carry = 0;
michael@0 3216 mp_err res = MP_OKAY;
michael@0 3217 int used = (int)MP_USED(mp);
michael@0 3218
michael@0 3219 mp_i = *pmp;
michael@0 3220 *pmp++ = sum = d + mp_i;
michael@0 3221 carry = (sum < d);
michael@0 3222 while (carry && --used > 0) {
michael@0 3223 mp_i = *pmp;
michael@0 3224 *pmp++ = sum = carry + mp_i;
michael@0 3225 carry = !sum;
michael@0 3226 }
michael@0 3227 if (carry && !used) {
michael@0 3228 /* mp is growing */
michael@0 3229 used = MP_USED(mp);
michael@0 3230 MP_CHECKOK( s_mp_pad(mp, used + 1) );
michael@0 3231 MP_DIGIT(mp, used) = carry;
michael@0 3232 }
michael@0 3233 CLEANUP:
michael@0 3234 return res;
michael@0 3235 #endif
michael@0 3236 } /* end s_mp_add_d() */
michael@0 3237
michael@0 3238 /* }}} */
michael@0 3239
michael@0 3240 /* {{{ s_mp_sub_d(mp, d) */
michael@0 3241
michael@0 3242 /* Subtract d from |mp| in place, assumes |mp| > d */
michael@0 3243 mp_err s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */
michael@0 3244 {
michael@0 3245 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3246 mp_word w, b = 0;
michael@0 3247 mp_size ix = 1;
michael@0 3248
michael@0 3249 /* Compute initial subtraction */
michael@0 3250 w = (RADIX + (mp_word)DIGIT(mp, 0)) - d;
michael@0 3251 b = CARRYOUT(w) ? 0 : 1;
michael@0 3252 DIGIT(mp, 0) = ACCUM(w);
michael@0 3253
michael@0 3254 /* Propagate borrows leftward */
michael@0 3255 while(b && ix < USED(mp)) {
michael@0 3256 w = (RADIX + (mp_word)DIGIT(mp, ix)) - b;
michael@0 3257 b = CARRYOUT(w) ? 0 : 1;
michael@0 3258 DIGIT(mp, ix) = ACCUM(w);
michael@0 3259 ++ix;
michael@0 3260 }
michael@0 3261
michael@0 3262 /* Remove leading zeroes */
michael@0 3263 s_mp_clamp(mp);
michael@0 3264
michael@0 3265 /* If we have a borrow out, it's a violation of the input invariant */
michael@0 3266 if(b)
michael@0 3267 return MP_RANGE;
michael@0 3268 else
michael@0 3269 return MP_OKAY;
michael@0 3270 #else
michael@0 3271 mp_digit *pmp = MP_DIGITS(mp);
michael@0 3272 mp_digit mp_i, diff, borrow;
michael@0 3273 mp_size used = MP_USED(mp);
michael@0 3274
michael@0 3275 mp_i = *pmp;
michael@0 3276 *pmp++ = diff = mp_i - d;
michael@0 3277 borrow = (diff > mp_i);
michael@0 3278 while (borrow && --used) {
michael@0 3279 mp_i = *pmp;
michael@0 3280 *pmp++ = diff = mp_i - borrow;
michael@0 3281 borrow = (diff > mp_i);
michael@0 3282 }
michael@0 3283 s_mp_clamp(mp);
michael@0 3284 return (borrow && !used) ? MP_RANGE : MP_OKAY;
michael@0 3285 #endif
michael@0 3286 } /* end s_mp_sub_d() */
michael@0 3287
michael@0 3288 /* }}} */
michael@0 3289
michael@0 3290 /* {{{ s_mp_mul_d(a, d) */
michael@0 3291
michael@0 3292 /* Compute a = a * d, single digit multiplication */
michael@0 3293 mp_err s_mp_mul_d(mp_int *a, mp_digit d)
michael@0 3294 {
michael@0 3295 mp_err res;
michael@0 3296 mp_size used;
michael@0 3297 int pow;
michael@0 3298
michael@0 3299 if (!d) {
michael@0 3300 mp_zero(a);
michael@0 3301 return MP_OKAY;
michael@0 3302 }
michael@0 3303 if (d == 1)
michael@0 3304 return MP_OKAY;
michael@0 3305 if (0 <= (pow = s_mp_ispow2d(d))) {
michael@0 3306 return s_mp_mul_2d(a, (mp_digit)pow);
michael@0 3307 }
michael@0 3308
michael@0 3309 used = MP_USED(a);
michael@0 3310 MP_CHECKOK( s_mp_pad(a, used + 1) );
michael@0 3311
michael@0 3312 s_mpv_mul_d(MP_DIGITS(a), used, d, MP_DIGITS(a));
michael@0 3313
michael@0 3314 s_mp_clamp(a);
michael@0 3315
michael@0 3316 CLEANUP:
michael@0 3317 return res;
michael@0 3318
michael@0 3319 } /* end s_mp_mul_d() */
michael@0 3320
michael@0 3321 /* }}} */
michael@0 3322
michael@0 3323 /* {{{ s_mp_div_d(mp, d, r) */
michael@0 3324
michael@0 3325 /*
michael@0 3326 s_mp_div_d(mp, d, r)
michael@0 3327
michael@0 3328 Compute the quotient mp = mp / d and remainder r = mp mod d, for a
michael@0 3329 single digit d. If r is null, the remainder will be discarded.
michael@0 3330 */
michael@0 3331
michael@0 3332 mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
michael@0 3333 {
michael@0 3334 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
michael@0 3335 mp_word w = 0, q;
michael@0 3336 #else
michael@0 3337 mp_digit w, q;
michael@0 3338 #endif
michael@0 3339 int ix;
michael@0 3340 mp_err res;
michael@0 3341 mp_int quot;
michael@0 3342 mp_int rem;
michael@0 3343
michael@0 3344 if(d == 0)
michael@0 3345 return MP_RANGE;
michael@0 3346 if (d == 1) {
michael@0 3347 if (r)
michael@0 3348 *r = 0;
michael@0 3349 return MP_OKAY;
michael@0 3350 }
michael@0 3351 /* could check for power of 2 here, but mp_div_d does that. */
michael@0 3352 if (MP_USED(mp) == 1) {
michael@0 3353 mp_digit n = MP_DIGIT(mp,0);
michael@0 3354 mp_digit rem;
michael@0 3355
michael@0 3356 q = n / d;
michael@0 3357 rem = n % d;
michael@0 3358 MP_DIGIT(mp,0) = q;
michael@0 3359 if (r)
michael@0 3360 *r = rem;
michael@0 3361 return MP_OKAY;
michael@0 3362 }
michael@0 3363
michael@0 3364 MP_DIGITS(&rem) = 0;
michael@0 3365 MP_DIGITS(&quot) = 0;
michael@0 3366 /* Make room for the quotient */
michael@0 3367 MP_CHECKOK( mp_init_size(&quot, USED(mp)) );
michael@0 3368
michael@0 3369 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
michael@0 3370 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 3371 w = (w << DIGIT_BIT) | DIGIT(mp, ix);
michael@0 3372
michael@0 3373 if(w >= d) {
michael@0 3374 q = w / d;
michael@0 3375 w = w % d;
michael@0 3376 } else {
michael@0 3377 q = 0;
michael@0 3378 }
michael@0 3379
michael@0 3380 s_mp_lshd(&quot, 1);
michael@0 3381 DIGIT(&quot, 0) = (mp_digit)q;
michael@0 3382 }
michael@0 3383 #else
michael@0 3384 {
michael@0 3385 mp_digit p;
michael@0 3386 #if !defined(MP_ASSEMBLY_DIV_2DX1D)
michael@0 3387 mp_digit norm;
michael@0 3388 #endif
michael@0 3389
michael@0 3390 MP_CHECKOK( mp_init_copy(&rem, mp) );
michael@0 3391
michael@0 3392 #if !defined(MP_ASSEMBLY_DIV_2DX1D)
michael@0 3393 MP_DIGIT(&quot, 0) = d;
michael@0 3394 MP_CHECKOK( s_mp_norm(&rem, &quot, &norm) );
michael@0 3395 if (norm)
michael@0 3396 d <<= norm;
michael@0 3397 MP_DIGIT(&quot, 0) = 0;
michael@0 3398 #endif
michael@0 3399
michael@0 3400 p = 0;
michael@0 3401 for (ix = USED(&rem) - 1; ix >= 0; ix--) {
michael@0 3402 w = DIGIT(&rem, ix);
michael@0 3403
michael@0 3404 if (p) {
michael@0 3405 MP_CHECKOK( s_mpv_div_2dx1d(p, w, d, &q, &w) );
michael@0 3406 } else if (w >= d) {
michael@0 3407 q = w / d;
michael@0 3408 w = w % d;
michael@0 3409 } else {
michael@0 3410 q = 0;
michael@0 3411 }
michael@0 3412
michael@0 3413 MP_CHECKOK( s_mp_lshd(&quot, 1) );
michael@0 3414 DIGIT(&quot, 0) = q;
michael@0 3415 p = w;
michael@0 3416 }
michael@0 3417 #if !defined(MP_ASSEMBLY_DIV_2DX1D)
michael@0 3418 if (norm)
michael@0 3419 w >>= norm;
michael@0 3420 #endif
michael@0 3421 }
michael@0 3422 #endif
michael@0 3423
michael@0 3424 /* Deliver the remainder, if desired */
michael@0 3425 if(r)
michael@0 3426 *r = (mp_digit)w;
michael@0 3427
michael@0 3428 s_mp_clamp(&quot);
michael@0 3429 mp_exch(&quot, mp);
michael@0 3430 CLEANUP:
michael@0 3431 mp_clear(&quot);
michael@0 3432 mp_clear(&rem);
michael@0 3433
michael@0 3434 return res;
michael@0 3435 } /* end s_mp_div_d() */
michael@0 3436
michael@0 3437 /* }}} */
michael@0 3438
michael@0 3439
michael@0 3440 /* }}} */
michael@0 3441
michael@0 3442 /* {{{ Primitive full arithmetic */
michael@0 3443
michael@0 3444 /* {{{ s_mp_add(a, b) */
michael@0 3445
michael@0 3446 /* Compute a = |a| + |b| */
michael@0 3447 mp_err s_mp_add(mp_int *a, const mp_int *b) /* magnitude addition */
michael@0 3448 {
michael@0 3449 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3450 mp_word w = 0;
michael@0 3451 #else
michael@0 3452 mp_digit d, sum, carry = 0;
michael@0 3453 #endif
michael@0 3454 mp_digit *pa, *pb;
michael@0 3455 mp_size ix;
michael@0 3456 mp_size used;
michael@0 3457 mp_err res;
michael@0 3458
michael@0 3459 /* Make sure a has enough precision for the output value */
michael@0 3460 if((USED(b) > USED(a)) && (res = s_mp_pad(a, USED(b))) != MP_OKAY)
michael@0 3461 return res;
michael@0 3462
michael@0 3463 /*
michael@0 3464 Add up all digits up to the precision of b. If b had initially
michael@0 3465 the same precision as a, or greater, we took care of it by the
michael@0 3466 padding step above, so there is no problem. If b had initially
michael@0 3467 less precision, we'll have to make sure the carry out is duly
michael@0 3468 propagated upward among the higher-order digits of the sum.
michael@0 3469 */
michael@0 3470 pa = MP_DIGITS(a);
michael@0 3471 pb = MP_DIGITS(b);
michael@0 3472 used = MP_USED(b);
michael@0 3473 for(ix = 0; ix < used; ix++) {
michael@0 3474 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3475 w = w + *pa + *pb++;
michael@0 3476 *pa++ = ACCUM(w);
michael@0 3477 w = CARRYOUT(w);
michael@0 3478 #else
michael@0 3479 d = *pa;
michael@0 3480 sum = d + *pb++;
michael@0 3481 d = (sum < d); /* detect overflow */
michael@0 3482 *pa++ = sum += carry;
michael@0 3483 carry = d + (sum < carry); /* detect overflow */
michael@0 3484 #endif
michael@0 3485 }
michael@0 3486
michael@0 3487 /* If we run out of 'b' digits before we're actually done, make
michael@0 3488 sure the carries get propagated upward...
michael@0 3489 */
michael@0 3490 used = MP_USED(a);
michael@0 3491 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3492 while (w && ix < used) {
michael@0 3493 w = w + *pa;
michael@0 3494 *pa++ = ACCUM(w);
michael@0 3495 w = CARRYOUT(w);
michael@0 3496 ++ix;
michael@0 3497 }
michael@0 3498 #else
michael@0 3499 while (carry && ix < used) {
michael@0 3500 sum = carry + *pa;
michael@0 3501 *pa++ = sum;
michael@0 3502 carry = !sum;
michael@0 3503 ++ix;
michael@0 3504 }
michael@0 3505 #endif
michael@0 3506
michael@0 3507 /* If there's an overall carry out, increase precision and include
michael@0 3508 it. We could have done this initially, but why touch the memory
michael@0 3509 allocator unless we're sure we have to?
michael@0 3510 */
michael@0 3511 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3512 if (w) {
michael@0 3513 if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
michael@0 3514 return res;
michael@0 3515
michael@0 3516 DIGIT(a, ix) = (mp_digit)w;
michael@0 3517 }
michael@0 3518 #else
michael@0 3519 if (carry) {
michael@0 3520 if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
michael@0 3521 return res;
michael@0 3522
michael@0 3523 DIGIT(a, used) = carry;
michael@0 3524 }
michael@0 3525 #endif
michael@0 3526
michael@0 3527 return MP_OKAY;
michael@0 3528 } /* end s_mp_add() */
michael@0 3529
michael@0 3530 /* }}} */
michael@0 3531
michael@0 3532 /* Compute c = |a| + |b| */ /* magnitude addition */
michael@0 3533 mp_err s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c)
michael@0 3534 {
michael@0 3535 mp_digit *pa, *pb, *pc;
michael@0 3536 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3537 mp_word w = 0;
michael@0 3538 #else
michael@0 3539 mp_digit sum, carry = 0, d;
michael@0 3540 #endif
michael@0 3541 mp_size ix;
michael@0 3542 mp_size used;
michael@0 3543 mp_err res;
michael@0 3544
michael@0 3545 MP_SIGN(c) = MP_SIGN(a);
michael@0 3546 if (MP_USED(a) < MP_USED(b)) {
michael@0 3547 const mp_int *xch = a;
michael@0 3548 a = b;
michael@0 3549 b = xch;
michael@0 3550 }
michael@0 3551
michael@0 3552 /* Make sure a has enough precision for the output value */
michael@0 3553 if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
michael@0 3554 return res;
michael@0 3555
michael@0 3556 /*
michael@0 3557 Add up all digits up to the precision of b. If b had initially
michael@0 3558 the same precision as a, or greater, we took care of it by the
michael@0 3559 exchange step above, so there is no problem. If b had initially
michael@0 3560 less precision, we'll have to make sure the carry out is duly
michael@0 3561 propagated upward among the higher-order digits of the sum.
michael@0 3562 */
michael@0 3563 pa = MP_DIGITS(a);
michael@0 3564 pb = MP_DIGITS(b);
michael@0 3565 pc = MP_DIGITS(c);
michael@0 3566 used = MP_USED(b);
michael@0 3567 for (ix = 0; ix < used; ix++) {
michael@0 3568 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3569 w = w + *pa++ + *pb++;
michael@0 3570 *pc++ = ACCUM(w);
michael@0 3571 w = CARRYOUT(w);
michael@0 3572 #else
michael@0 3573 d = *pa++;
michael@0 3574 sum = d + *pb++;
michael@0 3575 d = (sum < d); /* detect overflow */
michael@0 3576 *pc++ = sum += carry;
michael@0 3577 carry = d + (sum < carry); /* detect overflow */
michael@0 3578 #endif
michael@0 3579 }
michael@0 3580
michael@0 3581 /* If we run out of 'b' digits before we're actually done, make
michael@0 3582 sure the carries get propagated upward...
michael@0 3583 */
michael@0 3584 for (used = MP_USED(a); ix < used; ++ix) {
michael@0 3585 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3586 w = w + *pa++;
michael@0 3587 *pc++ = ACCUM(w);
michael@0 3588 w = CARRYOUT(w);
michael@0 3589 #else
michael@0 3590 *pc++ = sum = carry + *pa++;
michael@0 3591 carry = (sum < carry);
michael@0 3592 #endif
michael@0 3593 }
michael@0 3594
michael@0 3595 /* If there's an overall carry out, increase precision and include
michael@0 3596 it. We could have done this initially, but why touch the memory
michael@0 3597 allocator unless we're sure we have to?
michael@0 3598 */
michael@0 3599 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3600 if (w) {
michael@0 3601 if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
michael@0 3602 return res;
michael@0 3603
michael@0 3604 DIGIT(c, used) = (mp_digit)w;
michael@0 3605 ++used;
michael@0 3606 }
michael@0 3607 #else
michael@0 3608 if (carry) {
michael@0 3609 if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
michael@0 3610 return res;
michael@0 3611
michael@0 3612 DIGIT(c, used) = carry;
michael@0 3613 ++used;
michael@0 3614 }
michael@0 3615 #endif
michael@0 3616 MP_USED(c) = used;
michael@0 3617 return MP_OKAY;
michael@0 3618 }
michael@0 3619 /* {{{ s_mp_add_offset(a, b, offset) */
michael@0 3620
michael@0 3621 /* Compute a = |a| + ( |b| * (RADIX ** offset) ) */
michael@0 3622 mp_err s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset)
michael@0 3623 {
michael@0 3624 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3625 mp_word w, k = 0;
michael@0 3626 #else
michael@0 3627 mp_digit d, sum, carry = 0;
michael@0 3628 #endif
michael@0 3629 mp_size ib;
michael@0 3630 mp_size ia;
michael@0 3631 mp_size lim;
michael@0 3632 mp_err res;
michael@0 3633
michael@0 3634 /* Make sure a has enough precision for the output value */
michael@0 3635 lim = MP_USED(b) + offset;
michael@0 3636 if((lim > USED(a)) && (res = s_mp_pad(a, lim)) != MP_OKAY)
michael@0 3637 return res;
michael@0 3638
michael@0 3639 /*
michael@0 3640 Add up all digits up to the precision of b. If b had initially
michael@0 3641 the same precision as a, or greater, we took care of it by the
michael@0 3642 padding step above, so there is no problem. If b had initially
michael@0 3643 less precision, we'll have to make sure the carry out is duly
michael@0 3644 propagated upward among the higher-order digits of the sum.
michael@0 3645 */
michael@0 3646 lim = USED(b);
michael@0 3647 for(ib = 0, ia = offset; ib < lim; ib++, ia++) {
michael@0 3648 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3649 w = (mp_word)DIGIT(a, ia) + DIGIT(b, ib) + k;
michael@0 3650 DIGIT(a, ia) = ACCUM(w);
michael@0 3651 k = CARRYOUT(w);
michael@0 3652 #else
michael@0 3653 d = MP_DIGIT(a, ia);
michael@0 3654 sum = d + MP_DIGIT(b, ib);
michael@0 3655 d = (sum < d);
michael@0 3656 MP_DIGIT(a,ia) = sum += carry;
michael@0 3657 carry = d + (sum < carry);
michael@0 3658 #endif
michael@0 3659 }
michael@0 3660
michael@0 3661 /* If we run out of 'b' digits before we're actually done, make
michael@0 3662 sure the carries get propagated upward...
michael@0 3663 */
michael@0 3664 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3665 for (lim = MP_USED(a); k && (ia < lim); ++ia) {
michael@0 3666 w = (mp_word)DIGIT(a, ia) + k;
michael@0 3667 DIGIT(a, ia) = ACCUM(w);
michael@0 3668 k = CARRYOUT(w);
michael@0 3669 }
michael@0 3670 #else
michael@0 3671 for (lim = MP_USED(a); carry && (ia < lim); ++ia) {
michael@0 3672 d = MP_DIGIT(a, ia);
michael@0 3673 MP_DIGIT(a,ia) = sum = d + carry;
michael@0 3674 carry = (sum < d);
michael@0 3675 }
michael@0 3676 #endif
michael@0 3677
michael@0 3678 /* If there's an overall carry out, increase precision and include
michael@0 3679 it. We could have done this initially, but why touch the memory
michael@0 3680 allocator unless we're sure we have to?
michael@0 3681 */
michael@0 3682 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
michael@0 3683 if(k) {
michael@0 3684 if((res = s_mp_pad(a, USED(a) + 1)) != MP_OKAY)
michael@0 3685 return res;
michael@0 3686
michael@0 3687 DIGIT(a, ia) = (mp_digit)k;
michael@0 3688 }
michael@0 3689 #else
michael@0 3690 if (carry) {
michael@0 3691 if((res = s_mp_pad(a, lim + 1)) != MP_OKAY)
michael@0 3692 return res;
michael@0 3693
michael@0 3694 DIGIT(a, lim) = carry;
michael@0 3695 }
michael@0 3696 #endif
michael@0 3697 s_mp_clamp(a);
michael@0 3698
michael@0 3699 return MP_OKAY;
michael@0 3700
michael@0 3701 } /* end s_mp_add_offset() */
michael@0 3702
michael@0 3703 /* }}} */
michael@0 3704
michael@0 3705 /* {{{ s_mp_sub(a, b) */
michael@0 3706
michael@0 3707 /* Compute a = |a| - |b|, assumes |a| >= |b| */
michael@0 3708 mp_err s_mp_sub(mp_int *a, const mp_int *b) /* magnitude subtract */
michael@0 3709 {
michael@0 3710 mp_digit *pa, *pb, *limit;
michael@0 3711 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3712 mp_sword w = 0;
michael@0 3713 #else
michael@0 3714 mp_digit d, diff, borrow = 0;
michael@0 3715 #endif
michael@0 3716
michael@0 3717 /*
michael@0 3718 Subtract and propagate borrow. Up to the precision of b, this
michael@0 3719 accounts for the digits of b; after that, we just make sure the
michael@0 3720 carries get to the right place. This saves having to pad b out to
michael@0 3721 the precision of a just to make the loops work right...
michael@0 3722 */
michael@0 3723 pa = MP_DIGITS(a);
michael@0 3724 pb = MP_DIGITS(b);
michael@0 3725 limit = pb + MP_USED(b);
michael@0 3726 while (pb < limit) {
michael@0 3727 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3728 w = w + *pa - *pb++;
michael@0 3729 *pa++ = ACCUM(w);
michael@0 3730 w >>= MP_DIGIT_BIT;
michael@0 3731 #else
michael@0 3732 d = *pa;
michael@0 3733 diff = d - *pb++;
michael@0 3734 d = (diff > d); /* detect borrow */
michael@0 3735 if (borrow && --diff == MP_DIGIT_MAX)
michael@0 3736 ++d;
michael@0 3737 *pa++ = diff;
michael@0 3738 borrow = d;
michael@0 3739 #endif
michael@0 3740 }
michael@0 3741 limit = MP_DIGITS(a) + MP_USED(a);
michael@0 3742 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3743 while (w && pa < limit) {
michael@0 3744 w = w + *pa;
michael@0 3745 *pa++ = ACCUM(w);
michael@0 3746 w >>= MP_DIGIT_BIT;
michael@0 3747 }
michael@0 3748 #else
michael@0 3749 while (borrow && pa < limit) {
michael@0 3750 d = *pa;
michael@0 3751 *pa++ = diff = d - borrow;
michael@0 3752 borrow = (diff > d);
michael@0 3753 }
michael@0 3754 #endif
michael@0 3755
michael@0 3756 /* Clobber any leading zeroes we created */
michael@0 3757 s_mp_clamp(a);
michael@0 3758
michael@0 3759 /*
michael@0 3760 If there was a borrow out, then |b| > |a| in violation
michael@0 3761 of our input invariant. We've already done the work,
michael@0 3762 but we'll at least complain about it...
michael@0 3763 */
michael@0 3764 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3765 return w ? MP_RANGE : MP_OKAY;
michael@0 3766 #else
michael@0 3767 return borrow ? MP_RANGE : MP_OKAY;
michael@0 3768 #endif
michael@0 3769 } /* end s_mp_sub() */
michael@0 3770
michael@0 3771 /* }}} */
michael@0 3772
michael@0 3773 /* Compute c = |a| - |b|, assumes |a| >= |b| */ /* magnitude subtract */
michael@0 3774 mp_err s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c)
michael@0 3775 {
michael@0 3776 mp_digit *pa, *pb, *pc;
michael@0 3777 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3778 mp_sword w = 0;
michael@0 3779 #else
michael@0 3780 mp_digit d, diff, borrow = 0;
michael@0 3781 #endif
michael@0 3782 int ix, limit;
michael@0 3783 mp_err res;
michael@0 3784
michael@0 3785 MP_SIGN(c) = MP_SIGN(a);
michael@0 3786
michael@0 3787 /* Make sure a has enough precision for the output value */
michael@0 3788 if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
michael@0 3789 return res;
michael@0 3790
michael@0 3791 /*
michael@0 3792 Subtract and propagate borrow. Up to the precision of b, this
michael@0 3793 accounts for the digits of b; after that, we just make sure the
michael@0 3794 carries get to the right place. This saves having to pad b out to
michael@0 3795 the precision of a just to make the loops work right...
michael@0 3796 */
michael@0 3797 pa = MP_DIGITS(a);
michael@0 3798 pb = MP_DIGITS(b);
michael@0 3799 pc = MP_DIGITS(c);
michael@0 3800 limit = MP_USED(b);
michael@0 3801 for (ix = 0; ix < limit; ++ix) {
michael@0 3802 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3803 w = w + *pa++ - *pb++;
michael@0 3804 *pc++ = ACCUM(w);
michael@0 3805 w >>= MP_DIGIT_BIT;
michael@0 3806 #else
michael@0 3807 d = *pa++;
michael@0 3808 diff = d - *pb++;
michael@0 3809 d = (diff > d);
michael@0 3810 if (borrow && --diff == MP_DIGIT_MAX)
michael@0 3811 ++d;
michael@0 3812 *pc++ = diff;
michael@0 3813 borrow = d;
michael@0 3814 #endif
michael@0 3815 }
michael@0 3816 for (limit = MP_USED(a); ix < limit; ++ix) {
michael@0 3817 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3818 w = w + *pa++;
michael@0 3819 *pc++ = ACCUM(w);
michael@0 3820 w >>= MP_DIGIT_BIT;
michael@0 3821 #else
michael@0 3822 d = *pa++;
michael@0 3823 *pc++ = diff = d - borrow;
michael@0 3824 borrow = (diff > d);
michael@0 3825 #endif
michael@0 3826 }
michael@0 3827
michael@0 3828 /* Clobber any leading zeroes we created */
michael@0 3829 MP_USED(c) = ix;
michael@0 3830 s_mp_clamp(c);
michael@0 3831
michael@0 3832 /*
michael@0 3833 If there was a borrow out, then |b| > |a| in violation
michael@0 3834 of our input invariant. We've already done the work,
michael@0 3835 but we'll at least complain about it...
michael@0 3836 */
michael@0 3837 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
michael@0 3838 return w ? MP_RANGE : MP_OKAY;
michael@0 3839 #else
michael@0 3840 return borrow ? MP_RANGE : MP_OKAY;
michael@0 3841 #endif
michael@0 3842 }
michael@0 3843 /* {{{ s_mp_mul(a, b) */
michael@0 3844
michael@0 3845 /* Compute a = |a| * |b| */
michael@0 3846 mp_err s_mp_mul(mp_int *a, const mp_int *b)
michael@0 3847 {
michael@0 3848 return mp_mul(a, b, a);
michael@0 3849 } /* end s_mp_mul() */
michael@0 3850
michael@0 3851 /* }}} */
michael@0 3852
michael@0 3853 #if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
michael@0 3854 /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
michael@0 3855 #define MP_MUL_DxD(a, b, Phi, Plo) \
michael@0 3856 { unsigned long long product = (unsigned long long)a * b; \
michael@0 3857 Plo = (mp_digit)product; \
michael@0 3858 Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
michael@0 3859 #elif defined(OSF1)
michael@0 3860 #define MP_MUL_DxD(a, b, Phi, Plo) \
michael@0 3861 { Plo = asm ("mulq %a0, %a1, %v0", a, b);\
michael@0 3862 Phi = asm ("umulh %a0, %a1, %v0", a, b); }
michael@0 3863 #else
michael@0 3864 #define MP_MUL_DxD(a, b, Phi, Plo) \
michael@0 3865 { mp_digit a0b1, a1b0; \
michael@0 3866 Plo = (a & MP_HALF_DIGIT_MAX) * (b & MP_HALF_DIGIT_MAX); \
michael@0 3867 Phi = (a >> MP_HALF_DIGIT_BIT) * (b >> MP_HALF_DIGIT_BIT); \
michael@0 3868 a0b1 = (a & MP_HALF_DIGIT_MAX) * (b >> MP_HALF_DIGIT_BIT); \
michael@0 3869 a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \
michael@0 3870 a1b0 += a0b1; \
michael@0 3871 Phi += a1b0 >> MP_HALF_DIGIT_BIT; \
michael@0 3872 if (a1b0 < a0b1) \
michael@0 3873 Phi += MP_HALF_RADIX; \
michael@0 3874 a1b0 <<= MP_HALF_DIGIT_BIT; \
michael@0 3875 Plo += a1b0; \
michael@0 3876 if (Plo < a1b0) \
michael@0 3877 ++Phi; \
michael@0 3878 }
michael@0 3879 #endif
michael@0 3880
michael@0 3881 #if !defined(MP_ASSEMBLY_MULTIPLY)
michael@0 3882 /* c = a * b */
michael@0 3883 void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
michael@0 3884 {
michael@0 3885 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
michael@0 3886 mp_digit d = 0;
michael@0 3887
michael@0 3888 /* Inner product: Digits of a */
michael@0 3889 while (a_len--) {
michael@0 3890 mp_word w = ((mp_word)b * *a++) + d;
michael@0 3891 *c++ = ACCUM(w);
michael@0 3892 d = CARRYOUT(w);
michael@0 3893 }
michael@0 3894 *c = d;
michael@0 3895 #else
michael@0 3896 mp_digit carry = 0;
michael@0 3897 while (a_len--) {
michael@0 3898 mp_digit a_i = *a++;
michael@0 3899 mp_digit a0b0, a1b1;
michael@0 3900
michael@0 3901 MP_MUL_DxD(a_i, b, a1b1, a0b0);
michael@0 3902
michael@0 3903 a0b0 += carry;
michael@0 3904 if (a0b0 < carry)
michael@0 3905 ++a1b1;
michael@0 3906 *c++ = a0b0;
michael@0 3907 carry = a1b1;
michael@0 3908 }
michael@0 3909 *c = carry;
michael@0 3910 #endif
michael@0 3911 }
michael@0 3912
michael@0 3913 /* c += a * b */
michael@0 3914 void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
michael@0 3915 mp_digit *c)
michael@0 3916 {
michael@0 3917 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
michael@0 3918 mp_digit d = 0;
michael@0 3919
michael@0 3920 /* Inner product: Digits of a */
michael@0 3921 while (a_len--) {
michael@0 3922 mp_word w = ((mp_word)b * *a++) + *c + d;
michael@0 3923 *c++ = ACCUM(w);
michael@0 3924 d = CARRYOUT(w);
michael@0 3925 }
michael@0 3926 *c = d;
michael@0 3927 #else
michael@0 3928 mp_digit carry = 0;
michael@0 3929 while (a_len--) {
michael@0 3930 mp_digit a_i = *a++;
michael@0 3931 mp_digit a0b0, a1b1;
michael@0 3932
michael@0 3933 MP_MUL_DxD(a_i, b, a1b1, a0b0);
michael@0 3934
michael@0 3935 a0b0 += carry;
michael@0 3936 if (a0b0 < carry)
michael@0 3937 ++a1b1;
michael@0 3938 a0b0 += a_i = *c;
michael@0 3939 if (a0b0 < a_i)
michael@0 3940 ++a1b1;
michael@0 3941 *c++ = a0b0;
michael@0 3942 carry = a1b1;
michael@0 3943 }
michael@0 3944 *c = carry;
michael@0 3945 #endif
michael@0 3946 }
michael@0 3947
michael@0 3948 /* Presently, this is only used by the Montgomery arithmetic code. */
michael@0 3949 /* c += a * b */
michael@0 3950 void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
michael@0 3951 {
michael@0 3952 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
michael@0 3953 mp_digit d = 0;
michael@0 3954
michael@0 3955 /* Inner product: Digits of a */
michael@0 3956 while (a_len--) {
michael@0 3957 mp_word w = ((mp_word)b * *a++) + *c + d;
michael@0 3958 *c++ = ACCUM(w);
michael@0 3959 d = CARRYOUT(w);
michael@0 3960 }
michael@0 3961
michael@0 3962 while (d) {
michael@0 3963 mp_word w = (mp_word)*c + d;
michael@0 3964 *c++ = ACCUM(w);
michael@0 3965 d = CARRYOUT(w);
michael@0 3966 }
michael@0 3967 #else
michael@0 3968 mp_digit carry = 0;
michael@0 3969 while (a_len--) {
michael@0 3970 mp_digit a_i = *a++;
michael@0 3971 mp_digit a0b0, a1b1;
michael@0 3972
michael@0 3973 MP_MUL_DxD(a_i, b, a1b1, a0b0);
michael@0 3974
michael@0 3975 a0b0 += carry;
michael@0 3976 if (a0b0 < carry)
michael@0 3977 ++a1b1;
michael@0 3978
michael@0 3979 a0b0 += a_i = *c;
michael@0 3980 if (a0b0 < a_i)
michael@0 3981 ++a1b1;
michael@0 3982
michael@0 3983 *c++ = a0b0;
michael@0 3984 carry = a1b1;
michael@0 3985 }
michael@0 3986 while (carry) {
michael@0 3987 mp_digit c_i = *c;
michael@0 3988 carry += c_i;
michael@0 3989 *c++ = carry;
michael@0 3990 carry = carry < c_i;
michael@0 3991 }
michael@0 3992 #endif
michael@0 3993 }
michael@0 3994 #endif
michael@0 3995
michael@0 3996 #if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
michael@0 3997 /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
michael@0 3998 #define MP_SQR_D(a, Phi, Plo) \
michael@0 3999 { unsigned long long square = (unsigned long long)a * a; \
michael@0 4000 Plo = (mp_digit)square; \
michael@0 4001 Phi = (mp_digit)(square >> MP_DIGIT_BIT); }
michael@0 4002 #elif defined(OSF1)
michael@0 4003 #define MP_SQR_D(a, Phi, Plo) \
michael@0 4004 { Plo = asm ("mulq %a0, %a0, %v0", a);\
michael@0 4005 Phi = asm ("umulh %a0, %a0, %v0", a); }
michael@0 4006 #else
michael@0 4007 #define MP_SQR_D(a, Phi, Plo) \
michael@0 4008 { mp_digit Pmid; \
michael@0 4009 Plo = (a & MP_HALF_DIGIT_MAX) * (a & MP_HALF_DIGIT_MAX); \
michael@0 4010 Phi = (a >> MP_HALF_DIGIT_BIT) * (a >> MP_HALF_DIGIT_BIT); \
michael@0 4011 Pmid = (a & MP_HALF_DIGIT_MAX) * (a >> MP_HALF_DIGIT_BIT); \
michael@0 4012 Phi += Pmid >> (MP_HALF_DIGIT_BIT - 1); \
michael@0 4013 Pmid <<= (MP_HALF_DIGIT_BIT + 1); \
michael@0 4014 Plo += Pmid; \
michael@0 4015 if (Plo < Pmid) \
michael@0 4016 ++Phi; \
michael@0 4017 }
michael@0 4018 #endif
michael@0 4019
michael@0 4020 #if !defined(MP_ASSEMBLY_SQUARE)
michael@0 4021 /* Add the squares of the digits of a to the digits of b. */
michael@0 4022 void s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
michael@0 4023 {
michael@0 4024 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
michael@0 4025 mp_word w;
michael@0 4026 mp_digit d;
michael@0 4027 mp_size ix;
michael@0 4028
michael@0 4029 w = 0;
michael@0 4030 #define ADD_SQUARE(n) \
michael@0 4031 d = pa[n]; \
michael@0 4032 w += (d * (mp_word)d) + ps[2*n]; \
michael@0 4033 ps[2*n] = ACCUM(w); \
michael@0 4034 w = (w >> DIGIT_BIT) + ps[2*n+1]; \
michael@0 4035 ps[2*n+1] = ACCUM(w); \
michael@0 4036 w = (w >> DIGIT_BIT)
michael@0 4037
michael@0 4038 for (ix = a_len; ix >= 4; ix -= 4) {
michael@0 4039 ADD_SQUARE(0);
michael@0 4040 ADD_SQUARE(1);
michael@0 4041 ADD_SQUARE(2);
michael@0 4042 ADD_SQUARE(3);
michael@0 4043 pa += 4;
michael@0 4044 ps += 8;
michael@0 4045 }
michael@0 4046 if (ix) {
michael@0 4047 ps += 2*ix;
michael@0 4048 pa += ix;
michael@0 4049 switch (ix) {
michael@0 4050 case 3: ADD_SQUARE(-3); /* FALLTHRU */
michael@0 4051 case 2: ADD_SQUARE(-2); /* FALLTHRU */
michael@0 4052 case 1: ADD_SQUARE(-1); /* FALLTHRU */
michael@0 4053 case 0: break;
michael@0 4054 }
michael@0 4055 }
michael@0 4056 while (w) {
michael@0 4057 w += *ps;
michael@0 4058 *ps++ = ACCUM(w);
michael@0 4059 w = (w >> DIGIT_BIT);
michael@0 4060 }
michael@0 4061 #else
michael@0 4062 mp_digit carry = 0;
michael@0 4063 while (a_len--) {
michael@0 4064 mp_digit a_i = *pa++;
michael@0 4065 mp_digit a0a0, a1a1;
michael@0 4066
michael@0 4067 MP_SQR_D(a_i, a1a1, a0a0);
michael@0 4068
michael@0 4069 /* here a1a1 and a0a0 constitute a_i ** 2 */
michael@0 4070 a0a0 += carry;
michael@0 4071 if (a0a0 < carry)
michael@0 4072 ++a1a1;
michael@0 4073
michael@0 4074 /* now add to ps */
michael@0 4075 a0a0 += a_i = *ps;
michael@0 4076 if (a0a0 < a_i)
michael@0 4077 ++a1a1;
michael@0 4078 *ps++ = a0a0;
michael@0 4079 a1a1 += a_i = *ps;
michael@0 4080 carry = (a1a1 < a_i);
michael@0 4081 *ps++ = a1a1;
michael@0 4082 }
michael@0 4083 while (carry) {
michael@0 4084 mp_digit s_i = *ps;
michael@0 4085 carry += s_i;
michael@0 4086 *ps++ = carry;
michael@0 4087 carry = carry < s_i;
michael@0 4088 }
michael@0 4089 #endif
michael@0 4090 }
michael@0 4091 #endif
michael@0 4092
michael@0 4093 #if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) \
michael@0 4094 && !defined(MP_ASSEMBLY_DIV_2DX1D)
michael@0 4095 /*
michael@0 4096 ** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
michael@0 4097 ** so its high bit is 1. This code is from NSPR.
michael@0 4098 */
michael@0 4099 mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
michael@0 4100 mp_digit *qp, mp_digit *rp)
michael@0 4101 {
michael@0 4102 mp_digit d1, d0, q1, q0;
michael@0 4103 mp_digit r1, r0, m;
michael@0 4104
michael@0 4105 d1 = divisor >> MP_HALF_DIGIT_BIT;
michael@0 4106 d0 = divisor & MP_HALF_DIGIT_MAX;
michael@0 4107 r1 = Nhi % d1;
michael@0 4108 q1 = Nhi / d1;
michael@0 4109 m = q1 * d0;
michael@0 4110 r1 = (r1 << MP_HALF_DIGIT_BIT) | (Nlo >> MP_HALF_DIGIT_BIT);
michael@0 4111 if (r1 < m) {
michael@0 4112 q1--, r1 += divisor;
michael@0 4113 if (r1 >= divisor && r1 < m) {
michael@0 4114 q1--, r1 += divisor;
michael@0 4115 }
michael@0 4116 }
michael@0 4117 r1 -= m;
michael@0 4118 r0 = r1 % d1;
michael@0 4119 q0 = r1 / d1;
michael@0 4120 m = q0 * d0;
michael@0 4121 r0 = (r0 << MP_HALF_DIGIT_BIT) | (Nlo & MP_HALF_DIGIT_MAX);
michael@0 4122 if (r0 < m) {
michael@0 4123 q0--, r0 += divisor;
michael@0 4124 if (r0 >= divisor && r0 < m) {
michael@0 4125 q0--, r0 += divisor;
michael@0 4126 }
michael@0 4127 }
michael@0 4128 if (qp)
michael@0 4129 *qp = (q1 << MP_HALF_DIGIT_BIT) | q0;
michael@0 4130 if (rp)
michael@0 4131 *rp = r0 - m;
michael@0 4132 return MP_OKAY;
michael@0 4133 }
michael@0 4134 #endif
michael@0 4135
michael@0 4136 #if MP_SQUARE
michael@0 4137 /* {{{ s_mp_sqr(a) */
michael@0 4138
michael@0 4139 mp_err s_mp_sqr(mp_int *a)
michael@0 4140 {
michael@0 4141 mp_err res;
michael@0 4142 mp_int tmp;
michael@0 4143
michael@0 4144 if((res = mp_init_size(&tmp, 2 * USED(a))) != MP_OKAY)
michael@0 4145 return res;
michael@0 4146 res = mp_sqr(a, &tmp);
michael@0 4147 if (res == MP_OKAY) {
michael@0 4148 s_mp_exch(&tmp, a);
michael@0 4149 }
michael@0 4150 mp_clear(&tmp);
michael@0 4151 return res;
michael@0 4152 }
michael@0 4153
michael@0 4154 /* }}} */
michael@0 4155 #endif
michael@0 4156
michael@0 4157 /* {{{ s_mp_div(a, b) */
michael@0 4158
michael@0 4159 /*
michael@0 4160 s_mp_div(a, b)
michael@0 4161
michael@0 4162 Compute a = a / b and b = a mod b. Assumes b > a.
michael@0 4163 */
michael@0 4164
michael@0 4165 mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
michael@0 4166 mp_int *div, /* i: divisor */
michael@0 4167 mp_int *quot) /* i: 0; o: quotient */
michael@0 4168 {
michael@0 4169 mp_int part, t;
michael@0 4170 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
michael@0 4171 mp_word q_msd;
michael@0 4172 #else
michael@0 4173 mp_digit q_msd;
michael@0 4174 #endif
michael@0 4175 mp_err res;
michael@0 4176 mp_digit d;
michael@0 4177 mp_digit div_msd;
michael@0 4178 int ix;
michael@0 4179
michael@0 4180 if(mp_cmp_z(div) == 0)
michael@0 4181 return MP_RANGE;
michael@0 4182
michael@0 4183 DIGITS(&t) = 0;
michael@0 4184 /* Shortcut if divisor is power of two */
michael@0 4185 if((ix = s_mp_ispow2(div)) >= 0) {
michael@0 4186 MP_CHECKOK( mp_copy(rem, quot) );
michael@0 4187 s_mp_div_2d(quot, (mp_digit)ix);
michael@0 4188 s_mp_mod_2d(rem, (mp_digit)ix);
michael@0 4189
michael@0 4190 return MP_OKAY;
michael@0 4191 }
michael@0 4192
michael@0 4193 MP_SIGN(rem) = ZPOS;
michael@0 4194 MP_SIGN(div) = ZPOS;
michael@0 4195
michael@0 4196 /* A working temporary for division */
michael@0 4197 MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem)));
michael@0 4198
michael@0 4199 /* Normalize to optimize guessing */
michael@0 4200 MP_CHECKOK( s_mp_norm(rem, div, &d) );
michael@0 4201
michael@0 4202 part = *rem;
michael@0 4203
michael@0 4204 /* Perform the division itself...woo! */
michael@0 4205 MP_USED(quot) = MP_ALLOC(quot);
michael@0 4206
michael@0 4207 /* Find a partial substring of rem which is at least div */
michael@0 4208 /* If we didn't find one, we're finished dividing */
michael@0 4209 while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) {
michael@0 4210 int i;
michael@0 4211 int unusedRem;
michael@0 4212
michael@0 4213 unusedRem = MP_USED(rem) - MP_USED(div);
michael@0 4214 MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem;
michael@0 4215 MP_ALLOC(&part) = MP_ALLOC(rem) - unusedRem;
michael@0 4216 MP_USED(&part) = MP_USED(div);
michael@0 4217 if (s_mp_cmp(&part, div) < 0) {
michael@0 4218 -- unusedRem;
michael@0 4219 #if MP_ARGCHK == 2
michael@0 4220 assert(unusedRem >= 0);
michael@0 4221 #endif
michael@0 4222 -- MP_DIGITS(&part);
michael@0 4223 ++ MP_USED(&part);
michael@0 4224 ++ MP_ALLOC(&part);
michael@0 4225 }
michael@0 4226
michael@0 4227 /* Compute a guess for the next quotient digit */
michael@0 4228 q_msd = MP_DIGIT(&part, MP_USED(&part) - 1);
michael@0 4229 div_msd = MP_DIGIT(div, MP_USED(div) - 1);
michael@0 4230 if (q_msd >= div_msd) {
michael@0 4231 q_msd = 1;
michael@0 4232 } else if (MP_USED(&part) > 1) {
michael@0 4233 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
michael@0 4234 q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
michael@0 4235 q_msd /= div_msd;
michael@0 4236 if (q_msd == RADIX)
michael@0 4237 --q_msd;
michael@0 4238 #else
michael@0 4239 mp_digit r;
michael@0 4240 MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
michael@0 4241 div_msd, &q_msd, &r) );
michael@0 4242 #endif
michael@0 4243 } else {
michael@0 4244 q_msd = 0;
michael@0 4245 }
michael@0 4246 #if MP_ARGCHK == 2
michael@0 4247 assert(q_msd > 0); /* This case should never occur any more. */
michael@0 4248 #endif
michael@0 4249 if (q_msd <= 0)
michael@0 4250 break;
michael@0 4251
michael@0 4252 /* See what that multiplies out to */
michael@0 4253 mp_copy(div, &t);
michael@0 4254 MP_CHECKOK( s_mp_mul_d(&t, (mp_digit)q_msd) );
michael@0 4255
michael@0 4256 /*
michael@0 4257 If it's too big, back it off. We should not have to do this
michael@0 4258 more than once, or, in rare cases, twice. Knuth describes a
michael@0 4259 method by which this could be reduced to a maximum of once, but
michael@0 4260 I didn't implement that here.
michael@0 4261 * When using s_mpv_div_2dx1d, we may have to do this 3 times.
michael@0 4262 */
michael@0 4263 for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) {
michael@0 4264 --q_msd;
michael@0 4265 s_mp_sub(&t, div); /* t -= div */
michael@0 4266 }
michael@0 4267 if (i < 0) {
michael@0 4268 res = MP_RANGE;
michael@0 4269 goto CLEANUP;
michael@0 4270 }
michael@0 4271
michael@0 4272 /* At this point, q_msd should be the right next digit */
michael@0 4273 MP_CHECKOK( s_mp_sub(&part, &t) ); /* part -= t */
michael@0 4274 s_mp_clamp(rem);
michael@0 4275
michael@0 4276 /*
michael@0 4277 Include the digit in the quotient. We allocated enough memory
michael@0 4278 for any quotient we could ever possibly get, so we should not
michael@0 4279 have to check for failures here
michael@0 4280 */
michael@0 4281 MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd;
michael@0 4282 }
michael@0 4283
michael@0 4284 /* Denormalize remainder */
michael@0 4285 if (d) {
michael@0 4286 s_mp_div_2d(rem, d);
michael@0 4287 }
michael@0 4288
michael@0 4289 s_mp_clamp(quot);
michael@0 4290
michael@0 4291 CLEANUP:
michael@0 4292 mp_clear(&t);
michael@0 4293
michael@0 4294 return res;
michael@0 4295
michael@0 4296 } /* end s_mp_div() */
michael@0 4297
michael@0 4298
michael@0 4299 /* }}} */
michael@0 4300
michael@0 4301 /* {{{ s_mp_2expt(a, k) */
michael@0 4302
michael@0 4303 mp_err s_mp_2expt(mp_int *a, mp_digit k)
michael@0 4304 {
michael@0 4305 mp_err res;
michael@0 4306 mp_size dig, bit;
michael@0 4307
michael@0 4308 dig = k / DIGIT_BIT;
michael@0 4309 bit = k % DIGIT_BIT;
michael@0 4310
michael@0 4311 mp_zero(a);
michael@0 4312 if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
michael@0 4313 return res;
michael@0 4314
michael@0 4315 DIGIT(a, dig) |= ((mp_digit)1 << bit);
michael@0 4316
michael@0 4317 return MP_OKAY;
michael@0 4318
michael@0 4319 } /* end s_mp_2expt() */
michael@0 4320
michael@0 4321 /* }}} */
michael@0 4322
michael@0 4323 /* {{{ s_mp_reduce(x, m, mu) */
michael@0 4324
michael@0 4325 /*
michael@0 4326 Compute Barrett reduction, x (mod m), given a precomputed value for
michael@0 4327 mu = b^2k / m, where b = RADIX and k = #digits(m). This should be
michael@0 4328 faster than straight division, when many reductions by the same
michael@0 4329 value of m are required (such as in modular exponentiation). This
michael@0 4330 can nearly halve the time required to do modular exponentiation,
michael@0 4331 as compared to using the full integer divide to reduce.
michael@0 4332
michael@0 4333 This algorithm was derived from the _Handbook of Applied
michael@0 4334 Cryptography_ by Menezes, Oorschot and VanStone, Ch. 14,
michael@0 4335 pp. 603-604.
michael@0 4336 */
michael@0 4337
michael@0 4338 mp_err s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu)
michael@0 4339 {
michael@0 4340 mp_int q;
michael@0 4341 mp_err res;
michael@0 4342
michael@0 4343 if((res = mp_init_copy(&q, x)) != MP_OKAY)
michael@0 4344 return res;
michael@0 4345
michael@0 4346 s_mp_rshd(&q, USED(m) - 1); /* q1 = x / b^(k-1) */
michael@0 4347 s_mp_mul(&q, mu); /* q2 = q1 * mu */
michael@0 4348 s_mp_rshd(&q, USED(m) + 1); /* q3 = q2 / b^(k+1) */
michael@0 4349
michael@0 4350 /* x = x mod b^(k+1), quick (no division) */
michael@0 4351 s_mp_mod_2d(x, DIGIT_BIT * (USED(m) + 1));
michael@0 4352
michael@0 4353 /* q = q * m mod b^(k+1), quick (no division) */
michael@0 4354 s_mp_mul(&q, m);
michael@0 4355 s_mp_mod_2d(&q, DIGIT_BIT * (USED(m) + 1));
michael@0 4356
michael@0 4357 /* x = x - q */
michael@0 4358 if((res = mp_sub(x, &q, x)) != MP_OKAY)
michael@0 4359 goto CLEANUP;
michael@0 4360
michael@0 4361 /* If x < 0, add b^(k+1) to it */
michael@0 4362 if(mp_cmp_z(x) < 0) {
michael@0 4363 mp_set(&q, 1);
michael@0 4364 if((res = s_mp_lshd(&q, USED(m) + 1)) != MP_OKAY)
michael@0 4365 goto CLEANUP;
michael@0 4366 if((res = mp_add(x, &q, x)) != MP_OKAY)
michael@0 4367 goto CLEANUP;
michael@0 4368 }
michael@0 4369
michael@0 4370 /* Back off if it's too big */
michael@0 4371 while(mp_cmp(x, m) >= 0) {
michael@0 4372 if((res = s_mp_sub(x, m)) != MP_OKAY)
michael@0 4373 break;
michael@0 4374 }
michael@0 4375
michael@0 4376 CLEANUP:
michael@0 4377 mp_clear(&q);
michael@0 4378
michael@0 4379 return res;
michael@0 4380
michael@0 4381 } /* end s_mp_reduce() */
michael@0 4382
michael@0 4383 /* }}} */
michael@0 4384
michael@0 4385 /* }}} */
michael@0 4386
michael@0 4387 /* {{{ Primitive comparisons */
michael@0 4388
michael@0 4389 /* {{{ s_mp_cmp(a, b) */
michael@0 4390
michael@0 4391 /* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b */
michael@0 4392 int s_mp_cmp(const mp_int *a, const mp_int *b)
michael@0 4393 {
michael@0 4394 mp_size used_a = MP_USED(a);
michael@0 4395 {
michael@0 4396 mp_size used_b = MP_USED(b);
michael@0 4397
michael@0 4398 if (used_a > used_b)
michael@0 4399 goto IS_GT;
michael@0 4400 if (used_a < used_b)
michael@0 4401 goto IS_LT;
michael@0 4402 }
michael@0 4403 {
michael@0 4404 mp_digit *pa, *pb;
michael@0 4405 mp_digit da = 0, db = 0;
michael@0 4406
michael@0 4407 #define CMP_AB(n) if ((da = pa[n]) != (db = pb[n])) goto done
michael@0 4408
michael@0 4409 pa = MP_DIGITS(a) + used_a;
michael@0 4410 pb = MP_DIGITS(b) + used_a;
michael@0 4411 while (used_a >= 4) {
michael@0 4412 pa -= 4;
michael@0 4413 pb -= 4;
michael@0 4414 used_a -= 4;
michael@0 4415 CMP_AB(3);
michael@0 4416 CMP_AB(2);
michael@0 4417 CMP_AB(1);
michael@0 4418 CMP_AB(0);
michael@0 4419 }
michael@0 4420 while (used_a-- > 0 && ((da = *--pa) == (db = *--pb)))
michael@0 4421 /* do nothing */;
michael@0 4422 done:
michael@0 4423 if (da > db)
michael@0 4424 goto IS_GT;
michael@0 4425 if (da < db)
michael@0 4426 goto IS_LT;
michael@0 4427 }
michael@0 4428 return MP_EQ;
michael@0 4429 IS_LT:
michael@0 4430 return MP_LT;
michael@0 4431 IS_GT:
michael@0 4432 return MP_GT;
michael@0 4433 } /* end s_mp_cmp() */
michael@0 4434
michael@0 4435 /* }}} */
michael@0 4436
michael@0 4437 /* {{{ s_mp_cmp_d(a, d) */
michael@0 4438
michael@0 4439 /* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d */
michael@0 4440 int s_mp_cmp_d(const mp_int *a, mp_digit d)
michael@0 4441 {
michael@0 4442 if(USED(a) > 1)
michael@0 4443 return MP_GT;
michael@0 4444
michael@0 4445 if(DIGIT(a, 0) < d)
michael@0 4446 return MP_LT;
michael@0 4447 else if(DIGIT(a, 0) > d)
michael@0 4448 return MP_GT;
michael@0 4449 else
michael@0 4450 return MP_EQ;
michael@0 4451
michael@0 4452 } /* end s_mp_cmp_d() */
michael@0 4453
michael@0 4454 /* }}} */
michael@0 4455
michael@0 4456 /* {{{ s_mp_ispow2(v) */
michael@0 4457
michael@0 4458 /*
michael@0 4459 Returns -1 if the value is not a power of two; otherwise, it returns
michael@0 4460 k such that v = 2^k, i.e. lg(v).
michael@0 4461 */
michael@0 4462 int s_mp_ispow2(const mp_int *v)
michael@0 4463 {
michael@0 4464 mp_digit d;
michael@0 4465 int extra = 0, ix;
michael@0 4466
michael@0 4467 ix = MP_USED(v) - 1;
michael@0 4468 d = MP_DIGIT(v, ix); /* most significant digit of v */
michael@0 4469
michael@0 4470 extra = s_mp_ispow2d(d);
michael@0 4471 if (extra < 0 || ix == 0)
michael@0 4472 return extra;
michael@0 4473
michael@0 4474 while (--ix >= 0) {
michael@0 4475 if (DIGIT(v, ix) != 0)
michael@0 4476 return -1; /* not a power of two */
michael@0 4477 extra += MP_DIGIT_BIT;
michael@0 4478 }
michael@0 4479
michael@0 4480 return extra;
michael@0 4481
michael@0 4482 } /* end s_mp_ispow2() */
michael@0 4483
michael@0 4484 /* }}} */
michael@0 4485
michael@0 4486 /* {{{ s_mp_ispow2d(d) */
michael@0 4487
michael@0 4488 int s_mp_ispow2d(mp_digit d)
michael@0 4489 {
michael@0 4490 if ((d != 0) && ((d & (d-1)) == 0)) { /* d is a power of 2 */
michael@0 4491 int pow = 0;
michael@0 4492 #if defined (MP_USE_UINT_DIGIT)
michael@0 4493 if (d & 0xffff0000U)
michael@0 4494 pow += 16;
michael@0 4495 if (d & 0xff00ff00U)
michael@0 4496 pow += 8;
michael@0 4497 if (d & 0xf0f0f0f0U)
michael@0 4498 pow += 4;
michael@0 4499 if (d & 0xccccccccU)
michael@0 4500 pow += 2;
michael@0 4501 if (d & 0xaaaaaaaaU)
michael@0 4502 pow += 1;
michael@0 4503 #elif defined(MP_USE_LONG_LONG_DIGIT)
michael@0 4504 if (d & 0xffffffff00000000ULL)
michael@0 4505 pow += 32;
michael@0 4506 if (d & 0xffff0000ffff0000ULL)
michael@0 4507 pow += 16;
michael@0 4508 if (d & 0xff00ff00ff00ff00ULL)
michael@0 4509 pow += 8;
michael@0 4510 if (d & 0xf0f0f0f0f0f0f0f0ULL)
michael@0 4511 pow += 4;
michael@0 4512 if (d & 0xccccccccccccccccULL)
michael@0 4513 pow += 2;
michael@0 4514 if (d & 0xaaaaaaaaaaaaaaaaULL)
michael@0 4515 pow += 1;
michael@0 4516 #elif defined(MP_USE_LONG_DIGIT)
michael@0 4517 if (d & 0xffffffff00000000UL)
michael@0 4518 pow += 32;
michael@0 4519 if (d & 0xffff0000ffff0000UL)
michael@0 4520 pow += 16;
michael@0 4521 if (d & 0xff00ff00ff00ff00UL)
michael@0 4522 pow += 8;
michael@0 4523 if (d & 0xf0f0f0f0f0f0f0f0UL)
michael@0 4524 pow += 4;
michael@0 4525 if (d & 0xccccccccccccccccUL)
michael@0 4526 pow += 2;
michael@0 4527 if (d & 0xaaaaaaaaaaaaaaaaUL)
michael@0 4528 pow += 1;
michael@0 4529 #else
michael@0 4530 #error "unknown type for mp_digit"
michael@0 4531 #endif
michael@0 4532 return pow;
michael@0 4533 }
michael@0 4534 return -1;
michael@0 4535
michael@0 4536 } /* end s_mp_ispow2d() */
michael@0 4537
michael@0 4538 /* }}} */
michael@0 4539
michael@0 4540 /* }}} */
michael@0 4541
michael@0 4542 /* {{{ Primitive I/O helpers */
michael@0 4543
michael@0 4544 /* {{{ s_mp_tovalue(ch, r) */
michael@0 4545
michael@0 4546 /*
michael@0 4547 Convert the given character to its digit value, in the given radix.
michael@0 4548 If the given character is not understood in the given radix, -1 is
michael@0 4549 returned. Otherwise the digit's numeric value is returned.
michael@0 4550
michael@0 4551 The results will be odd if you use a radix < 2 or > 62, you are
michael@0 4552 expected to know what you're up to.
michael@0 4553 */
michael@0 4554 int s_mp_tovalue(char ch, int r)
michael@0 4555 {
michael@0 4556 int val, xch;
michael@0 4557
michael@0 4558 if(r > 36)
michael@0 4559 xch = ch;
michael@0 4560 else
michael@0 4561 xch = toupper(ch);
michael@0 4562
michael@0 4563 if(isdigit(xch))
michael@0 4564 val = xch - '0';
michael@0 4565 else if(isupper(xch))
michael@0 4566 val = xch - 'A' + 10;
michael@0 4567 else if(islower(xch))
michael@0 4568 val = xch - 'a' + 36;
michael@0 4569 else if(xch == '+')
michael@0 4570 val = 62;
michael@0 4571 else if(xch == '/')
michael@0 4572 val = 63;
michael@0 4573 else
michael@0 4574 return -1;
michael@0 4575
michael@0 4576 if(val < 0 || val >= r)
michael@0 4577 return -1;
michael@0 4578
michael@0 4579 return val;
michael@0 4580
michael@0 4581 } /* end s_mp_tovalue() */
michael@0 4582
michael@0 4583 /* }}} */
michael@0 4584
michael@0 4585 /* {{{ s_mp_todigit(val, r, low) */
michael@0 4586
michael@0 4587 /*
michael@0 4588 Convert val to a radix-r digit, if possible. If val is out of range
michael@0 4589 for r, returns zero. Otherwise, returns an ASCII character denoting
michael@0 4590 the value in the given radix.
michael@0 4591
michael@0 4592 The results may be odd if you use a radix < 2 or > 64, you are
michael@0 4593 expected to know what you're doing.
michael@0 4594 */
michael@0 4595
michael@0 4596 char s_mp_todigit(mp_digit val, int r, int low)
michael@0 4597 {
michael@0 4598 char ch;
michael@0 4599
michael@0 4600 if(val >= r)
michael@0 4601 return 0;
michael@0 4602
michael@0 4603 ch = s_dmap_1[val];
michael@0 4604
michael@0 4605 if(r <= 36 && low)
michael@0 4606 ch = tolower(ch);
michael@0 4607
michael@0 4608 return ch;
michael@0 4609
michael@0 4610 } /* end s_mp_todigit() */
michael@0 4611
michael@0 4612 /* }}} */
michael@0 4613
michael@0 4614 /* {{{ s_mp_outlen(bits, radix) */
michael@0 4615
michael@0 4616 /*
michael@0 4617 Return an estimate for how long a string is needed to hold a radix
michael@0 4618 r representation of a number with 'bits' significant bits, plus an
michael@0 4619 extra for a zero terminator (assuming C style strings here)
michael@0 4620 */
michael@0 4621 int s_mp_outlen(int bits, int r)
michael@0 4622 {
michael@0 4623 return (int)((double)bits * LOG_V_2(r) + 1.5) + 1;
michael@0 4624
michael@0 4625 } /* end s_mp_outlen() */
michael@0 4626
michael@0 4627 /* }}} */
michael@0 4628
michael@0 4629 /* }}} */
michael@0 4630
michael@0 4631 /* {{{ mp_read_unsigned_octets(mp, str, len) */
michael@0 4632 /* mp_read_unsigned_octets(mp, str, len)
michael@0 4633 Read in a raw value (base 256) into the given mp_int
michael@0 4634 No sign bit, number is positive. Leading zeros ignored.
michael@0 4635 */
michael@0 4636
michael@0 4637 mp_err
michael@0 4638 mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len)
michael@0 4639 {
michael@0 4640 int count;
michael@0 4641 mp_err res;
michael@0 4642 mp_digit d;
michael@0 4643
michael@0 4644 ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
michael@0 4645
michael@0 4646 mp_zero(mp);
michael@0 4647
michael@0 4648 count = len % sizeof(mp_digit);
michael@0 4649 if (count) {
michael@0 4650 for (d = 0; count-- > 0; --len) {
michael@0 4651 d = (d << 8) | *str++;
michael@0 4652 }
michael@0 4653 MP_DIGIT(mp, 0) = d;
michael@0 4654 }
michael@0 4655
michael@0 4656 /* Read the rest of the digits */
michael@0 4657 for(; len > 0; len -= sizeof(mp_digit)) {
michael@0 4658 for (d = 0, count = sizeof(mp_digit); count > 0; --count) {
michael@0 4659 d = (d << 8) | *str++;
michael@0 4660 }
michael@0 4661 if (MP_EQ == mp_cmp_z(mp)) {
michael@0 4662 if (!d)
michael@0 4663 continue;
michael@0 4664 } else {
michael@0 4665 if((res = s_mp_lshd(mp, 1)) != MP_OKAY)
michael@0 4666 return res;
michael@0 4667 }
michael@0 4668 MP_DIGIT(mp, 0) = d;
michael@0 4669 }
michael@0 4670 return MP_OKAY;
michael@0 4671 } /* end mp_read_unsigned_octets() */
michael@0 4672 /* }}} */
michael@0 4673
michael@0 4674 /* {{{ mp_unsigned_octet_size(mp) */
michael@0 4675 int
michael@0 4676 mp_unsigned_octet_size(const mp_int *mp)
michael@0 4677 {
michael@0 4678 int bytes;
michael@0 4679 int ix;
michael@0 4680 mp_digit d = 0;
michael@0 4681
michael@0 4682 ARGCHK(mp != NULL, MP_BADARG);
michael@0 4683 ARGCHK(MP_ZPOS == SIGN(mp), MP_BADARG);
michael@0 4684
michael@0 4685 bytes = (USED(mp) * sizeof(mp_digit));
michael@0 4686
michael@0 4687 /* subtract leading zeros. */
michael@0 4688 /* Iterate over each digit... */
michael@0 4689 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 4690 d = DIGIT(mp, ix);
michael@0 4691 if (d)
michael@0 4692 break;
michael@0 4693 bytes -= sizeof(d);
michael@0 4694 }
michael@0 4695 if (!bytes)
michael@0 4696 return 1;
michael@0 4697
michael@0 4698 /* Have MSD, check digit bytes, high order first */
michael@0 4699 for(ix = sizeof(mp_digit) - 1; ix >= 0; ix--) {
michael@0 4700 unsigned char x = (unsigned char)(d >> (ix * CHAR_BIT));
michael@0 4701 if (x)
michael@0 4702 break;
michael@0 4703 --bytes;
michael@0 4704 }
michael@0 4705 return bytes;
michael@0 4706 } /* end mp_unsigned_octet_size() */
michael@0 4707 /* }}} */
michael@0 4708
michael@0 4709 /* {{{ mp_to_unsigned_octets(mp, str) */
michael@0 4710 /* output a buffer of big endian octets no longer than specified. */
michael@0 4711 mp_err
michael@0 4712 mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
michael@0 4713 {
michael@0 4714 int ix, pos = 0;
michael@0 4715 int bytes;
michael@0 4716
michael@0 4717 ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
michael@0 4718
michael@0 4719 bytes = mp_unsigned_octet_size(mp);
michael@0 4720 ARGCHK(bytes >= 0 && bytes <= maxlen, MP_BADARG);
michael@0 4721
michael@0 4722 /* Iterate over each digit... */
michael@0 4723 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 4724 mp_digit d = DIGIT(mp, ix);
michael@0 4725 int jx;
michael@0 4726
michael@0 4727 /* Unpack digit bytes, high order first */
michael@0 4728 for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
michael@0 4729 unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
michael@0 4730 if (!pos && !x) /* suppress leading zeros */
michael@0 4731 continue;
michael@0 4732 str[pos++] = x;
michael@0 4733 }
michael@0 4734 }
michael@0 4735 if (!pos)
michael@0 4736 str[pos++] = 0;
michael@0 4737 return pos;
michael@0 4738 } /* end mp_to_unsigned_octets() */
michael@0 4739 /* }}} */
michael@0 4740
michael@0 4741 /* {{{ mp_to_signed_octets(mp, str) */
michael@0 4742 /* output a buffer of big endian octets no longer than specified. */
michael@0 4743 mp_err
michael@0 4744 mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
michael@0 4745 {
michael@0 4746 int ix, pos = 0;
michael@0 4747 int bytes;
michael@0 4748
michael@0 4749 ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
michael@0 4750
michael@0 4751 bytes = mp_unsigned_octet_size(mp);
michael@0 4752 ARGCHK(bytes >= 0 && bytes <= maxlen, MP_BADARG);
michael@0 4753
michael@0 4754 /* Iterate over each digit... */
michael@0 4755 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 4756 mp_digit d = DIGIT(mp, ix);
michael@0 4757 int jx;
michael@0 4758
michael@0 4759 /* Unpack digit bytes, high order first */
michael@0 4760 for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
michael@0 4761 unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
michael@0 4762 if (!pos) {
michael@0 4763 if (!x) /* suppress leading zeros */
michael@0 4764 continue;
michael@0 4765 if (x & 0x80) { /* add one leading zero to make output positive. */
michael@0 4766 ARGCHK(bytes + 1 <= maxlen, MP_BADARG);
michael@0 4767 if (bytes + 1 > maxlen)
michael@0 4768 return MP_BADARG;
michael@0 4769 str[pos++] = 0;
michael@0 4770 }
michael@0 4771 }
michael@0 4772 str[pos++] = x;
michael@0 4773 }
michael@0 4774 }
michael@0 4775 if (!pos)
michael@0 4776 str[pos++] = 0;
michael@0 4777 return pos;
michael@0 4778 } /* end mp_to_signed_octets() */
michael@0 4779 /* }}} */
michael@0 4780
michael@0 4781 /* {{{ mp_to_fixlen_octets(mp, str) */
michael@0 4782 /* output a buffer of big endian octets exactly as long as requested. */
michael@0 4783 mp_err
michael@0 4784 mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
michael@0 4785 {
michael@0 4786 int ix, pos = 0;
michael@0 4787 int bytes;
michael@0 4788
michael@0 4789 ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
michael@0 4790
michael@0 4791 bytes = mp_unsigned_octet_size(mp);
michael@0 4792 ARGCHK(bytes >= 0 && bytes <= length, MP_BADARG);
michael@0 4793
michael@0 4794 /* place any needed leading zeros */
michael@0 4795 for (;length > bytes; --length) {
michael@0 4796 *str++ = 0;
michael@0 4797 }
michael@0 4798
michael@0 4799 /* Iterate over each digit... */
michael@0 4800 for(ix = USED(mp) - 1; ix >= 0; ix--) {
michael@0 4801 mp_digit d = DIGIT(mp, ix);
michael@0 4802 int jx;
michael@0 4803
michael@0 4804 /* Unpack digit bytes, high order first */
michael@0 4805 for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
michael@0 4806 unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
michael@0 4807 if (!pos && !x) /* suppress leading zeros */
michael@0 4808 continue;
michael@0 4809 str[pos++] = x;
michael@0 4810 }
michael@0 4811 }
michael@0 4812 if (!pos)
michael@0 4813 str[pos++] = 0;
michael@0 4814 return MP_OKAY;
michael@0 4815 } /* end mp_to_fixlen_octets() */
michael@0 4816 /* }}} */
michael@0 4817
michael@0 4818
michael@0 4819 /*------------------------------------------------------------------------*/
michael@0 4820 /* HERE THERE BE DRAGONS */

mercurial