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>
22constexpr size_t MontgomeryUseStackLimit = 32;
30bool ranges_overlap(
const word* a,
size_t na,
const word* b,
size_t nb) {
31 if(na == 0 || nb == 0) {
34 const std::less<const word*> lt;
35 return lt(a, b + nb) && lt(b, a + na);
41 if(p.is_even() || p < 3) {
42 throw Invalid_Argument(
"Montgomery_Params invalid modulus");
46 m_p_words = m_p.sig_words();
51 m_r1 = mod_p.reduce(r);
52 m_r2 = mod_p.square(m_r1);
53 m_r3 = mod_p.multiply(m_r1, m_r2);
62 m_data(std::make_shared<Data>(
p, mod_p)) {}
68 if(this->m_data == other.m_data) {
72 return (this->m_data->p() == other.m_data->p());
76 const size_t p_size = this->
p_words();
78 if(ws.size() < p_size) {
91 const size_t p_size = this->
p_words();
93 this->
mul(z, x, y, ws);
98 BOTAN_ARG_CHECK(&z != &x && &z != &y,
"Montgomery_Params::mul output must not alias inputs");
100 const size_t p_size = this->
p_words();
102 if(ws.size() < 2 * p_size) {
103 ws.resize(2 * p_size);
109 if(z.
size() < 2 * p_size) {
117 std::min(p_size, x.
size()),
120 std::min(p_size, y.
size()),
128 BOTAN_ARG_CHECK(&z != &x,
"Montgomery_Params::mul output must not alias x");
130 "Montgomery_Params::mul output must not overlap y");
132 const size_t p_size = this->
p_words();
134 if(ws.size() < 2 * p_size) {
135 ws.resize(2 * p_size);
137 if(z.
size() < 2 * p_size) {
147 std::min(p_size, x.
size()),
150 std::min(p_size, y.size()),
158 const size_t p_size = this->
p_words();
160 if(ws.size() < 4 * p_size) {
161 ws.resize(4 * p_size);
164 word* z_data = ws.data();
165 word* ws_data = &ws[2 * p_size];
173 std::min(p_size, x.
size()),
176 std::min(p_size, y.
size()),
182 if(x.
size() < 2 * p_size) {
194 const size_t p_size = this->
p_words();
201 BOTAN_ARG_CHECK(&z != &x,
"Montgomery_Params::sqr output must not alias input");
207 "Montgomery_Params::sqr output must not overlap input");
209 const size_t p_size = this->
p_words();
211 if(ws.size() < 2 * p_size) {
212 ws.resize(2 * p_size);
215 if(z.
size() < 2 * p_size) {
227 m_params(params), m_v(std::move(words)) {
237 auto redc_x = params.
mul(params.
redc(x, ws), params.
R3(), ws);
242 m_params(params), m_v(m_params.p_words()) {
245 const size_t p_size = m_params.p_words();
249 if(v_span.size() > p_size) {
251 v_span = v_span.first(p_size);
256 copy_mem(std::span{m_v}.first(v_span.size()), v_span);
260 this->
mul_by(m_params.R2()._as_span().first(p_size), ws);
265 m_params(params), m_v(words.begin(), words.end()) {
266 BOTAN_ARG_CHECK(m_v.size() == m_params.p_words(),
"Invalid input span");
277 z.resize(2 * m_params.p_words());
280 z.data(), m_params.p()._data(), m_params.p_words(), m_params.p_dash(), ws.data(), ws.size());
288 const size_t p_size = m_params.p_words();
293 word* r = std::span{z}.first(p_size).data();
294 word* t = std::span{z}.last(p_size).data();
309 const size_t p_size = m_params.p_words();
313 const word borrow =
bigint_sub3(t.data(), m_v.data(), p_size, other.m_v.data(), p_size);
323 const size_t p_size = m_params.p_words();
326 if(ws.size() < 2 * p_size) {
327 ws.resize(2 * p_size);
332 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());
342 return this->
mul_by(std::span{other.m_v}, ws);
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_mul_by = [&](std::span<word> z) {
354 bigint_mul(z.data(), z.size(), m_v.data(), p_size, p_size, other.data(), p_size, p_size, ws.data(), ws.size());
361 if(p_size <= MontgomeryUseStackLimit) {
362 std::array<word, 2 * MontgomeryUseStackLimit> z{};
373 const size_t p_size = m_params.p_words();
376 if(ws.size() < 2 * p_size) {
377 ws.resize(2 * p_size);
380 auto do_sqr_n = [&](std::span<word> z) {
381 for(
size_t i = 0; i != n; ++i) {
382 bigint_sqr(z.data(), 2 * p_size, m_v.data(), p_size, p_size, ws.data(), ws.size());
386 copy_mem(m_v, std::span{z}.first(p_size));
390 if(p_size <= MontgomeryUseStackLimit) {
391 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
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)
constexpr void copy_mem(T *out, const T *in, size_t n)
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
The native machine word, used as the limb type for multiprecision integers.