7#include <botan/internal/monty.h>
9#include <botan/numthry.h>
10#include <botan/internal/barrett.h>
11#include <botan/internal/mp_core.h>
20constexpr size_t MontgomeryUseStackLimit = 32;
25 if(p.is_even() || p < 3) {
26 throw Invalid_Argument(
"Montgomery_Params invalid modulus");
30 m_p_words = m_p.sig_words();
35 m_r1 = mod_p.reduce(r);
36 m_r2 = mod_p.square(m_r1);
37 m_r3 = mod_p.multiply(m_r1, m_r2);
46 m_data(std::make_shared<Data>(
p, mod_p)) {}
52 if(this->m_data == other.m_data) {
56 return (this->m_data->p() == other.m_data->p());
60 const size_t p_size = this->
p_words();
62 if(ws.size() < p_size) {
75 const size_t p_size = this->
p_words();
77 this->
mul(z, x, y, ws);
82 const size_t p_size = this->
p_words();
84 if(ws.size() < 2 * p_size) {
85 ws.resize(2 * p_size);
91 if(z.
size() < 2 * p_size) {
99 std::min(p_size, x.
size()),
102 std::min(p_size, y.
size()),
110 const size_t p_size = this->
p_words();
112 if(ws.size() < 2 * p_size) {
113 ws.resize(2 * p_size);
115 if(z.
size() < 2 * p_size) {
125 std::min(p_size, x.
size()),
128 std::min(p_size, y.size()),
136 const size_t p_size = this->
p_words();
138 if(ws.size() < 4 * p_size) {
139 ws.resize(4 * p_size);
142 word* z_data = ws.data();
143 word* ws_data = &ws[2 * p_size];
151 std::min(p_size, x.
size()),
154 std::min(p_size, y.
size()),
160 if(x.
size() < 2 * p_size) {
172 const size_t p_size = this->
p_words();
183 const size_t p_size = this->
p_words();
185 if(ws.size() < 2 * p_size) {
186 ws.resize(2 * p_size);
189 if(z.
size() < 2 * p_size) {
199 m_params(params), m_v(std::move(words)) {
209 auto redc_x = params.
mul(params.
redc(x, ws), params.
R3(), ws);
214 m_params(params), m_v(m_params.p_words()) {
217 const size_t p_size = m_params.p_words();
221 if(v_span.size() > p_size) {
223 v_span = v_span.first(p_size);
228 copy_mem(std::span{m_v}.first(v_span.size()), v_span);
232 this->
mul_by(m_params.R2()._as_span().first(p_size), ws);
237 m_params(params), m_v(words.begin(), words.end()) {
238 BOTAN_ARG_CHECK(m_v.size() == m_params.p_words(),
"Invalid input span");
249 z.resize(2 * m_params.p_words());
252 z.data(), m_params.p()._data(), m_params.p_words(), m_params.p_dash(), ws.data(), ws.size());
260 const size_t p_size = m_params.p_words();
265 word* r = std::span{z}.first(p_size).data();
266 word* t = std::span{z}.last(p_size).data();
281 const size_t p_size = m_params.p_words();
285 const word borrow =
bigint_sub3(t.data(), m_v.data(), p_size, other.m_v.data(), p_size);
295 const size_t p_size = m_params.p_words();
298 if(ws.size() < 2 * p_size) {
299 ws.resize(2 * p_size);
304 bigint_mul(z.data(), z.size(), m_v.data(), p_size, p_size, other.m_v.data(), p_size, p_size, ws.data(), ws.size());
314 return this->
mul_by(std::span{other.m_v}, ws);
318 const size_t p_size = m_params.p_words();
321 if(ws.size() < 2 * p_size) {
322 ws.resize(2 * p_size);
325 auto do_mul_by = [&](std::span<word> z) {
326 bigint_mul(z.data(), z.size(), m_v.data(), p_size, p_size, other.data(), p_size, p_size, ws.data(), ws.size());
333 if(p_size <= MontgomeryUseStackLimit) {
334 std::array<word, 2 * MontgomeryUseStackLimit> z{};
345 const size_t p_size = m_params.p_words();
348 if(ws.size() < 2 * p_size) {
349 ws.resize(2 * p_size);
352 auto do_sqr_n = [&](std::span<word> z) {
353 for(
size_t i = 0; i != n; ++i) {
354 bigint_sqr(z.data(), 2 * p_size, m_v.data(), p_size, p_size, ws.data(), ws.size());
358 copy_mem(m_v, std::span{z}.first(p_size));
362 if(p_size <= MontgomeryUseStackLimit) {
363 std::array<word, 2 * MontgomeryUseStackLimit> z{};
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
void grow_to(size_t n) const
static BigInt _from_words(secure_vector< word > &words)
static BigInt power_of_2(size_t n)
const word * _data() const
T serialize(size_t len) const
static BigInt with_capacity(size_t n)
std::span< const word > _as_span() const
static Montgomery_Int from_wide_int(const Montgomery_Params ¶ms, const BigInt &x)
Montgomery_Int square(secure_vector< word > &ws) const
static Montgomery_Int one(const Montgomery_Params ¶ms)
Montgomery_Int operator-(const Montgomery_Int &other) const
Montgomery_Int(const Montgomery_Params ¶ms)
Montgomery_Int operator+(const Montgomery_Int &other) const
Montgomery_Int & square_this_n_times(secure_vector< word > &ws, size_t n)
Montgomery_Int mul(const Montgomery_Int &other, secure_vector< word > &ws) const
Montgomery_Int & mul_by(const Montgomery_Int &other, secure_vector< word > &ws)
std::vector< uint8_t > serialize() const
BigInt redc(const BigInt &x, secure_vector< word > &ws) const
BigInt sqr(const BigInt &x, secure_vector< word > &ws) const
void mul(BigInt &z, const BigInt &x, const BigInt &y, secure_vector< word > &ws) const
bool operator==(const Montgomery_Params &other) const
void mul_by(BigInt &x, const BigInt &y, secure_vector< word > &ws) const
Montgomery_Params(const BigInt &p, const Barrett_Reduction &mod_p)
const BigInt & R3() const
const BigInt & R1() const
constexpr auto bigint_add3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr void copy_mem(T *out, const T *in, size_t n)
void bigint_sqr(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, word workspace[], size_t ws_size)
constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr auto monty_inverse(W a) -> W
void bigint_mul(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word y[], size_t y_size, size_t y_sw, word workspace[], size_t ws_size)
void bigint_monty_redc_inplace(word z[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size)
constexpr W bigint_cnd_add(W cnd, W x[], const W y[], size_t size)
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
void carry(int64_t &h0, int64_t &h1)
std::vector< T, secure_allocator< T > > secure_vector
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word