/* rp[n-1..0] = bp[bn-1..0] ^ ep[en-1..0] mod mp[n-1..0] Requires that mp[n-1..0] is odd. FIXME: is this true? Requires that ep[en-1..0] is > 1. Uses scratch space at tp of 3n+1 limbs. */ void mpn_powm_sec (mp_ptr rp, mp_srcptr bp, mp_size_t bn, mp_srcptr ep, mp_size_t en, mp_srcptr mp, mp_size_t n, mp_ptr tp) { mp_limb_t minv; int cnt; mp_bitcnt_t ebi; int windowsize, this_windowsize; mp_limb_t expbits; mp_ptr pp, this_pp; long i; int cnd; ASSERT (en > 1 || (en == 1 && ep[0] > 0)); ASSERT (n >= 1 && ((mp[0] & 1) != 0)); count_leading_zeros (cnt, ep[en - 1]); ebi = (mp_bitcnt_t) en * GMP_LIMB_BITS - cnt; windowsize = win_size (ebi); binvert_limb (minv, mp[0]); minv = -minv; pp = tp + 4 * n; this_pp = pp; this_pp[n] = 1; redcify (this_pp, this_pp + n, 1, mp, n, tp + 6 * n); this_pp += n; redcify (this_pp, bp, bn, mp, n, tp + 6 * n); /* Precompute powers of b and put them in the temporary area at pp. */ for (i = (1 << windowsize) - 2; i > 0; i--) { mpn_mul_basecase (tp, this_pp, n, pp + n, n); this_pp += n; mpn_redc_1_sec (this_pp, tp, mp, n, minv); } expbits = getbits (ep, ebi, windowsize); if (ebi < windowsize) ebi = 0; else ebi -= windowsize; #if WANT_CACHE_SECURITY mpn_tabselect (rp, pp, n, 1 << windowsize, expbits); #else MPN_COPY (rp, pp + n * expbits, n); #endif while (ebi != 0) { expbits = getbits (ep, ebi, windowsize); this_windowsize = windowsize; if (ebi < windowsize) { this_windowsize -= windowsize - ebi; ebi = 0; } else ebi -= windowsize; do { mpn_local_sqr (tp, rp, n, tp + 2 * n); mpn_redc_1_sec (rp, tp, mp, n, minv); this_windowsize--; } while (this_windowsize != 0); #if WANT_CACHE_SECURITY mpn_tabselect (tp + 2*n, pp, n, 1 << windowsize, expbits); mpn_mul_basecase (tp, rp, n, tp + 2*n, n); #else mpn_mul_basecase (tp, rp, n, pp + n * expbits, n); #endif mpn_redc_1_sec (rp, tp, mp, n, minv); } MPN_COPY (tp, rp, n); MPN_ZERO (tp + n, n); mpn_redc_1_sec (rp, tp, mp, n, minv); cnd = mpn_sub_n (tp, rp, mp, n); /* we need just retval */ mpn_subcnd_n (rp, rp, mp, n, !cnd); }
/* rp[n-1..0] = bp[bn-1..0] ^ ep[en-1..0] mod mp[n-1..0] Requires that mp[n-1..0] is odd. Requires that ep[en-1..0] is > 1. Uses scratch space tp[3n..0], i.e., 3n+1 words. */ void mpn_powm_sec (mp_ptr rp, mp_srcptr bp, mp_size_t bn, mp_srcptr ep, mp_size_t en, mp_srcptr mp, mp_size_t n, mp_ptr tp) { mp_limb_t mip[2]; int cnt; long ebi; int windowsize, this_windowsize; mp_limb_t expbits; mp_ptr pp, this_pp, last_pp; long i; int redc_x; TMP_DECL; ASSERT (en > 1 || (en == 1 && ep[0] > 1)); ASSERT (n >= 1 && ((mp[0] & 1) != 0)); TMP_MARK; count_leading_zeros (cnt, ep[en - 1]); ebi = en * GMP_LIMB_BITS - cnt; windowsize = win_size (ebi); if (BELOW_THRESHOLD (n, REDC_2_THRESHOLD)) { binvert_limb (mip[0], mp[0]); mip[0] = -mip[0]; redc_x = 1; } #if defined (HAVE_NATIVE_mpn_addmul_2) else { mpn_binvert (mip, mp, 2, tp); mip[0] = -mip[0]; mip[1] = ~mip[1]; redc_x = 2; } #endif #if 0 mpn_binvert (mip, mp, n, tp); redc_x = 0; #endif pp = TMP_ALLOC_LIMBS (n << windowsize); this_pp = pp; this_pp[n] = 1; redcify (this_pp, this_pp + n, 1, mp, n); this_pp += n; redcify (this_pp, bp, bn, mp, n); /* Precompute powers of b and put them in the temporary area at pp. */ for (i = (1 << windowsize) - 2; i > 0; i--) { last_pp = this_pp; this_pp += n; mpn_mul_n (tp, last_pp, pp + n, n); MPN_REDC_X (this_pp, tp, mp, n, mip); } expbits = getbits (ep, ebi, windowsize); ebi -= windowsize; if (ebi < 0) ebi = 0; MPN_COPY (rp, pp + n * expbits, n); while (ebi != 0) { expbits = getbits (ep, ebi, windowsize); ebi -= windowsize; this_windowsize = windowsize; if (ebi < 0) { this_windowsize += ebi; ebi = 0; } do { mpn_sqr_n (tp, rp, n); MPN_REDC_X (rp, tp, mp, n, mip); this_windowsize--; } while (this_windowsize != 0); #if WANT_CACHE_SECURITY mpn_tabselect (tp + 2*n, pp, n, 1 << windowsize, expbits); mpn_mul_n (tp, rp, tp + 2*n, n); #else mpn_mul_n (tp, rp, pp + n * expbits, n); #endif MPN_REDC_X (rp, tp, mp, n, mip); } MPN_COPY (tp, rp, n); MPN_ZERO (tp + n, n); MPN_REDC_X (rp, tp, mp, n, mip); if (mpn_cmp (rp, mp, n) >= 0) mpn_sub_n (rp, rp, mp, n); TMP_FREE; }