Montgomery_Exponentation_State::Montgomery_Exponentation_State(const BigInt& g, const BigInt& p, const Modular_Reducer& mod_p, size_t window_bits) : m_p(p), m_p_words(p.sig_words()), m_window_bits(window_bits) { if(p.is_positive() == false || p.is_even()) throw Invalid_Argument("Cannot use Montgomery reduction on even or negative integer"); if(window_bits > 12) // really even 8 is too large ... throw Invalid_Argument("Montgomery window bits too large"); m_mod_prime = monty_inverse(m_p.word_at(0)); const BigInt r = BigInt::power_of_2(m_p_words * BOTAN_MP_WORD_BITS); m_R_mod = mod_p.reduce(r); m_R2_mod = mod_p.square(m_R_mod); m_g.resize(1U << m_window_bits); BigInt z(BigInt::Positive, 2 * (m_p_words + 1)); secure_vector<word> workspace(z.size()); m_g[0] = 1; bigint_monty_mul(z, m_g[0], m_R2_mod, m_p.data(), m_p_words, m_mod_prime, workspace.data()); m_g[0] = z; m_g[1] = mod_p.reduce(g); bigint_monty_mul(z, m_g[1], m_R2_mod, m_p.data(), m_p_words, m_mod_prime, workspace.data()); m_g[1] = z; const BigInt& x = m_g[1]; for(size_t i = 2; i != m_g.size(); ++i) { const BigInt& y = m_g[i-1]; bigint_monty_mul(z, x, y, m_p.data(), m_p_words, m_mod_prime, workspace.data()); m_g[i] = z; m_g[i].shrink_to_fit(); m_g[i].grow_to(m_p_words); } }
/* * Set the base */ void Montgomery_Exponentiator::set_base(const BigInt& base) { m_window_bits = Power_Mod::window_bits(m_exp.bits(), base.bits(), m_hints); m_g.resize((1 << m_window_bits)); BigInt z(BigInt::Positive, 2 * (m_mod_words + 1)); secure_vector<word> workspace(z.size()); m_g[0] = 1; bigint_monty_mul(z, m_g[0], m_R2_mod, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); m_g[0] = z; m_g[1] = (base >= m_modulus) ? (base % m_modulus) : base; bigint_monty_mul(z, m_g[1], m_R2_mod, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); m_g[1] = z; const BigInt& x = m_g[1]; for(size_t i = 2; i != m_g.size(); ++i) { const BigInt& y = m_g[i-1]; bigint_monty_mul(z, x, y, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); m_g[i] = z; } }
/* * Compute the result */ BigInt Montgomery_Exponentiator::execute() const { const size_t exp_nibbles = (m_exp_bits + m_window_bits - 1) / m_window_bits; BigInt x = m_R_mod; const size_t z_size = 2*(m_mod_words + 1); BigInt z(BigInt::Positive, z_size); secure_vector<word> workspace(z.size()); for(size_t i = exp_nibbles; i > 0; --i) { for(size_t k = 0; k != m_window_bits; ++k) { bigint_monty_sqr(z, x, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); x = z; } const u32bit nibble = m_exp.get_substring(m_window_bits*(i-1), m_window_bits); const BigInt& y = m_g[nibble]; bigint_monty_mul(z, x, y, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); x = z; } x.grow_to(2*m_mod_words + 1); bigint_monty_redc(x.mutable_data(), m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); return x; }
// Montgomery multiplication void PointGFp::monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const { //assert(&z != &x && &z != &y); if(x.is_zero() || y.is_zero()) { z = 0; return; } const BigInt& p = curve.get_p(); const size_t p_size = curve.get_p_words(); const word p_dash = curve.get_p_dash(); SecureVector<word>& z_reg = z.get_reg(); z_reg.resize(2*p_size+1); zeroise(z_reg); bigint_monty_mul(&z_reg[0], z_reg.size(), x.data(), x.size(), x.sig_words(), y.data(), y.size(), y.sig_words(), p.data(), p_size, p_dash, &ws[0]); }