7 #include <botan/internal/point_mul.h>
9 #include <botan/reducer.h>
10 #include <botan/internal/rounding.h>
11 #include <botan/internal/ct_utils.h>
17 const size_t PointGFp_SCALAR_BLINDING_BITS = 80;
47 return m_point_mul->mul(scalar, rng, m_order, m_ws);
53 m_mod_order(mod_order),
54 m_p_words(base.get_curve().get_p().sig_words()),
55 m_T_size(base.get_curve().get_p().bits() + PointGFp_SCALAR_BLINDING_BITS + 1)
66 const size_t T_bits =
round_up(p_bits + PointGFp_SCALAR_BLINDING_BITS + 1, WINDOW_BITS) / WINDOW_BITS;
68 std::vector<PointGFp>
T(WINDOW_SIZE*T_bits);
73 for(
size_t i = 0; i != T_bits; i++)
81 T[7*i+1] = std::move(g2);
82 T[7*i+2] = T[7*i+1].plus(T[7*i+0], ws);
84 T[7*i+4] = T[7*i+3].
plus(T[7*i+0], ws);
85 T[7*i+5] = T[7*i+3].
plus(T[7*i+1], ws);
86 T[7*i+6] = T[7*i+3].
plus(T[7*i+2], ws);
94 m_W.resize(T.size() * 2 * m_p_words);
97 for(
size_t i = 0; i != T.size(); ++i)
99 T[i].get_x().encode_words(p, m_p_words);
101 T[i].get_y().encode_words(p, m_p_words);
108 const BigInt& group_order,
109 std::vector<BigInt>& ws)
const
112 throw Invalid_Argument(
"PointGFp_Base_Point_Precompute scalar must be positive");
120 const BigInt mask(rng, PointGFp_SCALAR_BLINDING_BITS);
121 scalar += group_order * mask;
131 scalar += group_order;
132 if(scalar.
bits() == group_order.
bits())
133 scalar += group_order;
137 const size_t windows =
round_up(scalar.
bits(), WINDOW_BITS) / WINDOW_BITS;
139 const size_t elem_size = 2*m_p_words;
142 "Precomputed sufficient values for scalar mult");
150 std::vector<word> Wt(elem_size);
152 for(
size_t i = 0; i != windows; ++i)
154 const size_t window = windows - i - 1;
155 const size_t base_addr = (WINDOW_SIZE*window)*elem_size;
157 const word w = scalar.
get_substring(WINDOW_BITS*window, WINDOW_BITS);
167 for(
size_t j = 0; j != elem_size; ++j)
169 const word w1 = w_is_1.if_set_return(m_W[base_addr + 0*elem_size + j]);
170 const word w2 = w_is_2.if_set_return(m_W[base_addr + 1*elem_size + j]);
171 const word w3 = w_is_3.if_set_return(m_W[base_addr + 2*elem_size + j]);
172 const word w4 = w_is_4.if_set_return(m_W[base_addr + 3*elem_size + j]);
173 const word w5 = w_is_5.if_set_return(m_W[base_addr + 4*elem_size + j]);
174 const word w6 = w_is_6.if_set_return(m_W[base_addr + 5*elem_size + j]);
175 const word w7 = w_is_7.if_set_return(m_W[base_addr + 6*elem_size + j]);
177 Wt[j] = w1 | w2 | w3 | w4 | w5 | w6 | w7;
180 R.
add_affine(&Wt[0], m_p_words, &Wt[m_p_words], m_p_words, ws);
201 std::vector<BigInt>& ws) :
202 m_curve(point.get_curve()),
209 std::vector<PointGFp> U(static_cast<size_t>(1) << m_window_bits);
213 for(
size_t i = 2; i < U.size(); i += 2)
216 U[i+1] = U[i].
plus(point, ws);
230 const CurveGFp& curve = U[0].get_curve();
232 const size_t p_bits = curve.
get_p().
bits();
235 for(
size_t i = 1; i != U.size(); ++i)
241 curve.
sqr(mask2, mask, tmp);
242 curve.
mul(mask3, mask, mask2, tmp);
244 curve.
mul(new_x, U[i].get_x(), mask2, tmp);
245 curve.
mul(new_y, U[i].get_y(), mask3, tmp);
246 curve.
mul(new_z, U[i].get_z(), mask, tmp);
248 U[i].swap_coords(new_x, new_y, new_z);
252 m_T.resize(U.size() * 3 * m_p_words);
255 for(
size_t i = 0; i != U.size(); ++i)
257 U[i].get_x().encode_words(p , m_p_words);
258 U[i].get_y().encode_words(p + m_p_words, m_p_words);
259 U[i].get_z().encode_words(p + 2*m_p_words, m_p_words);
266 const BigInt& group_order,
267 std::vector<BigInt>& ws)
const
270 throw Invalid_Argument(
"PointGFp_Var_Point_Precompute scalar must be positive");
275 const BigInt mask(rng, PointGFp_SCALAR_BLINDING_BITS,
false);
276 const BigInt scalar = k + group_order * mask;
278 const size_t elem_size = 3*m_p_words;
279 const size_t window_elems = (1ULL << m_window_bits);
281 size_t windows =
round_up(scalar.
bits(), m_window_bits) / m_window_bits;
289 const uint32_t w = scalar.
get_substring(windows*m_window_bits, m_window_bits);
292 for(
size_t i = 1; i != window_elems; ++i)
296 for(
size_t j = 0; j != elem_size; ++j)
298 e[j] |= wmask.if_set_return(m_T[i * elem_size + j]);
302 R.add(&e[0], m_p_words, &e[m_p_words], m_p_words, &e[2*m_p_words], m_p_words, ws);
309 R.randomize_repr(rng, ws[0].get_word_vector());
314 R.mult2i(m_window_bits, ws);
316 const uint32_t w = scalar.
get_substring((windows-1)*m_window_bits, m_window_bits);
319 for(
size_t i = 1; i != window_elems; ++i)
323 for(
size_t j = 0; j != elem_size; ++j)
325 e[j] |= wmask.if_set_return(m_T[i * elem_size + j]);
329 R.add(&e[0], m_p_words, &e[m_p_words], m_p_words, &e[2*m_p_words], m_p_words, ws);
362 m_M.push_back(y.
plus(x, ws));
363 m_M.push_back(y.
plus(x2, ws));
364 m_M.push_back(y.
plus(x3, ws));
367 m_M.push_back(y2.plus(x, ws));
368 m_M.push_back(y2.plus(x2, ws));
369 m_M.push_back(y2.plus(x3, ws));
372 m_M.push_back(y3.plus(x, ws));
373 m_M.push_back(y3.plus(x2, ws));
374 m_M.push_back(y3.plus(x3, ws));
388 for(
size_t i = 0; i != z_bits; i += 2)
398 const uint32_t z12 = (4*z2_b) + z1_b;
void sqr(BigInt &z, const BigInt &x, secure_vector< word > &ws) const
void randomize(RandomNumberGenerator &rng, size_t bitsize, bool set_high_bit=true)
void clear_mem(T *ptr, size_t n)
PointGFp_Multi_Point_Precompute(const PointGFp &g1, const PointGFp &g2)
secure_vector< word > & get_word_vector()
PointGFp mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
const CurveGFp & get_curve() const
#define BOTAN_ASSERT(expr, assertion_made)
void swap(PointGFp &other)
PointGFp_Base_Point_Precompute(const PointGFp &base_point, const Modular_Reducer &mod_order)
std::vector< T, secure_allocator< T >> secure_vector
#define BOTAN_DEBUG_ASSERT(expr)
void randomize_repr(RandomNumberGenerator &rng)
void mult2i(size_t i, std::vector< BigInt > &workspace)
PointGFp mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
std::vector< BigInt > m_ws
PointGFp blinded_multiply(const BigInt &scalar, RandomNumberGenerator &rng)
PointGFp plus(const PointGFp &other, std::vector< BigInt > &workspace) const
void mult2(std::vector< BigInt > &workspace)
#define BOTAN_UNUSED(...)
BigInt reduce(const BigInt &x) const
PointGFp double_of(std::vector< BigInt > &workspace) const
uint32_t get_substring(size_t offset, size_t length) const
void add_affine(const PointGFp &other, std::vector< BigInt > &workspace)
const BigInt & get_p() const
virtual bool is_seeded() const =0
static void force_all_affine(std::vector< PointGFp > &points, secure_vector< word > &ws)
bool on_the_curve() const
Blinded_Point_Multiply(const PointGFp &base, const BigInt &order, size_t h=0)
size_t round_up(size_t n, size_t align_to)
static Mask< T > is_equal(T x, T y)
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
~Blinded_Point_Multiply()
void mul(BigInt &z, const BigInt &x, const BigInt &y, secure_vector< word > &ws) const
PointGFp multi_exponentiate(const PointGFp &p1, const BigInt &z1, const PointGFp &p2, const BigInt &z2)
PointGFp_Var_Point_Precompute(const PointGFp &point, RandomNumberGenerator &rng, std::vector< BigInt > &ws)