7#ifndef BOTAN_PCURVES_MUL_H_
8#define BOTAN_PCURVES_MUL_H_
10#include <botan/types.h>
11#include <botan/internal/ct_utils.h>
12#include <botan/internal/pcurves_algos.h>
23static constexpr size_t BasePointWindowBits = 6;
24static constexpr size_t VarPointWindowBits = 4;
25static constexpr size_t Mul2PrecompWindowBits = 3;
26static constexpr size_t Mul2WindowBits = 2;
45 if(scalar_bits == 521) {
48 return scalar_bits / 8;
61template <
typename C,
size_t R = 0>
89 auto result = AffinePoint::identity(m_table[0]);
92 const size_t idx1 =
static_cast<size_t>(idx - 1);
93 for(
size_t i = 0; i != m_table.size(); ++i) {
95 result.conditional_assign(found, m_table[i]);
111 auto result = AffinePoint::identity(m_table[R * iter]);
114 const size_t idx1 =
static_cast<size_t>(idx - 1);
115 for(
size_t i = 0; i != R; ++i) {
117 result.conditional_assign(found, m_table[R * iter + i]);
124 std::vector<AffinePoint> m_table;
164template <
typename C,
size_t WindowBits>
165std::vector<typename C::AffinePoint>
basemul_setup(
const typename C::AffinePoint& p,
size_t max_scalar_bits) {
166 static_assert(WindowBits >= 1 && WindowBits <= 8);
169 constexpr size_t WindowElements = (1 << WindowBits) - 1;
171 const size_t Windows = (max_scalar_bits + WindowBits - 1) / WindowBits;
173 const size_t TableSize = Windows * WindowElements;
175 std::vector<typename C::ProjectivePoint> table;
176 table.reserve(TableSize);
178 auto accum = C::ProjectivePoint::from_affine(p);
180 for(
size_t i = 0; i != TableSize; i += WindowElements) {
181 table.push_back(accum);
183 for(
size_t j = 1; j != WindowElements; ++j) {
186 table.emplace_back(table[i + j / 2].dbl());
188 table.emplace_back(table[i + j - 1] + table[i]);
192 accum = table[i + (WindowElements / 2)].dbl();
199template <
typename C,
size_t WindowBits,
typename BlindedScalar>
200typename C::ProjectivePoint
basemul_exec(std::span<const typename C::AffinePoint> table,
201 const BlindedScalar& scalar,
204 static constexpr size_t WindowElements = (1 << WindowBits) - 1;
209 const size_t w_0 = scalar.get_window(0);
210 const auto tbl_0 = table.first(WindowElements);
211 auto pt = C::ProjectivePoint::from_affine(C::AffinePoint::ct_select(tbl_0, w_0));
213 pt.randomize_rep(rng);
217 const size_t windows = (scalar.bits() + WindowBits - 1) / WindowBits;
219 for(
size_t i = 1; i != windows; ++i) {
220 const size_t w_i = scalar.get_window(WindowBits * i);
221 const auto tbl_i = table.subspan(WindowElements * i, WindowElements);
228 accum += C::AffinePoint::ct_select(tbl_i, w_i);
232 accum.randomize_rep(rng);
253template <
typename C,
size_t WindowBits>
254std::vector<typename C::AffinePoint>
basemul_booth_setup(
const typename C::AffinePoint& p,
size_t max_scalar_bits) {
255 static_assert(WindowBits >= 1 && WindowBits <= 8);
258 constexpr size_t WindowElements = 1 << (WindowBits - 1);
260 const size_t Windows = (max_scalar_bits + WindowBits - 1) / WindowBits;
262 const size_t TableSize = Windows * WindowElements;
264 std::vector<typename C::ProjectivePoint> table;
265 table.reserve(TableSize);
267 auto accum = C::ProjectivePoint::from_affine(p);
269 for(
size_t i = 0; i != TableSize; i += WindowElements) {
270 table.push_back(accum);
272 for(
size_t j = 1; j != WindowElements; ++j) {
275 table.emplace_back(table[i + j / 2].dbl());
277 table.emplace_back(table[i + j - 1] + table[i]);
283 accum = table[i + WindowElements - 1].dbl();
293template <
size_t WindowBits, std::
unsigned_
integral T>
295 static_assert(WindowBits >= 1 && WindowBits <= 8);
298 const T neg_x = (1 << (WindowBits + 1)) - x - 1;
299 T d = s_mask.select(neg_x, x);
300 d = (d >> 1) + (d & 1);
302 return std::make_pair(
static_cast<size_t>(d), s_mask.as_choice());
305template <
typename C,
size_t WindowBits,
typename BlindedScalar>
307 const BlindedScalar& scalar,
309 static constexpr size_t WindowElements = 1 << (WindowBits - 1);
311 const size_t windows = (scalar.bits() + WindowBits) / WindowBits;
315 const size_t w_bits = scalar.get_window(0) & ((1 << WindowBits) - 1);
316 const size_t raw = w_bits << 1;
318 const auto tbl_0 = table.first(WindowElements);
320 auto pt = C::ProjectivePoint::from_affine(C::AffinePoint::ct_select(tbl_0, tidx));
321 pt.conditional_assign(tneg, pt.negate());
323 pt.randomize_rep(rng);
327 for(
size_t i = 1; i != windows; ++i) {
329 const size_t bit_pos = WindowBits * i - 1;
330 const size_t raw = scalar.get_window(bit_pos);
333 const auto tbl_i = table.subspan(WindowElements * i, WindowElements);
335 accum = C::ProjectivePoint::add_or_sub(accum, C::AffinePoint::ct_select(tbl_i, tidx), tneg);
339 accum.randomize_rep(rng);
350template <
typename C,
size_t TableSize>
352 static_assert(TableSize > 2);
354 std::vector<typename C::ProjectivePoint> table;
355 table.reserve(TableSize);
356 table.push_back(C::ProjectivePoint::from_affine(p));
358 for(
size_t i = 1; i != TableSize; ++i) {
361 table.push_back(table[i / 2].dbl());
363 table.push_back(table[i - 1] + p);
370template <
typename C,
size_t WindowBits,
typename BlindedScalar>
372 const BlindedScalar& scalar,
374 const size_t windows = (scalar.bits() + WindowBits - 1) / WindowBits;
377 const size_t w_0 = scalar.get_window((windows - 1) * WindowBits);
378 auto pt = C::ProjectivePoint::from_affine(table.
ct_select(w_0));
380 pt.randomize_rep(rng);
384 for(
size_t i = 1; i != windows; ++i) {
385 accum = accum.dbl_n(WindowBits);
386 auto w_i = scalar.get_window((windows - i - 1) * WindowBits);
418 accum.randomize_rep(rng);
447template <
typename C,
size_t WindowBits>
448std::vector<typename C::ProjectivePoint>
mul2_setup(
const typename C::AffinePoint& p,
449 const typename C::AffinePoint& q) {
450 static_assert(WindowBits >= 1 && WindowBits <= 4);
453 constexpr size_t TableSize = (1 << (2 * WindowBits)) - 1;
454 constexpr size_t WindowSize = (1 << WindowBits);
456 std::vector<typename C::ProjectivePoint> table;
457 table.reserve(TableSize);
459 for(
size_t i = 0; i != TableSize; ++i) {
460 const size_t t_i = (i + 1);
461 const size_t p_i = t_i % WindowSize;
462 const size_t q_i = (t_i >> WindowBits) % WindowSize;
467 auto next_tbl_e = [&]() {
468 if(p_i % 2 == 0 && q_i % 2 == 0) {
471 return table[(t_i / 2) - 1].dbl();
472 }
else if(p_i > 0 && q_i > 0) {
475 return p + table[(q_i << WindowBits) - 1];
476 }
else if(q_i == 1) {
477 return table[p_i - 1] + q;
479 return table[p_i - 1] + table[(q_i << WindowBits) - 1];
481 }
else if(p_i > 0 && q_i == 0) {
485 return C::ProjectivePoint::from_affine(p);
488 return p + table[p_i - 1 - 1];
490 }
else if(p_i == 0 && q_i > 0) {
493 return C::ProjectivePoint::from_affine(q);
496 return q + table[((q_i - 1) << WindowBits) - 1];
503 table.emplace_back(next_tbl_e());
509template <
typename C,
size_t WindowBits,
typename BlindedScalar>
511 const BlindedScalar& x,
512 const BlindedScalar& y,
514 const size_t Windows = (x.bits() + WindowBits - 1) / WindowBits;
517 const size_t w_1 = x.get_window((Windows - 1) * WindowBits);
518 const size_t w_2 = y.get_window((Windows - 1) * WindowBits);
519 const size_t window = w_1 + (w_2 << WindowBits);
520 auto pt = C::ProjectivePoint::from_affine(table.
ct_select(window));
522 pt.randomize_rep(rng);
526 for(
size_t i = 1; i != Windows; ++i) {
527 accum = accum.dbl_n(WindowBits);
529 const size_t w_1 = x.get_window((Windows - i - 1) * WindowBits);
530 const size_t w_2 = y.get_window((Windows - i - 1) * WindowBits);
531 const size_t window = w_1 + (w_2 << WindowBits);
536 accum.randomize_rep(rng);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_ASSERT_UNREACHABLE()
typename C::ProjectivePoint ProjectivePoint
AffinePoint ct_select(size_t idx) const
typename C::AffinePoint AffinePoint
AffinePoint ct_select(size_t idx, size_t iter) const
static constexpr bool WholeRangeSearch
AffinePointTable(std::span< const ProjectivePoint > pts)
static constexpr Mask< T > expand(T v)
static constexpr Mask< T > is_equal(T x, T y)
constexpr void unpoison(const T *p, size_t n)
constexpr void poison(const T *p, size_t n)
C::ProjectivePoint varpoint_exec(const AffinePointTable< C > &table, const BlindedScalar &scalar, RandomNumberGenerator &rng)
constexpr size_t scalar_blinding_bits(size_t scalar_bits)
C::ProjectivePoint mul2_exec(const AffinePointTable< C > &table, const BlindedScalar &x, const BlindedScalar &y, RandomNumberGenerator &rng)
auto to_affine_batch(std::span< const typename C::ProjectivePoint > projective)
C::ProjectivePoint basemul_exec(std::span< const typename C::AffinePoint > table, const BlindedScalar &scalar, RandomNumberGenerator &rng)
C::ProjectivePoint basemul_booth_exec(std::span< const typename C::AffinePoint > table, const BlindedScalar &scalar, RandomNumberGenerator &rng)
std::vector< typename C::ProjectivePoint > mul2_setup(const typename C::AffinePoint &p, const typename C::AffinePoint &q)
std::vector< typename C::AffinePoint > basemul_booth_setup(const typename C::AffinePoint &p, size_t max_scalar_bits)
constexpr std::pair< size_t, CT::Choice > booth_recode(T x)
AffinePointTable< C > varpoint_setup(const typename C::AffinePoint &p)
std::vector< typename C::AffinePoint > basemul_setup(const typename C::AffinePoint &p, size_t max_scalar_bits)