int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) { mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; int err; if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { return err; } /* initialize, (u1,u2,u3) = (1,0,a) */ mp_set(&u1, 1); if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } /* initialize, (v1,v2,v3) = (0,1,b) */ mp_set(&v2, 1); if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } /* loop while v3 != 0 */ while (mp_iszero(&v3) == MP_NO) { /* q = u3/v3 */ if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } /* (u1,u2,u3) = (v1,v2,v3) */ if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } /* (v1,v2,v3) = (t1,t2,t3) */ if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } } /* make sure U3 >= 0 */ if (u3.sign == MP_NEG) { mp_neg(&u1, &u1); mp_neg(&u2, &u2); mp_neg(&u3, &u3); } /* copy result out */ if (U1 != NULL) { mp_exch(U1, &u1); } if (U2 != NULL) { mp_exch(U2, &u2); } if (U3 != NULL) { mp_exch(U3, &u3); } err = MP_OKAY; _ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); return err; }
/* AND two ints together */ int mp_and (mp_int * a, mp_int * b, mp_int * c) { int res, ix, px; mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } px = b->used; x = b; } else { if ((res = mp_init_copy (&t, b)) != MP_OKAY) { return res; } px = a->used; x = a; } for (ix = 0; ix < px; ix++) { t.dp[ix] &= x->dp[ix]; } /* zero digits above the last from the smallest mp_int */ for (; ix < t.used; ix++) { t.dp[ix] = 0; } mp_clamp (&t); mp_exch (c, &t); mp_clear (&t); return MP_OKAY; }
/* XOR two ints together */ int mp_xor (mp_int * a, mp_int * b, mp_int * c) { int res, ix, px; mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } px = b->used; x = b; } else { if ((res = mp_init_copy (&t, b)) != MP_OKAY) { return res; } px = a->used; x = a; } for (ix = 0; ix < px; ix++) { t.dp[ix] ^= x->dp[ix]; } mp_clamp (&t); mp_exch (c, &t); mp_clear (&t); return MP_OKAY; }
/* c = a mod b, 0 <= c < b */ int mp_mod (mp_int * a, mp_int * b, mp_int * c) { mp_int t; int res; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { mp_clear (&t); return res; } if (t.sign != b->sign) { res = mp_add (b, &t, c); } else { res = MP_OKAY; mp_exch (&t, c); } mp_clear (&t); return res; }
/* this function is less generic than mp_n_root, simpler and faster */ int mp_sqrt(mp_int *arg, mp_int *ret) { int res; mp_int t1,t2; /* must be positive */ if (arg->sign == MP_NEG) { return MP_VAL; } /* easy out */ if (mp_iszero(arg) == MP_YES) { mp_zero(ret); return MP_OKAY; } if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { return res; } if ((res = mp_init(&t2)) != MP_OKAY) { goto E2; } /* First approx. (not very bad for large arg) */ mp_rshd (&t1,t1.used/2); /* t1 > 0 */ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* And now t1 > sqrt(arg) */ do { if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* t1 >= sqrt(arg) >= t2 at this point */ } while (mp_cmp_mag(&t1,&t2) == MP_GT); mp_exch(&t1,ret); E1: mp_clear(&t2); E2: mp_clear(&t1); return res; }
/* multiplies |a| * |b| and does not compute the lower digs digits * [meant to get the higher part of the product] */ int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs) { mp_int t; int res, pa, pb, ix, iy; mp_digit u; mp_word r; mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C if (((a->used + b->used + 1) < MP_WARRAY) && (MIN(a->used, b->used) < (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) { return fast_s_mp_mul_high_digs(a, b, c, digs); } #endif if ((res = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { return res; } t.used = a->used + b->used + 1; pa = a->used; pb = b->used; for (ix = 0; ix < pa; ix++) { /* clear the carry */ u = 0; /* left hand side of A[ix] * B[iy] */ tmpx = a->dp[ix]; /* alias to the address of where the digits will be stored */ tmpt = &(t.dp[digs]); /* alias for where to read the right hand side from */ tmpy = b->dp + (digs - ix); for (iy = digs - ix; iy < pb; iy++) { /* calculate the double precision result */ r = (mp_word) * tmpt + ((mp_word)tmpx * (mp_word) * tmpy++) + (mp_word)u; /* get the lower part */ *tmpt++ = (mp_digit)(r & ((mp_word)MP_MASK)); /* carry the carry */ u = (mp_digit)(r >> ((mp_word)DIGIT_BIT)); } *tmpt = u; } mp_clamp(&t); mp_exch(&t, c); mp_clear(&t); return MP_OKAY; }
/* single digit division (based on routine from MPI) */ int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) { mp_int q; mp_word w; mp_digit t; int res, ix; if (b == 0) { return MP_VAL; } if (b == 3) { return mp_div_3(a, c, d); } if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { return res; } q.used = a->used; q.sign = a->sign; w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); if (w >= b) { t = (mp_digit)(w / b); w = w % b; } else { t = 0; } q.dp[ix] = (mp_digit)t; } if (d != NULL) { *d = (mp_digit)w; } if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); } mp_clear(&q); return res; }
/* integer signed division. * c*b + d == a [e.g. a/b, c=quotient, d=remainder] * HAC pp.598 Algorithm 14.20 * * Note that the description in HAC is horribly * incomplete. For example, it doesn't consider * the case where digits are removed from 'x' in * the inner loop. It also doesn't consider the * case that y has fewer than three digits, etc.. * * The overall algorithm is as described as * 14.20 from HAC but fixed to treat these cases. */ int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int q, x, y, t1, t2; int res, n, t, i, norm, neg; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { return res; } q.used = a->used + 2; if ((res = mp_init (&t1)) != MP_OKAY) { goto LBL_Q; } if ((res = mp_init (&t2)) != MP_OKAY) { goto LBL_T1; } if ((res = mp_init_copy (&x, a)) != MP_OKAY) { goto LBL_T2; } if ((res = mp_init_copy (&y, b)) != MP_OKAY) { goto LBL_X; } /* fix the sign */ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; x.sign = y.sign = MP_ZPOS; /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ norm = mp_count_bits(&y) % DIGIT_BIT; if (norm < (int)(DIGIT_BIT-1)) { norm = (DIGIT_BIT-1) - norm; if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { goto LBL_Y; } } else { norm = 0; } /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ n = x.used - 1; t = y.used - 1; /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ goto LBL_Y; } while (mp_cmp (&x, &y) != MP_LT) { ++(q.dp[n - t]); if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { goto LBL_Y; } } /* reset y by shifting it back down */ mp_rshd (&y, n - t); /* step 3. for i from n down to (t + 1) */ for (i = n; i >= (t + 1); i--) { if (i > x.used) { continue; } /* step 3.1 if xi == yt then set q{i-t-1} to b-1, * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ if (x.dp[i] == y.dp[t]) { q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); } else { mp_word tmp; tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); tmp |= ((mp_word) x.dp[i - 1]); tmp /= ((mp_word) y.dp[t]); if (tmp > (mp_word) MP_MASK) tmp = MP_MASK; q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); } /* while (q{i-t-1} * (yt * b + y{t-1})) > xi * b**2 + xi-1 * b + xi-2 do q{i-t-1} -= 1; */ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; do { q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; /* find left hand */ mp_zero (&t1); t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; t1.dp[1] = y.dp[t]; t1.used = 2; if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } /* find right hand */ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; t2.dp[2] = x.dp[i]; t2.used = 3; } while (mp_cmp_mag(&t1, &t2) == MP_GT); /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ if (x.sign == MP_NEG) { if ((res = mp_copy (&y, &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; } } /* now q is the quotient and x is the remainder * [which we have to normalize] */ /* get sign before writing to c */ x.sign = x.used == 0 ? MP_ZPOS : a->sign; if (c != NULL) { mp_clamp (&q); mp_exch (&q, c); c->sign = neg; } if (d != NULL) { if ((res = mp_div_2d (&x, norm, &x, NULL)) != MP_OKAY) { goto LBL_Y; } mp_exch (&x, d); } res = MP_OKAY; LBL_Y:mp_clear (&y); LBL_X:mp_clear (&x); LBL_T2:mp_clear (&t2); LBL_T1:mp_clear (&t1); LBL_Q:mp_clear (&q); return res; }
int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res; mp_digit buf, mp; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; /* use a pointer to the reduction algorithm. This allows us to use * one of many reduction algorithms without modding the guts of * the code with if statements everywhere. */ int (*redux)(mp_int*,mp_int*,mp_digit); /* find window size */ x = mp_count_bits (X); if (x <= 7) { winsize = 2; } else if (x <= 36) { winsize = 3; } else if (x <= 140) { winsize = 4; } else if (x <= 450) { winsize = 5; } else if (x <= 1303) { winsize = 6; } else if (x <= 3529) { winsize = 7; } else { winsize = 8; } #ifdef MP_LOW_MEM if (winsize > 5) { winsize = 5; } #endif /* init M array */ /* init first cell */ if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) { return err; } /* now init the second half of the array */ for (x = 1<<(winsize-1); x < (1 << winsize); x++) { if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) { for (y = 1<<(winsize-1); y < x; y++) { mp_clear (&M[y]); } mp_clear(&M[1]); return err; } } /* determine and setup reduction code */ if (redmode == 0) { #ifdef BN_MP_MONTGOMERY_SETUP_C /* now setup montgomery */ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { goto LBL_M; } #else err = MP_VAL; goto LBL_M; #endif /* automatically pick the comba one if available (saves quite a few calls/ifs) */ #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C if ((((P->used * 2) + 1) < MP_WARRAY) && (P->used < (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) { redux = fast_mp_montgomery_reduce; } else #endif { #ifdef BN_MP_MONTGOMERY_REDUCE_C /* use slower baseline Montgomery method */ redux = mp_montgomery_reduce; #else err = MP_VAL; goto LBL_M; #endif } } else if (redmode == 1) { #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) /* setup DR reduction for moduli of the form B**k - b */ mp_dr_setup(P, &mp); redux = mp_dr_reduce; #else err = MP_VAL; goto LBL_M; #endif } else { #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) /* setup DR reduction for moduli of the form 2**k - b */ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { goto LBL_M; } redux = mp_reduce_2k; #else err = MP_VAL; goto LBL_M; #endif } /* setup result */ if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) { goto LBL_M; } /* create M table * * * The first half of the table is not computed though accept for M[0] and M[1] */ if (redmode == 0) { #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C /* now we need R mod m */ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { goto LBL_RES; } /* now set M[1] to G * R mod m */ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { goto LBL_RES; } #else err = MP_VAL; goto LBL_RES; #endif } else { mp_set(&res, 1); if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto LBL_RES; } } /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_RES; } for (x = 0; x < (winsize - 1); x++) { if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { goto LBL_RES; } } /* create upper table */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[x], P, mp)) != MP_OKAY) { goto LBL_RES; } } /* set initial mode and bit cnt */ mode = 0; bitcnt = 1; buf = 0; digidx = X->used - 1; bitcpy = 0; bitbuf = 0; for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { /* if digidx == -1 we are out of digits so break */ if (digidx == -1) { break; } /* read next digit and reset bitcnt */ buf = X->dp[digidx--]; bitcnt = (int)DIGIT_BIT; } /* grab the next msb from the exponent */ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it * These represent the leading zero bits before the first 1 bit * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ if ((mode == 0) && (y == 0)) { continue; } /* if the bit is zero and mode == 1 then we square */ if ((mode == 1) && (y == 0)) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } continue; } /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ /* square first */ for (x = 0; x < winsize; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } /* then multiply */ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } /* empty window and reset */ bitcpy = 0; bitbuf = 0; mode = 1; } } /* if bits remain then square/multiply */ if ((mode == 2) && (bitcpy > 0)) { /* square then multiply if the bit is set */ for (x = 0; x < bitcpy; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } /* get next bit of the window */ bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } } } if (redmode == 0) { /* fixup result if Montgomery reduction is used * recall that any value in a Montgomery system is * actually multiplied by R mod n. So we have * to reduce one more time to cancel out the factor * of R. */ if ((err = redux(&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } /* swap res with Y */ mp_exch (&res, Y); err = MP_OKAY; LBL_RES:mp_clear (&res); LBL_M: mp_clear(&M[1]); for (x = 1<<(winsize-1); x < (1 << winsize); x++) { mp_clear (&M[x]); } return err; }
/* Do modular exponentiation using integer multiply code. */ mp_err mp_exptmod_i(const mp_int * montBase, const mp_int * exponent, const mp_int * modulus, mp_int * result, mp_mont_modulus *mmm, int nLen, mp_size bits_in_exponent, mp_size window_bits, mp_size odd_ints) { mp_int *pa1, *pa2, *ptmp; mp_size i; mp_err res; int expOff; mp_int accum1, accum2, power2, oddPowers[MAX_ODD_INTS]; /* power2 = base ** 2; oddPowers[i] = base ** (2*i + 1); */ /* oddPowers[i] = base ** (2*i + 1); */ MP_DIGITS(&accum1) = 0; MP_DIGITS(&accum2) = 0; MP_DIGITS(&power2) = 0; for (i = 0; i < MAX_ODD_INTS; ++i) { MP_DIGITS(oddPowers + i) = 0; } MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); MP_CHECKOK( mp_init_copy(&oddPowers[0], montBase) ); mp_init_size(&power2, nLen + 2 * MP_USED(montBase) + 2); MP_CHECKOK( mp_sqr(montBase, &power2) ); /* power2 = montBase ** 2 */ MP_CHECKOK( s_mp_redc(&power2, mmm) ); for (i = 1; i < odd_ints; ++i) { mp_init_size(oddPowers + i, nLen + 2 * MP_USED(&power2) + 2); MP_CHECKOK( mp_mul(oddPowers + (i - 1), &power2, oddPowers + i) ); MP_CHECKOK( s_mp_redc(oddPowers + i, mmm) ); } /* set accumulator to montgomery residue of 1 */ mp_set(&accum1, 1); MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); pa1 = &accum1; pa2 = &accum2; for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) { mp_size smallExp; MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); smallExp = (mp_size)res; if (window_bits == 1) { if (!smallExp) { SQR(pa1,pa2); SWAPPA; } else if (smallExp & 1) { SQR(pa1,pa2); MUL(0,pa2,pa1); } else { ABORT; } } else if (window_bits == 4) { if (!smallExp) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); } else if (smallExp & 1) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/2, pa1,pa2); SWAPPA; } else if (smallExp & 2) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 4) { SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/8,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 8) { SQR(pa1,pa2); MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else { ABORT; } } else if (window_bits == 5) { if (!smallExp) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 1) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); MUL(smallExp/2,pa2,pa1); } else if (smallExp & 2) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/4,pa1,pa2); SQR(pa2,pa1); } else if (smallExp & 4) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); MUL(smallExp/8,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); } else if (smallExp & 8) { SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/16,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); } else if (smallExp & 0x10) { SQR(pa1,pa2); MUL(smallExp/32,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); } else { ABORT; } } else if (window_bits == 6) { if (!smallExp) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); } else if (smallExp & 1) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/2,pa1,pa2); SWAPPA; } else if (smallExp & 2) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 4) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/8,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 8) { SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 0x10) { SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/32,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else if (smallExp & 0x20) { SQR(pa1,pa2); MUL(smallExp/64,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else { ABORT; } } else { ABORT; } } res = s_mp_redc(pa1, mmm); mp_exch(pa1, result); CLEANUP: mp_clear(&accum1); mp_clear(&accum2); mp_clear(&power2); for (i = 0; i < odd_ints; ++i) { mp_clear(oddPowers + i); } return res; }
/* Greatest Common Divisor using the binary method */ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) { mp_int u, v; int k, u_lsb, v_lsb, res; /* either zero than gcd is the largest */ if (mp_iszero (a) == MP_YES) { return mp_abs (b, c); } if (mp_iszero (b) == MP_YES) { return mp_abs (a, c); } /* get copies of a and b we can modify */ if ((res = mp_init_copy (&u, a)) != MP_OKAY) { return res; } if ((res = mp_init_copy (&v, b)) != MP_OKAY) { goto LBL_U; } /* must be positive for the remainder of the algorithm */ u.sign = v.sign = MP_ZPOS; /* B1. Find the common power of two for u and v */ u_lsb = mp_cnt_lsb(&u); v_lsb = mp_cnt_lsb(&v); k = MIN(u_lsb, v_lsb); if (k > 0) { /* divide the power of two out */ if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { goto LBL_V; } if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { goto LBL_V; } } /* divide any remaining factors of two out */ if (u_lsb != k) { if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { goto LBL_V; } } if (v_lsb != k) { if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { goto LBL_V; } } while (mp_iszero(&v) == MP_NO) { /* make sure v is the largest */ if (mp_cmp_mag(&u, &v) == MP_GT) { /* swap u and v to make sure v is >= u */ mp_exch(&u, &v); } /* subtract smallest from largest */ if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { goto LBL_V; } /* Divide out all factors of two */ if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { goto LBL_V; } } /* multiply by 2**k which we divided out at the beginning */ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { goto LBL_V; } c->sign = MP_ZPOS; res = MP_OKAY; LBL_V:mp_clear (&u); LBL_U:mp_clear (&v); return res; }
/* find the n'th root of an integer * * Result found such that (c)**b <= a and (c+1)**b > a * * This algorithm uses Newton's approximation * x[i+1] = x[i] - f(x[i])/f'(x[i]) * which will find the root in log(N) time where * each step involves a fair bit. This is not meant to * find huge roots [square and cube, etc]. */ int mp_n_root (mp_int * a, mp_digit b, mp_int * c) { mp_int t1, t2, t3; int res, neg; /* input must be positive if b is even */ if ((b & 1) == 0 && a->sign == MP_NEG) { return MP_VAL; } if ((res = mp_init (&t1)) != MP_OKAY) { return res; } if ((res = mp_init (&t2)) != MP_OKAY) { goto LBL_T1; } if ((res = mp_init (&t3)) != MP_OKAY) { goto LBL_T2; } /* if a is negative fudge the sign but keep track */ neg = a->sign; a->sign = MP_ZPOS; /* t2 = 2 */ mp_set (&t2, 2); do { /* t1 = t2 */ if ((res = mp_copy (&t2, &t1)) != MP_OKAY) { goto LBL_T3; } /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ /* t3 = t1**(b-1) */ if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) { goto LBL_T3; } /* numerator */ /* t2 = t1**b */ if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) { goto LBL_T3; } /* t2 = t1**b - a */ if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) { goto LBL_T3; } /* denominator */ /* t3 = t1**(b-1) * b */ if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) { goto LBL_T3; } /* t3 = (t1**b - a)/(b * t1**(b-1)) */ if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) { goto LBL_T3; } if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) { goto LBL_T3; } } while (mp_cmp (&t1, &t2) != MP_EQ); /* result can be off by a few so check */ for (;;) { if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) { goto LBL_T3; } if (mp_cmp (&t2, a) == MP_GT) { if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { goto LBL_T3; } } else { break; } } /* reset the sign of a first */ a->sign = neg; /* set the result */ mp_exch (&t1, c); /* set the sign of the result */ c->sign = neg; res = MP_OKAY; LBL_T3:mp_clear (&t3); LBL_T2:mp_clear (&t2); LBL_T1:mp_clear (&t1); return res; }
/* slower bit-bang division... also smaller */ int mp_div MPA(mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int ta, tb, tq, q; int res, n, n2; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } /* init our temps */ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { return res; } mp_set(&tq, 1); n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { goto LBL_ERR; } while (n-- >= 0) { if (mp_cmp(&tb, &ta) != MP_GT) { if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { goto LBL_ERR; } } if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { goto LBL_ERR; } } /* now q == quotient and ta == remainder */ n = a->sign; n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); if (c != NULL) { mp_exch(c, &q); c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; } if (d != NULL) { mp_exch(d, &ta); d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; } LBL_ERR: mp_clear_multi(&ta, &tb, &tq, &q, NULL); return res; }
/* * take a private key with only a few elements and fill out the missing pieces. * * All the entries will be overwritten with data allocated out of the arena * If no arena is supplied, one will be created. * * The following fields must be supplied in order for this function * to succeed: * one of either publicExponent or privateExponent * two more of the following 5 parameters. * modulus (n) * prime1 (p) * prime2 (q) * publicExponent (e) * privateExponent (d) * * NOTE: if only the publicExponent, privateExponent, and one prime is given, * then there may be more than one RSA key that matches that combination. * * All parameters will be replaced in the key structure with new parameters * Allocated out of the arena. There is no attempt to free the old structures. * Prime1 will always be greater than prime2 (even if the caller supplies the * smaller prime as prime1 or the larger prime as prime2). The parameters are * not overwritten on failure. * * How it works: * We can generate all the parameters from: * one of the exponents, plus the two primes. (rsa_build_key_from_primes) * * If we are given one of the exponents and both primes, we are done. * If we are given one of the exponents, the modulus and one prime, we * caclulate the second prime by dividing the modulus by the given * prime, giving us and exponent and 2 primes. * If we are given 2 exponents and either the modulus or one of the primes * we calculate k*phi = d*e-1, where k is an integer less than d which * divides d*e-1. We find factor k so we can isolate phi. * phi = (p-1)(q-1) * If one of the primes are given, we can use phi to find the other prime * as follows: q = (phi/(p-1)) + 1. We now have 2 primes and an * exponent. (NOTE: if more then one prime meets this condition, the * operation will fail. See comments elsewhere in this file about this). * If the modulus is given, then we can calculate the sum of the primes * as follows: s := (p+q), phi = (p-1)(q-1) = pq -p - q +1, pq = n -> * phi = n - s + 1, s = n - phi +1. Now that we have s = p+q and n=pq, * we can solve our 2 equations and 2 unknowns as follows: q=s-p -> * n=p*(s-p)= sp -p^2 -> p^2-sp+n = 0. Using the quadratic to solve for * p, p=1/2*(s+ sqrt(s*s-4*n)) [q=1/2*(s-sqrt(s*s-4*n)]. We again have * 2 primes and an exponent. * */ SECStatus RSA_PopulatePrivateKey(RSAPrivateKey *key) { PLArenaPool *arena = NULL; PRBool needPublicExponent = PR_TRUE; PRBool needPrivateExponent = PR_TRUE; PRBool hasModulus = PR_FALSE; unsigned int keySizeInBits = 0; int prime_count = 0; /* standard RSA nominclature */ mp_int p, q, e, d, n; /* remainder */ mp_int r; mp_err err = 0; SECStatus rv = SECFailure; MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&e) = 0; MP_DIGITS(&d) = 0; MP_DIGITS(&n) = 0; MP_DIGITS(&r) = 0; CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&d) ); CHECK_MPI_OK( mp_init(&n) ); CHECK_MPI_OK( mp_init(&r) ); /* if the key didn't already have an arena, create one. */ if (key->arena == NULL) { arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); if (!arena) { goto cleanup; } key->arena = arena; } /* load up the known exponents */ if (key->publicExponent.data) { SECITEM_TO_MPINT(key->publicExponent, &e); needPublicExponent = PR_FALSE; } if (key->privateExponent.data) { SECITEM_TO_MPINT(key->privateExponent, &d); needPrivateExponent = PR_FALSE; } if (needPrivateExponent && needPublicExponent) { /* Not enough information, we need at least one exponent */ err = MP_BADARG; goto cleanup; } /* load up the known primes. If only one prime is given, it will be * assigned 'p'. Once we have both primes, well make sure p is the larger. * The value prime_count tells us howe many we have acquired. */ if (key->prime1.data) { int primeLen = key->prime1.len; if (key->prime1.data[0] == 0) { primeLen--; } keySizeInBits = primeLen * 2 * PR_BITS_PER_BYTE; SECITEM_TO_MPINT(key->prime1, &p); prime_count++; } if (key->prime2.data) { int primeLen = key->prime2.len; if (key->prime2.data[0] == 0) { primeLen--; } keySizeInBits = primeLen * 2 * PR_BITS_PER_BYTE; SECITEM_TO_MPINT(key->prime2, prime_count ? &q : &p); prime_count++; } /* load up the modulus */ if (key->modulus.data) { int modLen = key->modulus.len; if (key->modulus.data[0] == 0) { modLen--; } keySizeInBits = modLen * PR_BITS_PER_BYTE; SECITEM_TO_MPINT(key->modulus, &n); hasModulus = PR_TRUE; } /* if we have the modulus and one prime, calculate the second. */ if ((prime_count == 1) && (hasModulus)) { mp_div(&n,&p,&q,&r); if (mp_cmp_z(&r) != 0) { /* p is not a factor or n, fail */ err = MP_BADARG; goto cleanup; } prime_count++; } /* If we didn't have enough primes try to calculate the primes from * the exponents */ if (prime_count < 2) { /* if we don't have at least 2 primes at this point, then we need both * exponents and one prime or a modulus*/ if (!needPublicExponent && !needPrivateExponent && ((prime_count > 0) || hasModulus)) { CHECK_MPI_OK(rsa_get_primes_from_exponents(&e,&d,&p,&q, &n,hasModulus,keySizeInBits)); } else { /* not enough given parameters to get both primes */ err = MP_BADARG; goto cleanup; } } /* force p to the the larger prime */ if (mp_cmp(&p, &q) < 0) mp_exch(&p, &q); /* we now have our 2 primes and at least one exponent, we can fill * in the key */ rv = rsa_build_from_primes(&p, &q, &e, needPublicExponent, &d, needPrivateExponent, key, keySizeInBits); cleanup: mp_clear(&p); mp_clear(&q); mp_clear(&e); mp_clear(&d); mp_clear(&n); mp_clear(&r); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } if (rv && arena) { PORT_FreeArena(arena, PR_TRUE); key->arena = NULL; } return rv; }
/* hac 14.61, pp608 */ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) { mp_int x, y, u, v, A, B, C, D; int res; /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == 1) { return MP_VAL; } /* init temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL)) != MP_OKAY) { return res; } /* x = a, y = b */ if ((res = mp_mod(a, b, &x)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (b, &y)) != MP_OKAY) { goto LBL_ERR; } /* 2. [modified] if x,y are both even then return an error! */ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { res = MP_VAL; goto LBL_ERR; } /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ if ((res = mp_copy (&x, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } mp_set (&A, 1); mp_set (&D, 1); top: /* 4. while u is even do */ while (mp_iseven (&u) == 1) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if A or B is odd then */ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { /* A = (A+y)/2, B = (B-x)/2 */ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { goto LBL_ERR; } } /* A = A/2, B = B/2 */ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { goto LBL_ERR; } } /* 5. while v is even do */ while (mp_iseven (&v) == 1) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if C or D is odd then */ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { /* C = (C+y)/2, D = (D-x)/2 */ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { goto LBL_ERR; } } /* C = C/2, D = D/2 */ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { goto LBL_ERR; } } /* 6. if u >= v then */ if (mp_cmp (&u, &v) != MP_LT) { /* u = u - v, A = A - C, B = B - D */ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { goto LBL_ERR; } } else { /* v - v - u, C = C - A, D = D - B */ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { goto LBL_ERR; } } /* if not zero goto step 4 */ if (mp_iszero (&u) == 0) goto top; /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ if (mp_cmp_d (&v, 1) != MP_EQ) { res = MP_VAL; goto LBL_ERR; } /* if its too low */ while (mp_cmp_d(&C, 0) == MP_LT) { if ((res = mp_add(&C, b, &C)) != MP_OKAY) { goto LBL_ERR; } } /* too big */ while (mp_cmp_mag(&C, b) != MP_LT) { if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { goto LBL_ERR; } } /* C is now the inverse */ mp_exch (&C, c); res = MP_OKAY; LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); return res; }
static SECStatus get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen, mp_int *f, mp_int *g) { RSABlindingParams *rsabp = NULL; blindingParams *bpUnlinked = NULL; blindingParams *bp, *prevbp = NULL; PRCList *el; SECStatus rv = SECSuccess; mp_err err = MP_OKAY; int cmp = -1; PRBool holdingLock = PR_FALSE; do { if (blindingParamsList.lock == NULL) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } /* Acquire the list lock */ PZ_Lock(blindingParamsList.lock); holdingLock = PR_TRUE; /* Walk the list looking for the private key */ for (el = PR_NEXT_LINK(&blindingParamsList.head); el != &blindingParamsList.head; el = PR_NEXT_LINK(el)) { rsabp = (RSABlindingParams *)el; cmp = SECITEM_CompareItem(&rsabp->modulus, &key->modulus); if (cmp >= 0) { /* The key is found or not in the list. */ break; } } if (cmp) { /* At this point, the key is not in the list. el should point to ** the list element before which this key should be inserted. */ rsabp = PORT_ZNew(RSABlindingParams); if (!rsabp) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto cleanup; } rv = init_blinding_params(rsabp, key, n, modLen); if (rv != SECSuccess) { PORT_ZFree(rsabp, sizeof(RSABlindingParams)); goto cleanup; } /* Insert the new element into the list ** If inserting in the middle of the list, el points to the link ** to insert before. Otherwise, the link needs to be appended to ** the end of the list, which is the same as inserting before the ** head (since el would have looped back to the head). */ PR_INSERT_BEFORE(&rsabp->link, el); } /* We've found (or created) the RSAblindingParams struct for this key. * Now, search its list of ready blinding params for a usable one. */ while (0 != (bp = rsabp->bp)) { if (--(bp->counter) > 0) { /* Found a match and there are still remaining uses left */ /* Return the parameters */ CHECK_MPI_OK( mp_copy(&bp->f, f) ); CHECK_MPI_OK( mp_copy(&bp->g, g) ); PZ_Unlock(blindingParamsList.lock); return SECSuccess; } /* exhausted this one, give its values to caller, and * then retire it. */ mp_exch(&bp->f, f); mp_exch(&bp->g, g); mp_clear( &bp->f ); mp_clear( &bp->g ); bp->counter = 0; /* Move to free list */ rsabp->bp = bp->next; bp->next = rsabp->free; rsabp->free = bp; /* In case there're threads waiting for new blinding * value - notify 1 thread the value is ready */ if (blindingParamsList.waitCount > 0) { PR_NotifyCondVar( blindingParamsList.cVar ); blindingParamsList.waitCount--; } PZ_Unlock(blindingParamsList.lock); return SECSuccess; } /* We did not find a usable set of blinding params. Can we make one? */ /* Find a free bp struct. */ prevbp = NULL; if ((bp = rsabp->free) != NULL) { /* unlink this bp */ rsabp->free = bp->next; bp->next = NULL; bpUnlinked = bp; /* In case we fail */ PZ_Unlock(blindingParamsList.lock); holdingLock = PR_FALSE; /* generate blinding parameter values for the current thread */ CHECK_SEC_OK( generate_blinding_params(key, f, g, n, modLen ) ); /* put the blinding parameter values into cache */ CHECK_MPI_OK( mp_init( &bp->f) ); CHECK_MPI_OK( mp_init( &bp->g) ); CHECK_MPI_OK( mp_copy( f, &bp->f) ); CHECK_MPI_OK( mp_copy( g, &bp->g) ); /* Put this at head of queue of usable params. */ PZ_Lock(blindingParamsList.lock); holdingLock = PR_TRUE; /* initialize RSABlindingParamsStr */ bp->counter = RSA_BLINDING_PARAMS_MAX_REUSE; bp->next = rsabp->bp; rsabp->bp = bp; bpUnlinked = NULL; /* In case there're threads waiting for new blinding value * just notify them the value is ready */ if (blindingParamsList.waitCount > 0) { PR_NotifyAllCondVar( blindingParamsList.cVar ); blindingParamsList.waitCount = 0; } PZ_Unlock(blindingParamsList.lock); return SECSuccess; } /* Here, there are no usable blinding parameters available, * and no free bp blocks, presumably because they're all * actively having parameters generated for them. * So, we need to wait here and not eat up CPU until some * change happens. */ blindingParamsList.waitCount++; PR_WaitCondVar( blindingParamsList.cVar, PR_INTERVAL_NO_TIMEOUT ); PZ_Unlock(blindingParamsList.lock); holdingLock = PR_FALSE; } while (1); cleanup: /* It is possible to reach this after the lock is already released. */ if (bpUnlinked) { if (!holdingLock) { PZ_Lock(blindingParamsList.lock); holdingLock = PR_TRUE; } bp = bpUnlinked; mp_clear( &bp->f ); mp_clear( &bp->g ); bp->counter = 0; /* Must put the unlinked bp back on the free list */ bp->next = rsabp->free; rsabp->free = bp; } if (holdingLock) { PZ_Unlock(blindingParamsList.lock); holdingLock = PR_FALSE; } if (err) { MP_TO_SEC_ERROR(err); } return SECFailure; }
/* ** Generate and return a new RSA public and private key. ** Both keys are encoded in a single RSAPrivateKey structure. ** "cx" is the random number generator context ** "keySizeInBits" is the size of the key to be generated, in bits. ** 512, 1024, etc. ** "publicExponent" when not NULL is a pointer to some data that ** represents the public exponent to use. The data is a byte ** encoded integer, in "big endian" order. */ RSAPrivateKey * RSA_NewKey(int keySizeInBits, SECItem *publicExponent) { unsigned int primeLen; mp_int p, q, e, d; int kiter; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; int prerr = 0; RSAPrivateKey *key = NULL; PLArenaPool *arena = NULL; /* Require key size to be a multiple of 16 bits. */ if (!publicExponent || keySizeInBits % 16 != 0 || BAD_RSA_KEY_SIZE(keySizeInBits/8, publicExponent->len)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } /* 1. Allocate arena & key */ arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); if (!arena) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } key = PORT_ArenaZNew(arena, RSAPrivateKey); if (!key) { PORT_SetError(SEC_ERROR_NO_MEMORY); PORT_FreeArena(arena, PR_TRUE); return NULL; } key->arena = arena; /* length of primes p and q (in bytes) */ primeLen = keySizeInBits / (2 * PR_BITS_PER_BYTE); MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&e) = 0; MP_DIGITS(&d) = 0; CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&d) ); /* 2. Set the version number (PKCS1 v1.5 says it should be zero) */ SECITEM_AllocItem(arena, &key->version, 1); key->version.data[0] = 0; /* 3. Set the public exponent */ SECITEM_TO_MPINT(*publicExponent, &e); kiter = 0; do { prerr = 0; PORT_SetError(0); CHECK_SEC_OK( generate_prime(&p, primeLen) ); CHECK_SEC_OK( generate_prime(&q, primeLen) ); /* Assure q < p */ if (mp_cmp(&p, &q) < 0) mp_exch(&p, &q); /* Attempt to use these primes to generate a key */ rv = rsa_build_from_primes(&p, &q, &e, PR_FALSE, /* needPublicExponent=false */ &d, PR_TRUE, /* needPrivateExponent=true */ key, keySizeInBits); if (rv == SECSuccess) break; /* generated two good primes */ prerr = PORT_GetError(); kiter++; /* loop until have primes */ } while (prerr == SEC_ERROR_NEED_RANDOM && kiter < MAX_KEY_GEN_ATTEMPTS); if (prerr) goto cleanup; cleanup: mp_clear(&p); mp_clear(&q); mp_clear(&e); mp_clear(&d); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } if (rv && arena) { PORT_FreeArena(arena, PR_TRUE); key = NULL; } return key; }
/* computes the modular inverse via binary extended euclidean algorithm, * that is c = 1/a mod b * * Based on slow invmod except this is optimized for the case where b is * odd as per HAC Note 14.64 on pp. 610 */ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) { mp_int x, y, u, v, B, D; int res, neg; /* 2. [modified] b must be odd */ if (mp_iseven (b) == 1) { return MP_VAL; } /* init all our temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { return res; } /* x == modulus, y == value to invert */ if ((res = mp_copy (b, &x)) != MP_OKAY) { goto LBL_ERR; } /* we need y = |a| */ if ((res = mp_mod (a, b, &y)) != MP_OKAY) { goto LBL_ERR; } /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ if ((res = mp_copy (&x, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } mp_set (&D, 1); top: /* 4. while u is even do */ while (mp_iseven (&u) == 1) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if B is odd then */ if (mp_isodd (&B) == 1) { if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { goto LBL_ERR; } } /* B = B/2 */ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { goto LBL_ERR; } } /* 5. while v is even do */ while (mp_iseven (&v) == 1) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if D is odd then */ if (mp_isodd (&D) == 1) { /* D = (D-x)/2 */ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { goto LBL_ERR; } } /* D = D/2 */ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { goto LBL_ERR; } } /* 6. if u >= v then */ if (mp_cmp (&u, &v) != MP_LT) { /* u = u - v, B = B - D */ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { goto LBL_ERR; } } else { /* v - v - u, D = D - B */ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { goto LBL_ERR; } } /* if not zero goto step 4 */ if (mp_iszero (&u) == 0) { goto top; } /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ if (mp_cmp_d (&v, 1) != MP_EQ) { res = MP_VAL; goto LBL_ERR; } /* b is now the inverse */ neg = a->sign; while (D.sign == MP_NEG) { if ((res = mp_add (&D, b, &D)) != MP_OKAY) { goto LBL_ERR; } } mp_exch (&D, c); c->sign = neg; res = MP_OKAY; LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); return res; }
/** Create a DSA key @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param key [out] Where to store the created key @return CRYPT_OK if successful, upon error this function will free all allocated memory */ int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) { void *tmp, *tmp2; int err, res; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* check prng */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } /* check size */ if (group_size >= MDSA_MAX_GROUP || group_size <= 15 || group_size >= modulus_size || (modulus_size - group_size) >= MDSA_DELTA) { return CRYPT_INVALID_ARG; } /* allocate ram */ buf = XMALLOC(MDSA_DELTA); if (buf == NULL) { return CRYPT_MEM; } /* init mp_ints */ if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { XFREE(buf); return err; } /* make our prime q */ if ((err = rand_prime(key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error; } /* double q */ if ((err = mp_add(key->q, key->q, tmp)) != CRYPT_OK) { goto error; } /* now make a random string and multply it against q */ if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) { err = CRYPT_ERROR_READPRNG; goto error; } /* force magnitude */ buf[0] |= 0xC0; /* force even */ buf[modulus_size - group_size - 1] &= ~1; if ((err = mp_read_unsigned_bin(tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; } if ((err = mp_mul(key->q, tmp2, key->p)) != CRYPT_OK) { goto error; } if ((err = mp_add_d(key->p, 1, key->p)) != CRYPT_OK) { goto error; } /* now loop until p is prime */ for (;;) { if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { goto error; } if (res == LTC_MP_YES) break; /* add 2q to p and 2 to tmp2 */ if ((err = mp_add(tmp, key->p, key->p)) != CRYPT_OK) { goto error; } if ((err = mp_add_d(tmp2, 2, tmp2)) != CRYPT_OK) { goto error; } } /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */ mp_set(key->g, 1); do { if ((err = mp_add_d(key->g, 1, key->g)) != CRYPT_OK) { goto error; } if ((err = mp_exptmod(key->g, tmp2, key->p, tmp)) != CRYPT_OK) { goto error; } } while (mp_cmp_d(tmp, 1) == LTC_MP_EQ); /* at this point tmp generates a group of order q mod p */ mp_exch(tmp, key->g); /* so now we have our DH structure, generator g, order q, modulus p Now we need a random exponent [mod q] and it's power g^x mod p */ do { if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) { err = CRYPT_ERROR_READPRNG; goto error; } if ((err = mp_read_unsigned_bin(key->x, buf, group_size)) != CRYPT_OK) { goto error; } } while (mp_cmp_d(key->x, 1) != LTC_MP_GT); if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto error; } key->type = PK_PRIVATE; key->qord = group_size; #ifdef LTC_CLEAN_STACK zeromem(buf, MDSA_DELTA); #endif err = CRYPT_OK; goto done; error: mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); done: mp_clear_multi(tmp, tmp2, NULL); XFREE(buf); return err; }
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong, unsigned long * nTries) { mp_digit np; mp_err res; int i = 0; mp_int trial; mp_int q; mp_size num_tests; unsigned char *sieve; ARGCHK(start != 0, MP_BADARG); ARGCHK(nBits > 16, MP_RANGE); sieve = malloc(SIEVE_SIZE); ARGCHK(sieve != NULL, MP_MEM); MP_DIGITS(&trial) = 0; MP_DIGITS(&q) = 0; MP_CHECKOK( mp_init(&trial) ); MP_CHECKOK( mp_init(&q) ); /* values taken from table 4.4, HandBook of Applied Cryptography */ if (nBits >= 1300) { num_tests = 2; } else if (nBits >= 850) { num_tests = 3; } else if (nBits >= 650) { num_tests = 4; } else if (nBits >= 550) { num_tests = 5; } else if (nBits >= 450) { num_tests = 6; } else if (nBits >= 400) { num_tests = 7; } else if (nBits >= 350) { num_tests = 8; } else if (nBits >= 300) { num_tests = 9; } else if (nBits >= 250) { num_tests = 12; } else if (nBits >= 200) { num_tests = 15; } else if (nBits >= 150) { num_tests = 18; } else if (nBits >= 100) { num_tests = 27; } else num_tests = 50; if (strong) --nBits; MP_CHECKOK( mpl_set_bit(start, nBits - 1, 1) ); MP_CHECKOK( mpl_set_bit(start, 0, 1) ); for (i = mpl_significant_bits(start) - 1; i >= nBits; --i) { MP_CHECKOK( mpl_set_bit(start, i, 0) ); } /* start sieveing with prime value of 3. */ MP_CHECKOK(mpp_sieve(start, prime_tab + 1, prime_tab_size - 1, sieve, SIEVE_SIZE) ); #ifdef DEBUG_SIEVE res = 0; for (i = 0; i < SIEVE_SIZE; ++i) { if (!sieve[i]) ++res; } fprintf(stderr,"sieve found %d potential primes.\n", res); #define FPUTC(x,y) fputc(x,y) #else #define FPUTC(x,y) #endif res = MP_NO; for(i = 0; i < SIEVE_SIZE; ++i) { if (sieve[i]) /* this number is composite */ continue; MP_CHECKOK( mp_add_d(start, 2 * i, &trial) ); FPUTC('.', stderr); /* run a Fermat test */ res = mpp_fermat(&trial, 2); if (res != MP_OKAY) { if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } FPUTC('+', stderr); /* If that passed, run some Miller-Rabin tests */ res = mpp_pprime(&trial, num_tests); if (res != MP_OKAY) { if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } FPUTC('!', stderr); if (!strong) break; /* success !! */ /* At this point, we have strong evidence that our candidate is itself prime. If we want a strong prime, we need now to test q = 2p + 1 for primality... */ MP_CHECKOK( mp_mul_2(&trial, &q) ); MP_CHECKOK( mp_add_d(&q, 1, &q) ); /* Test q for small prime divisors ... */ np = prime_tab_size; res = mpp_divis_primes(&q, &np); if (res == MP_YES) { /* is composite */ mp_clear(&q); continue; } if (res != MP_NO) goto CLEANUP; /* And test with Fermat, as with its parent ... */ res = mpp_fermat(&q, 2); if (res != MP_YES) { mp_clear(&q); if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } /* And test with Miller-Rabin, as with its parent ... */ res = mpp_pprime(&q, num_tests); if (res != MP_YES) { mp_clear(&q); if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } /* If it passed, we've got a winner */ mp_exch(&q, &trial); mp_clear(&q); break; } /* end of loop through sieved values */ if (res == MP_YES) mp_exch(&trial, start); CLEANUP: mp_clear(&trial); mp_clear(&q); if (nTries) *nTries += i; if (sieve != NULL) { memset(sieve, 0, SIEVE_SIZE); free (sieve); } return res; }
/* Greatest Common Divisor using the binary method [Algorithm B, page 338, vol2 of TAOCP] */ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) { mp_int u, v, t; int k, res, neg; /* either zero than gcd is the largest */ if (mp_iszero (a) == 1 && mp_iszero (b) == 0) { return mp_copy (b, c); } if (mp_iszero (a) == 0 && mp_iszero (b) == 1) { return mp_copy (a, c); } if (mp_iszero (a) == 1 && mp_iszero (b) == 1) { mp_set (c, 1); return MP_OKAY; } /* if both are negative they share (-1) as a common divisor */ neg = (a->sign == b->sign) ? a->sign : MP_ZPOS; if ((res = mp_init_copy (&u, a)) != MP_OKAY) { return res; } if ((res = mp_init_copy (&v, b)) != MP_OKAY) { goto __U; } /* must be positive for the remainder of the algorithm */ u.sign = v.sign = MP_ZPOS; if ((res = mp_init (&t)) != MP_OKAY) { goto __V; } /* B1. Find power of two */ k = 0; while (mp_iseven(&u) == 1 && mp_iseven(&v) == 1) { ++k; if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto __T; } if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto __T; } } /* B2. Initialize */ if (mp_isodd(&u) == 1) { /* t = -v */ if ((res = mp_copy (&v, &t)) != MP_OKAY) { goto __T; } t.sign = MP_NEG; } else { /* t = u */ if ((res = mp_copy (&u, &t)) != MP_OKAY) { goto __T; } } do { /* B3 (and B4). Halve t, if even */ while (t.used != 0 && mp_iseven(&t) == 1) { if ((res = mp_div_2 (&t, &t)) != MP_OKAY) { goto __T; } } /* B5. if t>0 then u=t otherwise v=-t */ if (t.used != 0 && t.sign != MP_NEG) { if ((res = mp_copy (&t, &u)) != MP_OKAY) { goto __T; } } else { if ((res = mp_copy (&t, &v)) != MP_OKAY) { goto __T; } v.sign = (v.sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; } /* B6. t = u - v, if t != 0 loop otherwise terminate */ if ((res = mp_sub (&u, &v, &t)) != MP_OKAY) { goto __T; } } while (mp_iszero(&t) == 0); /* multiply by 2^k which we divided out at the beginning */ if ((res = mp_mul_2d (&u, k, &u)) != MP_OKAY) { goto __T; } mp_exch (&u, c); c->sign = neg; res = MP_OKAY; __T: mp_clear (&t); __V: mp_clear (&u); __U: mp_clear (&v); return res; }
SECStatus RSA_PrivateKeyCheck(RSAPrivateKey *key) { mp_int p, q, n, psub1, qsub1, e, d, d_p, d_q, qInv, res; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; MP_DIGITS(&n) = 0; MP_DIGITS(&psub1)= 0; MP_DIGITS(&qsub1)= 0; MP_DIGITS(&e) = 0; MP_DIGITS(&d) = 0; MP_DIGITS(&d_p) = 0; MP_DIGITS(&d_q) = 0; MP_DIGITS(&qInv) = 0; MP_DIGITS(&res) = 0; CHECK_MPI_OK( mp_init(&n) ); CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&psub1)); CHECK_MPI_OK( mp_init(&qsub1)); CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&d) ); CHECK_MPI_OK( mp_init(&d_p) ); CHECK_MPI_OK( mp_init(&d_q) ); CHECK_MPI_OK( mp_init(&qInv) ); CHECK_MPI_OK( mp_init(&res) ); SECITEM_TO_MPINT(key->modulus, &n); SECITEM_TO_MPINT(key->prime1, &p); SECITEM_TO_MPINT(key->prime2, &q); SECITEM_TO_MPINT(key->publicExponent, &e); SECITEM_TO_MPINT(key->privateExponent, &d); SECITEM_TO_MPINT(key->exponent1, &d_p); SECITEM_TO_MPINT(key->exponent2, &d_q); SECITEM_TO_MPINT(key->coefficient, &qInv); /* p > q */ if (mp_cmp(&p, &q) <= 0) { /* mind the p's and q's (and d_p's and d_q's) */ SECItem tmp; mp_exch(&p, &q); mp_exch(&d_p,&d_q); tmp = key->prime1; key->prime1 = key->prime2; key->prime2 = tmp; tmp = key->exponent1; key->exponent1 = key->exponent2; key->exponent2 = tmp; } #define VERIFY_MPI_EQUAL(m1, m2) \ if (mp_cmp(m1, m2) != 0) { \ rv = SECFailure; \ goto cleanup; \ } #define VERIFY_MPI_EQUAL_1(m) \ if (mp_cmp_d(m, 1) != 0) { \ rv = SECFailure; \ goto cleanup; \ } /* * The following errors cannot be recovered from. */ /* n == p * q */ CHECK_MPI_OK( mp_mul(&p, &q, &res) ); VERIFY_MPI_EQUAL(&res, &n); /* gcd(e, p-1) == 1 */ CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) ); CHECK_MPI_OK( mp_gcd(&e, &psub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* gcd(e, q-1) == 1 */ CHECK_MPI_OK( mp_sub_d(&q, 1, &qsub1) ); CHECK_MPI_OK( mp_gcd(&e, &qsub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* d*e == 1 mod p-1 */ CHECK_MPI_OK( mp_mulmod(&d, &e, &psub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* d*e == 1 mod q-1 */ CHECK_MPI_OK( mp_mulmod(&d, &e, &qsub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* * The following errors can be recovered from. */ /* d_p == d mod p-1 */ CHECK_MPI_OK( mp_mod(&d, &psub1, &res) ); if (mp_cmp(&d_p, &res) != 0) { /* swap in the correct value */ CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent1) ); } /* d_q == d mod q-1 */ CHECK_MPI_OK( mp_mod(&d, &qsub1, &res) ); if (mp_cmp(&d_q, &res) != 0) { /* swap in the correct value */ CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent2) ); } /* q * q**-1 == 1 mod p */ CHECK_MPI_OK( mp_mulmod(&q, &qInv, &p, &res) ); if (mp_cmp_d(&res, 1) != 0) { /* compute the correct value */ CHECK_MPI_OK( mp_invmod(&q, &p, &qInv) ); CHECK_SEC_OK( swap_in_key_value(key->arena, &qInv, &key->coefficient) ); } cleanup: mp_clear(&n); mp_clear(&p); mp_clear(&q); mp_clear(&psub1); mp_clear(&qsub1); mp_clear(&e); mp_clear(&d); mp_clear(&d_p); mp_clear(&d_q); mp_clear(&qInv); mp_clear(&res); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
/* makes a prime of at least k bits */ int pprime (int k, int li, mp_int * p, mp_int * q) { mp_int a, b, c, n, x, y, z, v; int res, ii; static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 }; /* single digit ? */ if (k <= (int) DIGIT_BIT) { mp_set (p, prime_digit ()); return MP_OKAY; } if ((res = mp_init (&c)) != MP_OKAY) { return res; } if ((res = mp_init (&v)) != MP_OKAY) { goto LBL_C; } /* product of first 50 primes */ if ((res = mp_read_radix (&v, "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", 10)) != MP_OKAY) { goto LBL_V; } if ((res = mp_init (&a)) != MP_OKAY) { goto LBL_V; } /* set the prime */ mp_set (&a, prime_digit ()); if ((res = mp_init (&b)) != MP_OKAY) { goto LBL_A; } if ((res = mp_init (&n)) != MP_OKAY) { goto LBL_B; } if ((res = mp_init (&x)) != MP_OKAY) { goto LBL_N; } if ((res = mp_init (&y)) != MP_OKAY) { goto LBL_X; } if ((res = mp_init (&z)) != MP_OKAY) { goto LBL_Y; } /* now loop making the single digit */ while (mp_count_bits (&a) < k) { fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a)); fflush (stderr); top: mp_set (&b, prime_digit ()); /* now compute z = a * b * 2 */ if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) { /* z = a * b */ goto LBL_Z; } if ((res = mp_copy (&z, &c)) != MP_OKAY) { /* c = a * b */ goto LBL_Z; } if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) { /* z = 2 * a * b */ goto LBL_Z; } /* n = z + 1 */ if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) { /* n = z + 1 */ goto LBL_Z; } /* check (n, v) == 1 */ if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */ goto LBL_Z; } if (mp_cmp_d (&y, 1) != MP_EQ) goto top; /* now try base x=bases[ii] */ for (ii = 0; ii < li; ii++) { mp_set (&x, bases[ii]); /* compute x^a mod n */ if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */ goto LBL_Z; } /* if y == 1 loop */ if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* now x^2a mod n */ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */ goto LBL_Z; } if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* compute x^b mod n */ if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */ goto LBL_Z; } /* if y == 1 loop */ if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* now x^2b mod n */ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */ goto LBL_Z; } if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* compute x^c mod n == x^ab mod n */ if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */ goto LBL_Z; } /* if y == 1 loop */ if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* now compute (x^c mod n)^2 */ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */ goto LBL_Z; } /* y should be 1 */ if (mp_cmp_d (&y, 1) != MP_EQ) continue; break; } /* no bases worked? */ if (ii == li) goto top; { char buf[4096]; mp_toradix(&n, buf, 10); printf("Certificate of primality for:\n%s\n\n", buf); mp_toradix(&a, buf, 10); printf("A == \n%s\n\n", buf); mp_toradix(&b, buf, 10); printf("B == \n%s\n\nG == %d\n", buf, bases[ii]); printf("----------------------------------------------------------------\n"); } /* a = n */ mp_copy (&n, &a); } /* get q to be the order of the large prime subgroup */ mp_sub_d (&n, 1, q); mp_div_2 (q, q); mp_div (q, &b, q, NULL); mp_exch (&n, p); res = MP_OKAY; LBL_Z:mp_clear (&z); LBL_Y:mp_clear (&y); LBL_X:mp_clear (&x); LBL_N:mp_clear (&n); LBL_B:mp_clear (&b); LBL_A:mp_clear (&a); LBL_V:mp_clear (&v); LBL_C:mp_clear (&c); return res; }
void swap( mpint &target ) { mp_exch( &value, &target.value ); }
/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ int s_mp_sqr (mp_int * a, mp_int * b) { mp_int t; int res, ix, iy, pa; mp_word r; mp_digit u, tmpx, *tmpt; pa = a->used; if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { return res; } /* default used is maximum possible size */ t.used = 2*pa + 1; for (ix = 0; ix < pa; ix++) { /* first calculate the digit at 2*ix */ /* calculate double precision result */ r = ((mp_word) t.dp[2*ix]) + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); /* store lower part in result */ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); /* left hand side of A[ix] * A[iy] */ tmpx = a->dp[ix]; /* alias for where to store the results */ tmpt = t.dp + (2*ix + 1); for (iy = ix + 1; iy < pa; iy++) { /* first calculate the product */ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); /* now calculate the double precision result, note we use * addition instead of *2 since it's easier to optimize */ r = ((mp_word) *tmpt) + r + r + ((mp_word) u); /* store lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } /* propagate upwards */ while (u != ((mp_digit) 0)) { r = ((mp_word) *tmpt) + ((mp_word) u); *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } } mp_clamp (&t); mp_exch (&t, b); mp_clear (&t); return MP_OKAY; }
/* this function is less generic than mp_n_root, simpler and faster */ int mp_sqrt(const mp_int *arg, mp_int *ret) { int res; mp_int t1, t2; int i, j, k; #ifndef NO_FLOATING_POINT volatile double d; mp_digit dig; #endif /* must be positive */ if (arg->sign == MP_NEG) { return MP_VAL; } /* easy out */ if (mp_iszero(arg) == MP_YES) { mp_zero(ret); return MP_OKAY; } i = (arg->used / 2) - 1; j = 2 * i; if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) { return res; } if ((res = mp_init(&t2)) != MP_OKAY) { goto E2; } for (k = 0; k < i; ++k) { t1.dp[k] = (mp_digit) 0; } #ifndef NO_FLOATING_POINT /* Estimate the square root using the hardware floating point unit. */ d = 0.0; for (k = arg->used-1; k >= j; --k) { d = ldexp(d, DIGIT_BIT) + (double)(arg->dp[k]); } /* * At this point, d is the nearest floating point number to the most * significant 1 or 2 mp_digits of arg. Extract its square root. */ d = sqrt(d); /* dig is the most significant mp_digit of the square root */ dig = (mp_digit) ldexp(d, -DIGIT_BIT); /* * If the most significant digit is nonzero, find the next digit down * by subtracting DIGIT_BIT times thie most significant digit. * Subtract one from the result so that our initial estimate is always * low. */ if (dig) { t1.used = i+2; d -= ldexp((double) dig, DIGIT_BIT); if (d >= 1.0) { t1.dp[i+1] = dig; t1.dp[i] = ((mp_digit) d) - 1; } else { t1.dp[i+1] = dig-1; t1.dp[i] = MP_DIGIT_MAX; } } else { t1.used = i+1; t1.dp[i] = ((mp_digit) d) - 1; } #else /* Estimate the square root as having 1 in the most significant place. */ t1.used = i + 2; t1.dp[i+1] = (mp_digit) 1; t1.dp[i] = (mp_digit) 0; #endif /* t1 > 0 */ if ((res = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1, &t2, &t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) { goto E1; } /* And now t1 > sqrt(arg) */ do { if ((res = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1, &t2, &t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) { goto E1; } /* t1 >= sqrt(arg) >= t2 at this point */ } while (mp_cmp_mag(&t1, &t2) == MP_GT); mp_exch(&t1, ret); E1: mp_clear(&t2); E2: mp_clear(&t1); return res; }
/* Do modular exponentiation using integer multiply code. */ mp_err mp_exptmod_safe_i(const mp_int * montBase, const mp_int * exponent, const mp_int * modulus, mp_int * result, mp_mont_modulus *mmm, int nLen, mp_size bits_in_exponent, mp_size window_bits, mp_size num_powers) { mp_int *pa1, *pa2, *ptmp; mp_size i; mp_size first_window; mp_err res; int expOff; mp_int accum1, accum2, accum[WEAVE_WORD_SIZE]; mp_int tmp; unsigned char *powersArray; unsigned char *powers; MP_DIGITS(&accum1) = 0; MP_DIGITS(&accum2) = 0; MP_DIGITS(&accum[0]) = 0; MP_DIGITS(&accum[1]) = 0; MP_DIGITS(&accum[2]) = 0; MP_DIGITS(&accum[3]) = 0; MP_DIGITS(&tmp) = 0; powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1)); if (powersArray == NULL) { res = MP_MEM; goto CLEANUP; } /* powers[i] = base ** (i); */ powers = (unsigned char *)MP_ALIGN(powersArray,num_powers); /* grab the first window value. This allows us to preload accumulator1 * and save a conversion, some squares and a multiple*/ MP_CHECKOK( mpl_get_bits(exponent, bits_in_exponent-window_bits, window_bits) ); first_window = (mp_size)res; MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) ); /* build the first WEAVE_WORD powers inline */ /* if WEAVE_WORD_SIZE is not 4, this code will have to change */ if (num_powers > 2) { MP_CHECKOK( mp_init_size(&accum[0], 3 * nLen + 2) ); MP_CHECKOK( mp_init_size(&accum[1], 3 * nLen + 2) ); MP_CHECKOK( mp_init_size(&accum[2], 3 * nLen + 2) ); MP_CHECKOK( mp_init_size(&accum[3], 3 * nLen + 2) ); mp_set(&accum[0], 1); MP_CHECKOK( s_mp_to_mont(&accum[0], mmm, &accum[0]) ); MP_CHECKOK( mp_copy(montBase, &accum[1]) ); SQR(montBase, &accum[2]); MUL_NOWEAVE(montBase, &accum[2], &accum[3]); MP_CHECKOK( mpi_to_weave(accum, powers, nLen, num_powers) ); if (first_window < 4) { MP_CHECKOK( mp_copy(&accum[first_window], &accum1) ); first_window = num_powers; } } else { if (first_window == 0) { mp_set(&accum1, 1); MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); } else { /* assert first_window == 1? */ MP_CHECKOK( mp_copy(montBase, &accum1) ); } } /* * calculate all the powers in the powers array. * this adds 2**(k-1)-2 square operations over just calculating the * odd powers where k is the window size in the two other mp_modexpt * implementations in this file. We will get some of that * back by not needing the first 'k' squares and one multiply for the * first window */ for (i = WEAVE_WORD_SIZE; i < num_powers; i++) { int acc_index = i & (WEAVE_WORD_SIZE-1); /* i % WEAVE_WORD_SIZE */ if ( i & 1 ) { MUL_NOWEAVE(montBase, &accum[acc_index-1] , &accum[acc_index]); /* we've filled the array do our 'per array' processing */ if (acc_index == (WEAVE_WORD_SIZE-1)) { MP_CHECKOK( mpi_to_weave(accum, powers + i - (WEAVE_WORD_SIZE-1), nLen, num_powers) ); if (first_window <= i) { MP_CHECKOK( mp_copy(&accum[first_window & (WEAVE_WORD_SIZE-1)], &accum1) ); first_window = num_powers; } } } else { /* up to 8 we can find 2^i-1 in the accum array, but at 8 we our source * and target are the same so we need to copy.. After that, the * value is overwritten, so we need to fetch it from the stored * weave array */ if (i > 2* WEAVE_WORD_SIZE) { MP_CHECKOK(weave_to_mpi(&accum2, powers+i/2, nLen, num_powers)); SQR(&accum2, &accum[acc_index]); } else { int half_power_index = (i/2) & (WEAVE_WORD_SIZE-1); if (half_power_index == acc_index) { /* copy is cheaper than weave_to_mpi */ MP_CHECKOK(mp_copy(&accum[half_power_index], &accum2)); SQR(&accum2,&accum[acc_index]); } else { SQR(&accum[half_power_index],&accum[acc_index]); } } } } /* if the accum1 isn't set, Then there is something wrong with our logic * above and is an internal programming error. */ #if MP_ARGCHK == 2 assert(MP_USED(&accum1) != 0); #endif /* set accumulator to montgomery residue of 1 */ pa1 = &accum1; pa2 = &accum2; for (expOff = bits_in_exponent - window_bits*2; expOff >= 0; expOff -= window_bits) { mp_size smallExp; MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); smallExp = (mp_size)res; /* handle unroll the loops */ switch (window_bits) { case 1: if (!smallExp) { SQR(pa1,pa2); SWAPPA; } else if (smallExp & 1) { SQR(pa1,pa2); MUL_NOWEAVE(montBase,pa2,pa1); } else { abort(); } break; case 6: SQR(pa1,pa2); SQR(pa2,pa1); /* fall through */ case 4: SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp, pa1,pa2); SWAPPA; break; case 5: SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); MUL(smallExp,pa2,pa1); break; default: abort(); /* could do a loop? */ } } res = s_mp_redc(pa1, mmm); mp_exch(pa1, result); CLEANUP: mp_clear(&accum1); mp_clear(&accum2); mp_clear(&accum[0]); mp_clear(&accum[1]); mp_clear(&accum[2]); mp_clear(&accum[3]); mp_clear(&tmp); /* PORT_Memset(powers,0,num_powers*nLen*sizeof(mp_digit)); */ free(powersArray); return res; }
/* Do modular exponentiation using floating point multiply code. */ mp_err mp_exptmod_f(const mp_int * montBase, const mp_int * exponent, const mp_int * modulus, mp_int * result, mp_mont_modulus *mmm, int nLen, mp_size bits_in_exponent, mp_size window_bits, mp_size odd_ints) { mp_digit *mResult; double *dBuf = 0, *dm1, *dn, *dSqr, *d16Tmp, *dTmp; double dn0; mp_size i; mp_err res; int expOff; int dSize = 0, oddPowSize, dTmpSize; mp_int accum1; double *oddPowers[MAX_ODD_INTS]; /* function for computing n0prime only works if n0 is odd */ MP_DIGITS(&accum1) = 0; for (i = 0; i < MAX_ODD_INTS; ++i) oddPowers[i] = 0; MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); mp_set(&accum1, 1); MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); MP_CHECKOK( s_mp_pad(&accum1, nLen) ); oddPowSize = 2 * nLen + 1; dTmpSize = 2 * oddPowSize; dSize = sizeof(double) * (nLen * 4 + 1 + ((odd_ints + 1) * oddPowSize) + dTmpSize); dBuf = (double *)malloc(dSize); dm1 = dBuf; /* array of d32 */ dn = dBuf + nLen; /* array of d32 */ dSqr = dn + nLen; /* array of d32 */ d16Tmp = dSqr + nLen; /* array of d16 */ dTmp = d16Tmp + oddPowSize; for (i = 0; i < odd_ints; ++i) { oddPowers[i] = dTmp; dTmp += oddPowSize; } mResult = (mp_digit *)(dTmp + dTmpSize); /* size is nLen + 1 */ /* Make dn and dn0 */ conv_i32_to_d32(dn, MP_DIGITS(modulus), nLen); dn0 = (double)(mmm->n0prime & 0xffff); /* Make dSqr */ conv_i32_to_d32_and_d16(dm1, oddPowers[0], MP_DIGITS(montBase), nLen); mont_mulf_noconv(mResult, dm1, oddPowers[0], dTmp, dn, MP_DIGITS(modulus), nLen, dn0); conv_i32_to_d32(dSqr, mResult, nLen); for (i = 1; i < odd_ints; ++i) { mont_mulf_noconv(mResult, dSqr, oddPowers[i - 1], dTmp, dn, MP_DIGITS(modulus), nLen, dn0); conv_i32_to_d16(oddPowers[i], mResult, nLen); } s_mp_copy(MP_DIGITS(&accum1), mResult, nLen); /* from, to, len */ for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) { mp_size smallExp; MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); smallExp = (mp_size)res; if (window_bits == 1) { if (!smallExp) { SQR; } else if (smallExp & 1) { SQR; MUL(0); } else { ABORT; } } else if (window_bits == 4) { if (!smallExp) { SQR; SQR; SQR; SQR; } else if (smallExp & 1) { SQR; SQR; SQR; SQR; MUL(smallExp/2); } else if (smallExp & 2) { SQR; SQR; SQR; MUL(smallExp/4); SQR; } else if (smallExp & 4) { SQR; SQR; MUL(smallExp/8); SQR; SQR; } else if (smallExp & 8) { SQR; MUL(smallExp/16); SQR; SQR; SQR; } else { ABORT; } } else if (window_bits == 5) { if (!smallExp) { SQR; SQR; SQR; SQR; SQR; } else if (smallExp & 1) { SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2); } else if (smallExp & 2) { SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR; } else if (smallExp & 4) { SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR; } else if (smallExp & 8) { SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR; } else if (smallExp & 0x10) { SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR; } else { ABORT; } } else if (window_bits == 6) { if (!smallExp) { SQR; SQR; SQR; SQR; SQR; SQR; } else if (smallExp & 1) { SQR; SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2); } else if (smallExp & 2) { SQR; SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR; } else if (smallExp & 4) { SQR; SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR; } else if (smallExp & 8) { SQR; SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR; } else if (smallExp & 0x10) { SQR; SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR; } else if (smallExp & 0x20) { SQR; MUL(smallExp/64); SQR; SQR; SQR; SQR; SQR; } else { ABORT; } } else { ABORT; } } s_mp_copy(mResult, MP_DIGITS(&accum1), nLen); /* from, to, len */ res = s_mp_redc(&accum1, mmm); mp_exch(&accum1, result); CLEANUP: mp_clear(&accum1); if (dBuf) { if (dSize) memset(dBuf, 0, dSize); free(dBuf); } return res; }
/* single digit division (based on routine from MPI) */ int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) { mp_int q; mp_word w; mp_digit t; int res, ix; /* cannot divide by zero */ if (b == 0) { return MP_VAL; } /* quick outs */ if (b == 1 || mp_iszero(a) == 1) { if (d != NULL) { *d = 0; } if (c != NULL) { return mp_copy(a, c); } return MP_OKAY; } /* power of two ? */ if (s_is_power_of_two(b, &ix) == 1) { if (d != NULL) { *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1); } if (c != NULL) { return mp_div_2d(a, ix, c, NULL); } return MP_OKAY; } #ifdef BN_MP_DIV_3_C /* three? */ if (b == 3) { return mp_div_3(a, c, d); } #endif /* no easy answer [c'est la vie]. Just division */ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { return res; } q.used = a->used; q.sign = a->sign; w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); if (w >= b) { t = (mp_digit)(w / b); w -= ((mp_word)t) * ((mp_word)b); } else { t = 0; } q.dp[ix] = (mp_digit)t; } if (d != NULL) { *d = (mp_digit)w; } if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); } mp_clear(&q); return res; }
/* this function is less generic than mp_n_root, simpler and faster */ int mp_sqrt(mp_int *arg, mp_int *ret) { int res; mp_int t1,t2; int i, j, k; #ifndef NO_FLOATING_POINT double d; mp_digit dig; #endif /* must be positive */ if (arg->sign == MP_NEG) { return MP_VAL; } /* easy out */ if (mp_iszero(arg) == MP_YES) { mp_zero(ret); return MP_OKAY; } i = (arg->used / 2) - 1; j = 2 * i; if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) { return res; } if ((res = mp_init(&t2)) != MP_OKAY) { goto E2; } for (k = 0; k < i; ++k) { t1.dp[k] = (mp_digit) 0; } #ifndef NO_FLOATING_POINT /* Estimate the square root using the hardware floating point unit. */ d = 0.0; for (k = arg->used-1; k >= j; --k) { d = ldexp(d, DIGIT_BIT) + (double) (arg->dp[k]); } d = sqrt(d); dig = (mp_digit) ldexp(d, -DIGIT_BIT); if (dig) { t1.used = i+2; d -= ldexp((double) dig, DIGIT_BIT); if (d != 0.0) { t1.dp[i+1] = dig; t1.dp[i] = ((mp_digit) d) - 1; } else { t1.dp[i+1] = dig-1; t1.dp[i] = MP_DIGIT_MAX; } } else { t1.used = i+1; t1.dp[i] = ((mp_digit) d) - 1; } #else /* Estimate the square root as having 1 in the most significant place. */ t1.used = i + 2; t1.dp[i+1] = (mp_digit) 1; t1.dp[i] = (mp_digit) 0; #endif /* t1 > 0 */ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* And now t1 > sqrt(arg) */ do { if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* t1 >= sqrt(arg) >= t2 at this point */ } while (mp_cmp_mag(&t1,&t2) == MP_GT); mp_exch(&t1,ret); E1: mp_clear(&t2); E2: mp_clear(&t1); return res; }