10#include <botan/ec_point.h>
12#include <botan/numthry.h>
14#include <botan/internal/ct_utils.h>
15#include <botan/internal/stl_util.h>
24 m_curve(curve), m_coord_x(std::move(x)), m_coord_y(std::move(y)), m_coord_z(m_curve.get_1_rep()) {
25 if(m_coord_x < 0 || m_coord_x >= curve.
get_p()) {
26 throw Invalid_Argument(
"Invalid EC_Point affine x");
28 if(m_coord_y < 0 || m_coord_y >= curve.
get_p()) {
29 throw Invalid_Argument(
"Invalid EC_Point affine y");
33 m_curve.to_rep(m_coord_x, monty_ws);
34 m_curve.to_rep(m_coord_y, monty_ws);
52 const BigInt mask2 = m_curve.sqr_to_tmp(mask, ws);
53 const BigInt mask3 = m_curve.mul_to_tmp(mask2, mask, ws);
55 m_coord_x = m_curve.mul_to_tmp(m_coord_x, mask2, ws);
56 m_coord_y = m_curve.mul_to_tmp(m_coord_y, mask3, ws);
57 m_coord_z = m_curve.mul_to_tmp(m_coord_z, mask, ws);
62inline void resize_ws(std::vector<BigInt>& ws_bn,
size_t cap_size) {
65 for(
auto& ws : ws_bn) {
66 if(ws.size() < cap_size) {
67 ws.get_word_vector().resize(cap_size);
75 const word x_words[],
size_t x_size,
const word y_words[],
size_t y_size, std::vector<BigInt>& ws_bn) {
83 m_coord_z = m_curve.get_1_rep();
87 resize_ws(ws_bn, m_curve.get_ws_size());
105 m_curve.sqr(T3, m_coord_z, ws);
106 m_curve.mul(T4, x_words, x_size, T3, ws);
108 m_curve.mul(T2, m_coord_z, T3, ws);
109 m_curve.mul(T0, y_words, y_size, T2, ws);
111 T4.
mod_sub(m_coord_x, p, sub_ws);
113 T0.
mod_sub(m_coord_y, p, sub_ws);
123 m_coord_y = m_curve.get_1_rep();
128 m_curve.sqr(T2, T4, ws);
130 m_curve.mul(T3, m_coord_x, T2, ws);
132 m_curve.mul(T1, T2, T4, ws);
134 m_curve.sqr(m_coord_x, T0, ws);
135 m_coord_x.
mod_sub(T1, p, sub_ws);
137 m_coord_x.
mod_sub(T3, p, sub_ws);
138 m_coord_x.
mod_sub(T3, p, sub_ws);
140 T3.
mod_sub(m_coord_x, p, sub_ws);
142 m_curve.mul(T2, T0, T3, ws);
143 m_curve.mul(T0, m_coord_y, T1, ws);
147 m_curve.mul(T0, m_coord_z, T4, ws);
153 const word y_words[],
155 const word z_words[],
157 std::vector<BigInt>& ws_bn) {
169 resize_ws(ws_bn, m_curve.get_ws_size());
187 m_curve.sqr(T0, z_words, z_size, ws);
188 m_curve.mul(T1, m_coord_x, T0, ws);
189 m_curve.mul(T3, z_words, z_size, T0, ws);
190 m_curve.mul(T2, m_coord_y, T3, ws);
192 m_curve.sqr(T3, m_coord_z, ws);
193 m_curve.mul(T4, x_words, x_size, T3, ws);
195 m_curve.mul(T5, m_coord_z, T3, ws);
196 m_curve.mul(T0, y_words, y_size, T5, ws);
210 m_coord_y = m_curve.get_1_rep();
215 m_curve.sqr(T5, T4, ws);
217 m_curve.mul(T3, T1, T5, ws);
219 m_curve.mul(T1, T5, T4, ws);
221 m_curve.sqr(m_coord_x, T0, ws);
222 m_coord_x.
mod_sub(T1, p, sub_ws);
223 m_coord_x.
mod_sub(T3, p, sub_ws);
224 m_coord_x.
mod_sub(T3, p, sub_ws);
226 T3.
mod_sub(m_coord_x, p, sub_ws);
228 m_curve.mul(m_coord_y, T0, T3, ws);
229 m_curve.mul(T3, T2, T1, ws);
231 m_coord_y.
mod_sub(T3, p, sub_ws);
233 m_curve.mul(T3, z_words, z_size, m_coord_z, ws);
234 m_curve.mul(m_coord_z, T3, T4, ws);
238 if(iterations == 0) {
251 for(
size_t i = 0; i != iterations; ++i) {
267 resize_ws(ws_bn, m_curve.get_ws_size());
283 m_curve.sqr(T0, m_coord_y, ws);
285 m_curve.mul(T1, m_coord_x, T0, ws);
288 if(m_curve.a_is_zero()) {
290 m_curve.sqr(T4, m_coord_x, ws);
292 }
else if(m_curve.a_is_minus_3()) {
297 m_curve.sqr(T3, m_coord_z, ws);
304 T3.
mod_add(m_coord_x, p, sub_ws);
306 m_curve.mul(T4, T2, T3, ws);
310 m_curve.sqr(T3, m_coord_z, ws);
311 m_curve.sqr(T4, T3, ws);
312 m_curve.mul(T3, m_curve.get_a_rep(), T4, ws);
314 m_curve.sqr(T4, m_coord_x, ws);
319 m_curve.sqr(T2, T4, ws);
323 m_curve.sqr(T3, T0, ws);
328 m_curve.mul(T0, T4, T1, ws);
333 m_curve.mul(T2, m_coord_y, m_coord_z, ws);
360 *
this = scalar * *
this;
365 const size_t scalar_bits = scalar.
bits();
371 for(
size_t i = scalar_bits; i > 0; i--) {
372 const size_t b = scalar.
get_bit(i - 1);
373 R[
b ^ 1].
add(R[
b], ws);
388 if(points.size() <= 1) {
389 for(
auto& point : points) {
390 point.force_affine();
395 for(
auto& point : points) {
396 if(point.is_zero()) {
397 throw Invalid_State(
"Cannot convert zero ECC point to affine");
410 const CurveGFp& curve = points[0].m_curve;
411 const BigInt& rep_1 = curve.get_1_rep();
413 if(ws.size() < curve.get_ws_size()) {
414 ws.resize(curve.get_ws_size());
417 std::vector<BigInt> c(points.size());
418 c[0] = points[0].m_coord_z;
420 for(
size_t i = 1; i != points.size(); ++i) {
421 curve.mul(c[i], c[i - 1], points[i].m_coord_z, ws);
424 BigInt s_inv = curve.invert_element(c[c.size() - 1], ws);
426 BigInt z_inv, z2_inv, z3_inv;
428 for(
size_t i = points.size() - 1; i != 0; i--) {
431 curve.mul(z_inv, s_inv, c[i - 1], ws);
433 s_inv = curve.mul_to_tmp(s_inv, point.m_coord_z, ws);
435 curve.sqr(z2_inv, z_inv, ws);
436 curve.mul(z3_inv, z2_inv, z_inv, ws);
437 point.m_coord_x = curve.mul_to_tmp(point.m_coord_x, z2_inv, ws);
438 point.m_coord_y = curve.mul_to_tmp(point.m_coord_y, z3_inv, ws);
439 point.m_coord_z = rep_1;
442 curve.sqr(z2_inv, s_inv, ws);
443 curve.mul(z3_inv, z2_inv, s_inv, ws);
444 points[0].m_coord_x = curve.mul_to_tmp(points[0].m_coord_x, z2_inv, ws);
445 points[0].m_coord_y = curve.mul_to_tmp(points[0].m_coord_y, z3_inv, ws);
446 points[0].m_coord_z = rep_1;
451 throw Invalid_State(
"Cannot convert zero ECC point to affine");
456 const BigInt z_inv = m_curve.invert_element(m_coord_z, ws);
457 const BigInt z2_inv = m_curve.sqr_to_tmp(z_inv, ws);
458 const BigInt z3_inv = m_curve.mul_to_tmp(z_inv, z2_inv, ws);
459 m_coord_x = m_curve.mul_to_tmp(m_coord_x, z2_inv, ws);
460 m_coord_y = m_curve.mul_to_tmp(m_coord_y, z3_inv, ws);
461 m_coord_z = m_curve.get_1_rep();
465 return m_curve.is_one(m_coord_z);
469 const size_t p_bytes = m_curve.get_p_bytes();
476 const size_t p_bytes = m_curve.get_p_bytes();
483 const size_t p_bytes = m_curve.get_p_bytes();
498 return m_curve.from_rep_to_tmp(m_coord_x, monty_ws);
501 BigInt z2 = m_curve.sqr_to_tmp(m_coord_z, monty_ws);
502 z2 = m_curve.invert_element(z2, monty_ws);
505 m_curve.mul(r, m_coord_x, z2, monty_ws);
506 m_curve.from_rep(r, monty_ws);
518 return m_curve.from_rep_to_tmp(m_coord_y, monty_ws);
521 const BigInt z2 = m_curve.sqr_to_tmp(m_coord_z, monty_ws);
522 const BigInt z3 = m_curve.mul_to_tmp(m_coord_z, z2, monty_ws);
523 const BigInt z3_inv = m_curve.invert_element(z3, monty_ws);
526 m_curve.mul(r, m_coord_y, z3_inv, monty_ws);
527 m_curve.from_rep(r, monty_ws);
544 const BigInt y2 = m_curve.from_rep_to_tmp(m_curve.sqr_to_tmp(m_coord_y, monty_ws), monty_ws);
545 const BigInt x3 = m_curve.mul_to_tmp(m_coord_x, m_curve.sqr_to_tmp(m_coord_x, monty_ws), monty_ws);
546 const BigInt ax = m_curve.mul_to_tmp(m_coord_x, m_curve.get_a_rep(), monty_ws);
547 const BigInt z2 = m_curve.sqr_to_tmp(m_coord_z, monty_ws);
550 if(m_coord_z == z2) {
551 if(y2 != m_curve.from_rep_to_tmp(x3 + ax + m_curve.get_b_rep(), monty_ws)) {
556 const BigInt z3 = m_curve.mul_to_tmp(m_coord_z, z2, monty_ws);
557 const BigInt ax_z4 = m_curve.mul_to_tmp(ax, m_curve.sqr_to_tmp(z2, monty_ws), monty_ws);
558 const BigInt b_z6 = m_curve.mul_to_tmp(m_curve.get_b_rep(), m_curve.sqr_to_tmp(z3, monty_ws), monty_ws);
560 if(y2 != m_curve.from_rep_to_tmp(x3 + ax_z4 + b_z6, monty_ws)) {
569 m_curve.swap(other.m_curve);
570 m_coord_x.swap(other.m_coord_x);
571 m_coord_y.swap(other.m_coord_y);
572 m_coord_z.swap(other.m_coord_z);
576 if(m_curve != other.m_curve) {
591 return std::vector<uint8_t>(1);
594 const size_t p_bytes = m_curve.
get_p().
bytes();
601 std::vector<uint8_t> result(1 + parts * p_bytes);
656 EC_Point point(curve, xy.first, xy.second);
659 throw Decoding_Error(
"OS2ECP: Decoded point was not on the curve");
666 const uint8_t data[],
size_t data_len,
const BigInt& curve_p,
const BigInt& curve_a,
const BigInt& curve_b) {
671 const uint8_t pc = data[0];
675 if(pc == 2 || pc == 3) {
679 const bool y_mod_2 = ((pc & 0x01) == 1);
680 y = decompress_point(y_mod_2, x, curve_p, curve_a, curve_b);
682 const size_t l = (data_len - 1) / 2;
687 }
else if(pc == 6 || pc == 7) {
688 const size_t l = (data_len - 1) / 2;
694 const bool y_mod_2 = ((pc & 0x01) == 1);
696 if(decompress_point(y_mod_2, x, curve_p, curve_a, curve_b) != y) {
700 throw Invalid_Argument(
"OS2ECP: Unknown format type " + std::to_string(pc));
703 return std::make_pair(x, y);
707 return OS2ECP(data.data(), data.size(), curve);
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_ASSERT(expr, assertion_made)
BigInt & mod_mul(uint8_t y, const BigInt &mod, secure_vector< word > &ws)
static BigInt decode(const uint8_t buf[], size_t length)
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
void set_words(const word w[], size_t len)
BigInt & mod_add(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
void serialize_to(std::span< uint8_t > out) const
BigInt & mod_sub(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
bool get_bit(size_t n) const
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr void append(std::span< const uint8_t > buffer)
constexpr std::span< uint8_t > next(size_t bytes)
const BigInt & get_a() const
const BigInt & get_p() const
const BigInt & get_b() const
void randomize_repr(RandomNumberGenerator &rng)
BigInt get_affine_x() const
secure_vector< uint8_t > x_bytes() const
secure_vector< uint8_t > xy_bytes() const
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)
EC_Point & operator-=(const EC_Point &rhs)
bool on_the_curve() const
EC_Point & operator+=(const EC_Point &rhs)
bool operator==(const EC_Point &other) const
EC_Point mul(const BigInt &scalar) const
static void force_all_affine(std::span< EC_Point > points, secure_vector< word > &ws)
BigInt get_affine_y() const
EC_Point & operator*=(const BigInt &scalar)
secure_vector< uint8_t > y_bytes() const
friend void swap(EC_Point &x, EC_Point &y)
std::vector< uint8_t > encode(EC_Point_Format format) const
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
EC_Point OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
std::vector< T, secure_allocator< T > > secure_vector
BigInt sqrt_modulo_prime(const BigInt &a, const BigInt &p)