7#ifndef BOTAN_PCURVES_UTIL_H_
8#define BOTAN_PCURVES_UTIL_H_
10#include <botan/internal/mp_core.h>
15template <WordType W,
size_t N,
size_t XN>
16inline consteval std::array<W, N>
reduce_mod(
const std::array<W, XN>& x,
const std::array<W, N>& p) {
17 std::array<W, N + 1> r = {0};
18 std::array<W, N + 1> t = {0};
22 for(
size_t i = 0; i != x_bits; ++i) {
23 const size_t b = x_bits - 1 - i;
27 const bool x_b = (x[b_word] >> b_bit) & 1;
43 std::array<W, N> rs = {};
44 copy_mem(rs, std::span{r}.template first<N>());
48template <WordType W,
size_t N>
49inline consteval std::array<W, N>
montygomery_r(
const std::array<W, N>& p) {
50 std::array<W, N + 1> x = {};
55template <WordType W,
size_t N>
56inline consteval std::array<W, N>
mul_mod(
const std::array<W, N>& x,
57 const std::array<W, N>& y,
58 const std::array<W, N>& p) {
59 std::array<W, 2 * N> z = {};
64template <WordType W,
size_t N>
65inline constexpr auto monty_redc_pdash1(
const std::array<W, 2 * N>& z,
const std::array<W, N>& p) -> std::array<W, N> {
66 static_assert(N >= 1);
77 for(
size_t i = 1; i != N; ++i) {
78 for(
size_t j = 0; j < i; ++j) {
79 accum.
mul(ws[j], p[i - j]);
87 for(
size_t i = 0; i != N - 1; ++i) {
88 for(
size_t j = i + 1; j != N; ++j) {
89 accum.
mul(ws[j], p[N + i - j]);
97 accum.
add(z[2 * N - 1]);
108template <WordType W,
size_t N>
109inline constexpr auto monty_redc(
const std::array<W, 2 * N>& z,
const std::array<W, N>& p, W p_dash)
110 -> std::array<W, N> {
111 static_assert(N >= 1);
117 if(!std::is_constant_evaluated()) {
119 if constexpr(N == 4) {
122 }
else if constexpr(N == 6) {
125 }
else if constexpr(N == 8) {
128 }
else if constexpr(N == 12) {
131 }
else if constexpr(N == 16) {
143 for(
size_t i = 1; i != N; ++i) {
144 for(
size_t j = 0; j < i; ++j) {
145 accum.
mul(ws[j], p[i - j]);
153 for(
size_t i = 0; i != N - 1; ++i) {
154 for(
size_t j = i + 1; j != N; ++j) {
155 accum.
mul(ws[j], p[N + i - j]);
163 accum.
add(z[2 * N - 1]);
174template <u
int8_t X, WordType W,
size_t N>
175inline consteval std::array<W, N>
p_minus(
const std::array<W, N>& p) {
177 static_assert(X > 0);
178 std::array<W, N> r{};
181 std::reverse(r.begin(), r.end());
185template <WordType W,
size_t N>
188 std::array<W, N> r{};
191 std::reverse(r.begin(), r.end());
195template <WordType W,
size_t N>
198 std::array<W, N> r{};
201 std::reverse(r.begin(), r.end());
205template <WordType W,
size_t N>
208 std::array<W, N> r = p;
214template <WordType W,
size_t N>
233 std::reverse(c2.begin(), c2.end());
237template <WordType W,
size_t N>
240 std::reverse(c3.begin(), c3.end());
242 std::reverse(c3.begin(), c3.end());
246template <
typename Z, WordType W,
size_t N>
248 const auto one = Z::one();
252 auto z = Z::constant(11);
257 auto is_square = c.is_zero() || c.is_one();
260 if(!is_square.as_bool()) {
268template <WordType W,
size_t N>
269inline consteval size_t count_bits(
const std::array<W, N>& p) {
270 auto get_bit = [&](
size_t i) {
273 return static_cast<uint8_t
>((p[w] >> b) & 0x01);
279 while(get_bit(b - 1) == 0) {
286template <WordType W,
size_t N,
size_t L>
288 static_assert(L <= WordInfo<W>::bytes * N);
290 std::array<W, N> r = {};
295 static_assert(full_words + (extra_bytes ? 1 : 0) <= N);
297 for(
size_t i = 0; i != full_words; ++i) {
298 r[i] =
load_be<W>(bytes.data(), full_words - 1 - i);
301 if constexpr(extra_bytes > 0) {
302 constexpr size_t shift = extra_bytes * 8;
305 for(
size_t i = 0; i != extra_bytes; ++i) {
307 r[0] |= (b0 << (8 * (extra_bytes - 1 - i)));
constexpr W monty_step(W p0, W p_dash)
constexpr void mul(W x, W y)
constexpr W monty_step_pdash1()
constexpr auto bigint_add2(W x[], size_t x_size, const W y[], size_t y_size) -> W
consteval std::array< W, N > shanks_tonelli_c3(const std::array< W, N > &c2)
consteval std::array< W, N > p_plus_1_over_4(const std::array< W, N > &p)
constexpr auto bigint_add3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr auto bytes_to_words(std::span< const uint8_t, L > bytes)
constexpr W shift_left(std::array< W, N > &x)
consteval std::array< W, N > p_minus_1_over_2(const std::array< W, N > &p)
constexpr void copy_mem(T *out, const T *in, size_t n)
consteval auto shanks_tonelli_c4(const std::array< W, N > &p_minus_1_over_2) -> Z
BOTAN_FUZZER_API void bigint_monty_redc_6(word r[6], const word z[12], const word p[6], word p_dash, word ws[6])
constexpr void comba_mul(W z[2 *N], const W x[N], const W y[N])
consteval std::array< W, N > p_div_2_plus_1(const std::array< W, N > &p)
constexpr auto monty_redc(const std::array< W, 2 *N > &z, const std::array< W, N > &p, W p_dash) -> std::array< W, N >
constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
consteval std::array< W, N > mul_mod(const std::array< W, N > &x, const std::array< W, N > &y, const std::array< W, N > &p)
consteval std::array< W, N > reduce_mod(const std::array< W, XN > &x, const std::array< W, N > &p)
BOTAN_FUZZER_API void bigint_monty_redc_4(word r[4], const word z[8], const word p[4], word p_dash, word ws[4])
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
BOTAN_FUZZER_API void bigint_monty_redc_12(word r[12], const word z[24], const word p[12], word p_dash, word ws[12])
void carry(int64_t &h0, int64_t &h1)
BOTAN_FUZZER_API void bigint_monty_redc_16(word r[16], const word z[32], const word p[16], word p_dash, word ws[16])
consteval std::array< W, N > p_minus(const std::array< W, N > &p)
consteval size_t count_bits(const std::array< W, N > &p)
BOTAN_FUZZER_API void bigint_monty_redc_8(word r[8], const word z[16], const word p[8], word p_dash, word ws[8])
constexpr auto load_be(ParamTs &&... params)
constexpr auto monty_redc_pdash1(const std::array< W, 2 *N > &z, const std::array< W, N > &p) -> std::array< W, N >
consteval std::array< W, N > montygomery_r(const std::array< W, N > &p)
constexpr W shift_right(std::array< W, N > &x)
consteval std::pair< size_t, std::array< W, N > > shanks_tonelli_c1c2(const std::array< W, N > &p)