7#include <botan/internal/point_mul.h>
9#include <botan/exceptn.h>
10#include <botan/mem_ops.h>
12#include <botan/internal/barrett.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/rounding.h>
20size_t blinding_size(
size_t order_bits) {
21 return (order_bits + 1) / 2;
26 BigInt mask(rng, blinding_size(group_order.bits()));
43 m_base_point(base), m_mod_order(mod_order), m_p_words(base.get_curve().get_p_words()) {
48 const size_t T_bits =
round_up(order_bits + blinding_size(order_bits), WindowBits) / WindowBits;
50 std::vector<EC_Point> T(WindowSize * T_bits);
56 for(
size_t i = 0; i != T_bits; i++) {
63 T[7 * i + 1] = std::move(g2);
64 T[7 * i + 2] = T[7 * i + 1].plus(T[7 * i + 0], ws);
66 T[7 * i + 4] = T[7 * i + 3].
plus(T[7 * i + 0], ws);
67 T[7 * i + 5] = T[7 * i + 3].
plus(T[7 * i + 1], ws);
68 T[7 * i + 6] = T[7 * i + 3].
plus(T[7 * i + 2], ws);
76 m_W.resize(T.size() * 2 * m_p_words);
79 for(
const auto& pt : T) {
80 pt.get_x().encode_words(p, m_p_words);
82 pt.get_y().encode_words(p, m_p_words);
90 std::vector<BigInt>& ws)
const {
92 throw Invalid_Argument(
"EC_Point_Base_Point_Precompute scalar must be positive");
96 BigInt scalar = m_mod_order.reduce(k);
100 scalar += group_order * blinding_mask(group_order, rng);
108 scalar += group_order;
109 if(scalar.
bits() == group_order.
bits()) {
110 scalar += group_order;
115 const size_t windows =
round_up(scalar.
bits(), WindowBits) / WindowBits;
117 const size_t elem_size = 2 * m_p_words;
119 BOTAN_ASSERT(windows <= m_W.size() / (3 * elem_size),
"Precomputed sufficient values for scalar mult");
128 std::vector<word> Wt(elem_size);
130 for(
size_t i = 0; i != windows; ++i) {
131 const size_t window = windows - i - 1;
132 const size_t base_addr = (WindowSize * window) * elem_size;
144 for(
size_t j = 0; j != elem_size; ++j) {
145 const word w1 = w_is_1.if_set_return(m_W[base_addr + 0 * elem_size + j]);
146 const word w2 = w_is_2.if_set_return(m_W[base_addr + 1 * elem_size + j]);
147 const word w3 = w_is_3.if_set_return(m_W[base_addr + 2 * elem_size + j]);
148 const word w4 = w_is_4.if_set_return(m_W[base_addr + 3 * elem_size + j]);
149 const word w5 = w_is_5.if_set_return(m_W[base_addr + 4 * elem_size + j]);
150 const word w6 = w_is_6.if_set_return(m_W[base_addr + 5 * elem_size + j]);
151 const word w7 = w_is_7.if_set_return(m_W[base_addr + 6 * elem_size + j]);
153 Wt[j] = w1 | w2 | w3 | w4 | w5 | w6 | w7;
156 R.
add_affine(Wt.data(), m_p_words, &Wt[m_p_words], m_p_words, ws);
176 std::vector<BigInt>& ws) :
177 m_curve(ipoint.get_curve()), m_p_words(m_curve.get_p_words()) {
179 ws.resize(EC_Point::WORKSPACE_SIZE);
185 std::vector<EC_Point> U(
static_cast<size_t>(1) << WindowBits);
189 for(
size_t i = 2; i < U.size(); i += 2) {
190 U[i] = U[i / 2].double_of(ws);
191 U[i + 1] = U[i].plus(point, ws);
197 for(size_t i = 1; i != U.size(); ++i) {
198 U[i].randomize_repr(rng);
202 m_T.resize(U.size() * 3 * m_p_words);
204 word* p = m_T.data();
205 for(
const auto& pt : U) {
206 pt.get_x().encode_words(p, m_p_words);
207 pt.get_y().encode_words(p + m_p_words, m_p_words);
208 pt.get_z().encode_words(p + 2 * m_p_words, m_p_words);
215 const BigInt& group_order,
216 std::vector<BigInt>& ws)
const {
218 throw Invalid_Argument(
"EC_Point_Var_Point_Precompute scalar must be positive");
225 const BigInt scalar = k + group_order * blinding_mask(group_order, rng);
227 const size_t elem_size = 3 * m_p_words;
228 const size_t window_elems =
static_cast<size_t>(1) << WindowBits;
230 size_t windows =
round_up(scalar.
bits(), WindowBits) / WindowBits;
237 const uint32_t w = scalar.
get_substring(windows * WindowBits, WindowBits);
240 for(
size_t i = 1; i != window_elems; ++i) {
243 for(
size_t j = 0; j != elem_size; ++j) {
244 e[j] |= wmask.if_set_return(m_T[i * elem_size + j]);
248 R.
add(e.data(), m_p_words, &e[m_p_words], m_p_words, &e[2 * m_p_words], m_p_words, ws);
261 const uint32_t w = scalar.
get_substring((windows - 1) * WindowBits, WindowBits);
264 for(
size_t i = 1; i != window_elems; ++i) {
267 for(
size_t j = 0; j != elem_size; ++j) {
268 e[j] |= wmask.if_set_return(m_T[i * elem_size + j]);
272 R.
add(e.data(), m_p_words, &e[m_p_words], m_p_words, &e[2 * m_p_words], m_p_words, ws);
284 m_M.push_back(x.
zero());
307 m_M.push_back(y.
plus(x, ws));
308 m_M.push_back(y.
plus(x2, ws));
309 m_M.push_back(y.
plus(x3, ws));
312 m_M.push_back(y2.
plus(x, ws));
313 m_M.push_back(y2.
plus(x2, ws));
314 m_M.push_back(y2.
plus(x3, ws));
317 m_M.push_back(y3.
plus(x, ws));
318 m_M.push_back(y3.
plus(x2, ws));
319 m_M.push_back(y3.
plus(x3, ws));
321 bool no_infinity =
true;
322 for(
auto& pt : m_M) {
332 m_no_infinity = no_infinity;
336 if(m_M.size() == 1) {
346 for(
size_t i = 0; i != z_bits; i += 2) {
354 const uint32_t z12 = (4 * z2_b) + z1_b;
361 H.
add(m_M[z12 - 1], ws);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_ASSERT(expr, assertion_made)
size_t modulus_bits() const
uint32_t get_substring(size_t offset, size_t length) const
static constexpr Mask< T > is_equal(T x, T y)
EC_Point_Base_Point_Precompute(const EC_Point &base_point, const Barrett_Reduction &mod_order)
EC_Point mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
EC_Point_Multi_Point_Precompute(const EC_Point &g1, const EC_Point &g2)
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
EC_Point_Var_Point_Precompute(const EC_Point &point, RandomNumberGenerator &rng, std::vector< BigInt > &ws)
EC_Point mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
void swap(EC_Point &other) noexcept
EC_Point plus(const EC_Point &other, std::vector< BigInt > &workspace) const
void randomize_repr(RandomNumberGenerator &rng)
void add(const EC_Point &other, std::vector< BigInt > &workspace)
void add_affine(const EC_Point &other, std::vector< BigInt > &workspace)
void mult2(std::vector< BigInt > &workspace)
void mult2i(size_t i, std::vector< BigInt > &workspace)
bool on_the_curve() const
static void force_all_affine(std::span< EC_Point > points, secure_vector< word > &ws)
virtual bool is_seeded() const =0
constexpr size_t round_up(size_t n, size_t align_to)
EC_Point multi_exponentiate(const EC_Point &p1, const BigInt &z1, const EC_Point &p2, const BigInt &z2)
std::vector< T, secure_allocator< T > > secure_vector
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
constexpr void clear_mem(T *ptr, size_t n)