7#include <botan/internal/monty.h>
9#include <botan/exceptn.h>
10#include <botan/mem_ops.h>
11#include <botan/internal/barrett.h>
12#include <botan/internal/mp_core.h>
21constexpr size_t MontgomeryUseStackLimit = 32;
26 if(p.is_even() || p < 3) {
27 throw Invalid_Argument(
"Montgomery_Params invalid modulus");
31 m_p_words = m_p.sig_words();
36 m_r1 = mod_p.reduce(r);
37 m_r2 = mod_p.square(m_r1);
38 m_r3 = mod_p.multiply(m_r1, m_r2);
47 m_data(std::make_shared<Data>(
p, mod_p)) {}
53 if(this->m_data == other.m_data) {
57 return (this->m_data->p() == other.m_data->p());
61 const size_t p_size = this->
p_words();
63 if(ws.size() < p_size) {
76 const size_t p_size = this->
p_words();
78 this->
mul(z, x, y, ws);
83 const size_t p_size = this->
p_words();
85 if(ws.size() < 2 * p_size) {
86 ws.resize(2 * p_size);
92 if(z.
size() < 2 * p_size) {
100 std::min(p_size, x.
size()),
103 std::min(p_size, y.
size()),
111 const size_t p_size = this->
p_words();
113 if(ws.size() < 2 * p_size) {
114 ws.resize(2 * p_size);
116 if(z.
size() < 2 * p_size) {
126 std::min(p_size, x.
size()),
129 std::min(p_size, y.size()),
137 const size_t p_size = this->
p_words();
139 if(ws.size() < 4 * p_size) {
140 ws.resize(4 * p_size);
143 word* z_data = ws.data();
144 word* ws_data = &ws[2 * p_size];
152 std::min(p_size, x.
size()),
155 std::min(p_size, y.
size()),
161 if(x.
size() < 2 * p_size) {
173 const size_t p_size = this->
p_words();
184 const size_t p_size = this->
p_words();
186 if(ws.size() < 2 * p_size) {
187 ws.resize(2 * p_size);
190 if(z.
size() < 2 * p_size) {
200 m_params(params), m_v(std::move(words)) {
210 auto redc_x = params.
mul(params.
redc(x, ws), params.
R3(), ws);
215 m_params(params), m_v(m_params.p_words()) {
218 const size_t p_size = m_params.p_words();
222 if(v_span.size() > p_size) {
224 v_span = v_span.first(p_size);
229 copy_mem(std::span{m_v}.first(v_span.size()), v_span);
233 this->
mul_by(m_params.R2()._as_span().first(p_size), ws);
238 m_params(params), m_v(words.begin(), words.end()) {
239 BOTAN_ARG_CHECK(m_v.size() == m_params.p_words(),
"Invalid input span");
250 z.resize(2 * m_params.p_words());
253 z.data(), m_params.p()._data(), m_params.p_words(), m_params.p_dash(), ws.data(), ws.size());
261 const size_t p_size = m_params.p_words();
266 word* r = std::span{z}.first(p_size).data();
267 word* t = std::span{z}.last(p_size).data();
282 const size_t p_size = m_params.p_words();
286 const word borrow =
bigint_sub3(t.data(), m_v.data(), p_size, other.m_v.data(), p_size);
296 const size_t p_size = m_params.p_words();
299 if(ws.size() < 2 * p_size) {
300 ws.resize(2 * p_size);
305 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());
315 return this->
mul_by(std::span{other.m_v}, ws);
319 const size_t p_size = m_params.p_words();
322 if(ws.size() < 2 * p_size) {
323 ws.resize(2 * p_size);
326 auto do_mul_by = [&](std::span<word> z) {
327 bigint_mul(z.data(), z.size(), m_v.data(), p_size, p_size, other.data(), p_size, p_size, ws.data(), ws.size());
334 if(p_size <= MontgomeryUseStackLimit) {
335 std::array<word, 2 * MontgomeryUseStackLimit> z{};
346 const size_t p_size = m_params.p_words();
349 if(ws.size() < 2 * p_size) {
350 ws.resize(2 * p_size);
353 auto do_sqr_n = [&](std::span<word> z) {
354 for(
size_t i = 0; i != n; ++i) {
355 bigint_sqr(z.data(), 2 * p_size, m_v.data(), p_size, p_size, ws.data(), ws.size());
359 copy_mem(m_v, std::span{z}.first(p_size));
363 if(p_size <= MontgomeryUseStackLimit) {
364 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