int mpl_abs_cmp(const mpl_int *a, const mpl_int *b) { if (a == b || (mpl_iszero(a) && mpl_iszero(b))) return MPL_CMP_EQ; return _mpl_abs_cmp(a, b); }
int mpl_cmp(const mpl_int *a, const mpl_int *b) { int res; if (a == b || (mpl_iszero(a) && mpl_iszero(b))) return MPL_CMP_EQ; if (a->sign != b->sign) return a->sign == MPL_SIGN_POS ? MPL_CMP_GT : MPL_CMP_LT; if (a->sign == MPL_SIGN_NEG) res = _mpl_abs_cmp(b, a); else res = _mpl_abs_cmp(a, b); return res; }
int mpl_shr(mpl_int *a, unsigned int nr) { _mpl_int_t *dst, *src; unsigned int nbits, ndigs; int i, n; if (nr == 0 || mpl_iszero(a)) return MPL_OK; if (nr >= mpl_nr_bits(a)) { mpl_zero(a); return MPL_OK; } ndigs = nr / MPL_INT_BITS; nbits = nr % MPL_INT_BITS; n = a->top + 1 - ndigs; dst = a->dig; src = a->dig + ndigs; if (nbits > 0) { _mpl_int_t mask, shift; mask = (~(_mpl_int_t)0 & MPL_INT_MASK) >> (MPL_INT_BITS - nbits); shift = MPL_INT_BITS - nbits; for (i = 1; i < n; i++) { *dst = *src >> nbits; *dst |= (*(src+1) & mask) << shift; ++dst; ++src; } *dst = *src >> nbits; } else {
int mpl_gcd(mpl_int *c, const mpl_int *a, const mpl_int *b) { mpl_int x, y, u, v; int rc, k; if ((rc = mpl_initv(&u, &v, NULL)) != MPL_OK) return rc; x.dig = a->dig; x.alloc = a->alloc; x.top = a->top; x.sign = MPL_SIGN_POS; y.dig = b->dig; y.alloc = b->alloc; y.top = b->top; y.sign = MPL_SIGN_POS; rc = mpl_copy(&u, &x); if (rc != MPL_OK) goto err; rc = mpl_copy(&v, &y); if (rc != MPL_OK) goto err; k = 0; while (mpl_iseven(&v) && mpl_iseven(&u)) { rc = mpl_shr(&u, 1); if (rc != MPL_OK) goto err; rc = mpl_shr(&v, 1); if (rc != MPL_OK) goto err; ++k; } do { /* Reduce u by factor of two. */ while (mpl_iseven(&u)) { rc = mpl_shr(&u, 1); if (rc != MPL_OK) goto err; } /* Reduce v by factor of two. */ while (mpl_iseven(&v)) { rc = mpl_shr(&v, 1); if (rc != MPL_OK) goto err; } /* Reduce greatest of u or v. */ if (mpl_cmp(&u, &v) != MPL_CMP_LT) { /* u = (u - v) / 2 */ rc = mpl_sub(&u, &u, &v); if (rc != MPL_OK) goto err; rc = mpl_shr(&u, 1); if (rc != MPL_OK) goto err; } else { /* v = (v - u) / 2 */ rc = mpl_sub(&v, &v, &u); if (rc != MPL_OK) goto err; rc = mpl_shr(&v, 1); if (rc != MPL_OK) goto err; } } while (!mpl_iszero(&u) && !mpl_iszero(&v)); if (mpl_iszero(&u)) { rc = mpl_copy(c, &v); if (rc != MPL_OK) goto err; } else { rc = mpl_copy(c, &u); if (rc != MPL_OK) goto err; } if (k > 0) { rc = mpl_shl(c, k); if (rc != MPL_OK) goto err; } rc = MPL_OK; err: mpl_clearv(&u, &v, NULL); return rc; }
int mpl_primality_miller_rabin(const mpl_int *m, int r, int (*rnd)(void *buf, size_t size, void *rndctx), void *rndctx) { mpl_int m_minus_one, one; mpl_int m_mod, a, t, x, mu; int i, rc, s, n; if (rnd == NULL || r == 0 || mpl_iszero(m)) return MPL_ERR; rc = mpl_initv(&m_minus_one, &one, &a, &t, &x, &mu, NULL); if (rc != MPL_OK) return rc; /* m_mod = |m| */ m_mod.dig = m->dig; m_mod.top = m->top; m_mod.sign = MPL_SIGN_POS; m_mod.alloc = 0; /* one = 1, m_minus_one = |m| - 1 */ mpl_set_one(&one); rc = mpl_sub(&m_minus_one, &m_mod, &one); if (rc != MPL_OK) goto out; /* Prepare Barrett reduction precalculated constant. */ rc = mpl_reduce_barrett_setup(&mu, &m_mod); if (rc != MPL_OK) goto out; /* Determine power of two used to construct |m|-1 = 2^s * t. */ s = 0; n = m_minus_one.top + 1; for (i = 0; i < n; i++) { _mpl_int_t dig; int cnt; dig = m_minus_one.dig[i]; for (cnt = 0; cnt < MPL_INT_BITS; cnt++) { if (dig & 0x1) goto brk_loop; dig >>= 1; ++s; } } brk_loop: /* The following condition is a paranoidal check. */ if (i >= n) { rc = MPL_ERR; goto out; } /* m_minus_one = 2^s * t */ rc = mpl_copy(&t, &m_minus_one); if (rc != MPL_OK) goto out; if (s > 0) { rc = mpl_shr(&t, s); if (rc != MPL_OK) goto out; } /* Number of random bytes one digit less than m. */ n = (m->top * MPL_INT_BITS) / CHAR_BIT; for (i = 0; i < r; i++) { int j; //rc = mpl_random(&a, n, rnd, rndctx); rc = mpl_rand_below(&a, &m_minus_one, rnd, rndctx); if (rc != MPL_OK) goto out; rc = mpl_mod_exp(&x, &a, &t, &m_mod); if (rc != MPL_OK) goto out; if (mpl_cmp(&x, &one) == MPL_CMP_EQ) continue; if (mpl_cmp(&x, &m_minus_one) == MPL_CMP_EQ) continue; for (j = 1; j < s; j++) { rc = mpl_sqr(&x, &x); if (rc != MPL_OK) goto out; rc = mpl_reduce_barrett(&x, &x, &m_mod, &mu); if (rc != MPL_OK) goto out; if (mpl_isone(&x)) { rc = MPL_COMPOSITE; goto out; } if (mpl_cmp(&x, &m_minus_one) == MPL_CMP_EQ) break; } if (j >= s) { rc = MPL_COMPOSITE; goto out; } } rc = MPL_OK; out: mpl_clearv(&m_minus_one, &one, &a, &t, &x, &mu, NULL); return rc; }