7#include <botan/internal/monty.h>
9#include <botan/internal/barrett.h>
10#include <botan/internal/mp_core.h>
19constexpr size_t MontgomeryUseStackLimit = 32;
24 if(p.is_even() || p < 3) {
25 throw Invalid_Argument(
"Montgomery_Params invalid modulus");
29 m_p_words = m_p.sig_words();
34 m_r1 = mod_p.reduce(r);
35 m_r2 = mod_p.square(m_r1);
36 m_r3 = mod_p.multiply(m_r1, m_r2);
45 m_data(std::make_shared<Data>(
p, mod_p)) {}
51 if(this->m_data == other.m_data) {
55 return (this->m_data->p() == other.m_data->p());
59 const size_t p_size = this->
p_words();
61 if(ws.size() < p_size) {
74 const size_t p_size = this->
p_words();
76 this->
mul(z, x, y, ws);
81 const size_t p_size = this->
p_words();
83 if(ws.size() < 2 * p_size) {
84 ws.resize(2 * p_size);
90 if(z.
size() < 2 * p_size) {
98 std::min(p_size, x.
size()),
101 std::min(p_size, y.
size()),
109 const size_t p_size = this->
p_words();
111 if(ws.size() < 2 * p_size) {
112 ws.resize(2 * p_size);
114 if(z.
size() < 2 * p_size) {
124 std::min(p_size, x.
size()),
127 std::min(p_size, y.size()),
135 const size_t p_size = this->
p_words();
137 if(ws.size() < 4 * p_size) {
138 ws.resize(4 * p_size);
141 word* z_data = ws.data();
142 word* ws_data = &ws[2 * p_size];
150 std::min(p_size, x.
size()),
153 std::min(p_size, y.
size()),
159 if(x.
size() < 2 * p_size) {
171 const size_t p_size = this->
p_words();
182 const size_t p_size = this->
p_words();
184 if(ws.size() < 2 * p_size) {
185 ws.resize(2 * p_size);
188 if(z.
size() < 2 * p_size) {
198 m_params(params), m_v(std::move(words)) {
208 auto redc_x = params.
mul(params.
redc(x, ws), params.
R3(), ws);
213 m_params(params), m_v(m_params.p_words()) {
216 const size_t p_size = m_params.p_words();
220 if(v_span.size() > p_size) {
222 v_span = v_span.first(p_size);
227 copy_mem(std::span{m_v}.first(v_span.size()), v_span);
231 this->
mul_by(m_params.R2()._as_span().first(p_size), ws);
236 m_params(params), m_v(words.begin(), words.end()) {
237 BOTAN_ARG_CHECK(m_v.size() == m_params.p_words(),
"Invalid input span");
248 z.resize(2 * m_params.p_words());
251 z.data(), m_params.p()._data(), m_params.p_words(), m_params.p_dash(), ws.data(), ws.size());
259 const size_t p_size = m_params.p_words();
264 word* r = std::span{z}.first(p_size).data();
265 word* t = std::span{z}.last(p_size).data();
280 const size_t p_size = m_params.p_words();
284 const word borrow =
bigint_sub3(t.data(), m_v.data(), p_size, other.m_v.data(), p_size);
294 const size_t p_size = m_params.p_words();
297 if(ws.size() < 2 * p_size) {
298 ws.resize(2 * p_size);
303 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());
313 return this->
mul_by(std::span{other.m_v}, ws);
317 const size_t p_size = m_params.p_words();
320 if(ws.size() < 2 * p_size) {
321 ws.resize(2 * p_size);
324 auto do_mul_by = [&](std::span<word> z) {
325 bigint_mul(z.data(), z.size(), m_v.data(), p_size, p_size, other.data(), p_size, p_size, ws.data(), ws.size());
332 if(p_size <= MontgomeryUseStackLimit) {
333 std::array<word, 2 * MontgomeryUseStackLimit> z{};
344 const size_t p_size = m_params.p_words();
347 if(ws.size() < 2 * p_size) {
348 ws.resize(2 * p_size);
351 auto do_sqr_n = [&](std::span<word> z) {
352 for(
size_t i = 0; i != n; ++i) {
353 bigint_sqr(z.data(), 2 * p_size, m_v.data(), p_size, p_size, ws.data(), ws.size());
357 copy_mem(m_v, std::span{z}.first(p_size));
361 if(p_size <= MontgomeryUseStackLimit) {
362 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