10#include <botan/ec_point.h>
12#include <botan/numthry.h>
14#include <botan/internal/ct_utils.h>
15#include <botan/internal/ec_inner_data.h>
16#include <botan/internal/mod_inv.h>
17#include <botan/internal/monty.h>
18#include <botan/internal/mp_core.h>
19#include <botan/internal/stl_util.h>
28CurveGFp::CurveGFp(
const EC_Group_Data* group) : m_group(group) {
32const BigInt& CurveGFp::get_a()
const {
33 return this->group().a();
36const BigInt& CurveGFp::get_b()
const {
37 return this->group().b();
40const BigInt& CurveGFp::get_p()
const {
41 return this->group().p();
44size_t CurveGFp::get_p_words()
const {
45 return this->group().p_words();
44size_t CurveGFp::get_p_words()
const {
…}
51 group.monty().mul_by(x, group.monty().R2(), ws);
54void from_rep(
const EC_Group_Data& group, BigInt& z, secure_vector<word>& ws) {
55 group.monty().redc_in_place(z, ws);
58BigInt from_rep_to_tmp(
const EC_Group_Data& group,
const BigInt& x, secure_vector<word>& ws) {
59 return group.monty().redc(x, ws);
62void fe_mul(
const EC_Group_Data& group, BigInt& z,
const BigInt& x,
const BigInt& y, secure_vector<word>& ws) {
63 group.monty().mul(z, x, y, ws);
67 const EC_Group_Data& group, BigInt& z,
const word x_w[],
size_t x_size,
const BigInt& y, secure_vector<word>& ws) {
68 group.monty().mul(z, y, std::span{x_w, x_size}, ws);
71BigInt
fe_mul(
const EC_Group_Data& group,
const BigInt& x,
const BigInt& y, secure_vector<word>& ws) {
72 return group.monty().mul(x, y, ws);
75void fe_sqr(
const EC_Group_Data& group, BigInt& z,
const BigInt& x, secure_vector<word>& ws) {
76 group.monty().sqr(z, x, ws);
79void fe_sqr(
const EC_Group_Data& group, BigInt& z,
const word x_w[],
size_t x_size, secure_vector<word>& ws) {
80 group.monty().sqr(z, std::span{x_w, x_size}, ws);
83BigInt fe_sqr(
const EC_Group_Data& group,
const BigInt& x, secure_vector<word>& ws) {
84 return group.monty().sqr(x, ws);
87BigInt invert_element(
const EC_Group_Data& group,
const BigInt& x, secure_vector<word>& ws) {
91size_t monty_ws_size(
const EC_Group_Data& group) {
92 return 2 * group.p_words();
97EC_Point::EC_Point(
const CurveGFp& curve) : m_curve(curve), m_x(0), m_y(curve.group().monty().R1()), m_z(0) {}
104 m_curve(curve), m_x(std::move(x)), m_y(std::move(y)), m_z(m_curve.group().monty().R1()) {
105 const auto& group = m_curve.group();
107 if(m_x < 0 || m_x >= group.p()) {
108 throw Invalid_Argument(
"Invalid EC_Point affine x");
110 if(m_y < 0 || m_y >= group.p()) {
111 throw Invalid_Argument(
"Invalid EC_Point affine y");
116 to_rep(group, m_x, monty_ws);
117 to_rep(group, m_y, monty_ws);
121 const auto& group = m_curve.group();
131 const auto& group = m_curve.group();
142 const BigInt mask2 = fe_sqr(group, mask, ws);
145 m_x =
fe_mul(group, m_x, mask2, ws);
146 m_y =
fe_mul(group, m_y, mask3, ws);
147 m_z =
fe_mul(group, m_z, mask, ws);
152inline void resize_ws(std::vector<BigInt>& ws_bn,
size_t cap_size) {
155 for(
auto& ws : ws_bn) {
156 if(ws.size() < cap_size) {
157 ws.get_word_vector().resize(cap_size);
165 const word x_words[],
size_t x_size,
const word y_words[],
size_t y_size, std::vector<BigInt>& ws_bn) {
170 const auto& group = m_curve.group();
175 m_z = group.monty().R1();
179 resize_ws(ws_bn, monty_ws_size(group));
195 const BigInt& p = group.p();
197 fe_sqr(group, T3, m_z, ws);
198 fe_mul(group, T4, x_words, x_size, T3, ws);
200 fe_mul(group, T2, m_z, T3, ws);
201 fe_mul(group, T0, y_words, y_size, T2, ws);
215 m_y = group.monty().R1();
220 fe_sqr(group, T2, T4, ws);
222 fe_mul(group, T3, m_x, T2, ws);
224 fe_mul(group, T1, T2, T4, ws);
226 fe_sqr(group, m_x, T0, ws);
234 fe_mul(group, T2, T0, T3, ws);
235 fe_mul(group, T0, m_y, T1, ws);
239 fe_mul(group, T0, m_z, T4, ws);
245 const word y_words[],
247 const word z_words[],
249 std::vector<BigInt>& ws_bn) {
254 const auto& group = m_curve.group();
263 resize_ws(ws_bn, monty_ws_size(group));
279 const BigInt& p = group.p();
281 fe_sqr(group, T0, z_words, z_size, ws);
282 fe_mul(group, T1, m_x, T0, ws);
283 fe_mul(group, T3, z_words, z_size, T0, ws);
284 fe_mul(group, T2, m_y, T3, ws);
286 fe_sqr(group, T3, m_z, ws);
287 fe_mul(group, T4, x_words, x_size, T3, ws);
289 fe_mul(group, T5, m_z, T3, ws);
290 fe_mul(group, T0, y_words, y_size, T5, ws);
304 m_y = group.monty().R1();
309 fe_sqr(group, T5, T4, ws);
311 fe_mul(group, T3, T1, T5, ws);
313 fe_mul(group, T1, T5, T4, ws);
315 fe_sqr(group, m_x, T0, ws);
322 fe_mul(group, m_y, T0, T3, ws);
323 fe_mul(group, T3, T2, T1, ws);
327 fe_mul(group, T3, z_words, z_size, m_z, ws);
328 fe_mul(group, m_z, T3, T4, ws);
332 if(iterations == 0) {
345 for(
size_t i = 0; i != iterations; ++i) {
356 const auto& group = m_curve.group();
363 resize_ws(ws_bn, monty_ws_size(group));
377 const BigInt& p = group.p();
379 fe_sqr(group, T0, m_y, ws);
381 fe_mul(group, T1, m_x, T0, ws);
384 if(group.a_is_zero()) {
386 fe_sqr(group, T4, m_x, ws);
388 }
else if(group.a_is_minus_3()) {
393 fe_sqr(group, T3, m_z, ws);
402 fe_mul(group, T4, T2, T3, ws);
406 fe_sqr(group, T3, m_z, ws);
407 fe_sqr(group, T4, T3, ws);
408 fe_mul(group, T3, group.monty_a(), T4, ws);
410 fe_sqr(group, T4, m_x, ws);
415 fe_sqr(group, T2, T4, ws);
419 fe_sqr(group, T3, T0, ws);
424 fe_mul(group, T0, T4, T1, ws);
429 fe_mul(group, T2, m_y, m_z, ws);
456 *
this = scalar * *
this;
461 const size_t scalar_bits = scalar.
bits();
467 for(
size_t i = scalar_bits; i > 0; i--) {
468 const size_t b = scalar.
get_bit(i - 1);
469 R[
b ^ 1].
add(R[
b], ws);
484 if(points.size() <= 1) {
485 for(
auto& point : points) {
486 point.force_affine();
491 for(
auto& point : points) {
492 if(point.is_zero()) {
493 throw Invalid_State(
"Cannot convert zero ECC point to affine");
506 const auto& group = points[0].m_curve.group();
507 const BigInt& rep_1 = group.monty().R1();
509 if(ws.size() < monty_ws_size(group)) {
510 ws.resize(monty_ws_size(group));
513 std::vector<BigInt> c(points.size());
514 c[0] = points[0].m_z;
516 for(
size_t i = 1; i != points.size(); ++i) {
517 fe_mul(group, c[i], c[i - 1], points[i].m_z, ws);
520 BigInt s_inv = invert_element(group, c[c.size() - 1], ws);
522 BigInt z_inv, z2_inv, z3_inv;
524 for(
size_t i = points.size() - 1; i != 0; i--) {
527 fe_mul(group, z_inv, s_inv, c[i - 1], ws);
529 s_inv =
fe_mul(group, s_inv, point.m_z, ws);
531 fe_sqr(group, z2_inv, z_inv, ws);
532 fe_mul(group, z3_inv, z2_inv, z_inv, ws);
533 point.m_x =
fe_mul(group, point.m_x, z2_inv, ws);
534 point.m_y =
fe_mul(group, point.m_y, z3_inv, ws);
538 fe_sqr(group, z2_inv, s_inv, ws);
539 fe_mul(group, z3_inv, z2_inv, s_inv, ws);
540 points[0].m_x =
fe_mul(group, points[0].m_x, z2_inv, ws);
541 points[0].m_y =
fe_mul(group, points[0].m_y, z3_inv, ws);
542 points[0].m_z = rep_1;
547 throw Invalid_State(
"Cannot convert zero ECC point to affine");
552 const auto& group = m_curve.group();
554 const BigInt z_inv = invert_element(group, m_z, ws);
555 const BigInt z2_inv = fe_sqr(group, z_inv, ws);
557 m_x =
fe_mul(group, m_x, z2_inv, ws);
558 m_y =
fe_mul(group, m_y, z3_inv, ws);
559 m_z = group.monty().R1();
563 const auto& group = m_curve.group();
564 return m_z == group.monty().R1();
568 const auto& group = m_curve.group();
569 const size_t p_bytes = group.
p_bytes();
576 const auto& group = m_curve.group();
577 const size_t p_bytes = group.
p_bytes();
584 const auto& group = m_curve.group();
585 const size_t p_bytes = group.
p_bytes();
599 const auto& group = m_curve.group();
602 return from_rep_to_tmp(group, m_x, monty_ws);
605 BigInt z2 = fe_sqr(group, m_z, monty_ws);
606 z2 = invert_element(group, z2, monty_ws);
609 fe_mul(group, r, m_x, z2, monty_ws);
610 from_rep(group, r, monty_ws);
619 const auto& group = m_curve.group();
623 return from_rep_to_tmp(group, m_y, monty_ws);
626 const BigInt z2 = fe_sqr(group, m_z, monty_ws);
628 const BigInt z3_inv = invert_element(group, z3, monty_ws);
631 fe_mul(group, r, m_y, z3_inv, monty_ws);
632 from_rep(group, r, monty_ws);
647 const auto& group = m_curve.group();
650 const BigInt y2 = from_rep_to_tmp(group, fe_sqr(group, m_y, monty_ws), monty_ws);
651 const BigInt x3 =
fe_mul(group, m_x, fe_sqr(group, m_x, monty_ws), monty_ws);
652 const BigInt ax =
fe_mul(group, m_x, group.monty_a(), monty_ws);
653 const BigInt z2 = fe_sqr(group, m_z, monty_ws);
655 const BigInt& monty_b = group.monty_b();
659 if(y2 != from_rep_to_tmp(group, x3 + ax + monty_b, monty_ws)) {
665 const BigInt ax_z4 =
fe_mul(group, ax, fe_sqr(group, z2, monty_ws), monty_ws);
666 const BigInt b_z6 =
fe_mul(group, monty_b, fe_sqr(group, z3, monty_ws), monty_ws);
668 if(y2 != from_rep_to_tmp(group, x3 + ax_z4 + b_z6, monty_ws)) {
680 const auto& group = m_curve.group();
685 if(group.has_cofactor()) {
686 return group.mod_order().reduce(this->
get_affine_x()) == v;
706 to_rep(group, vr, ws);
708 fe_sqr(group, z2, this->
get_z(), ws);
709 fe_mul(group, v_z2, vr, z2, ws);
720 if(this->
get_x() == v_z2) {
724 if(group.order_is_less_than_p()) {
725 vr = v + group.order();
727 to_rep(group, vr, ws);
728 fe_mul(group, v_z2, vr, z2, ws);
730 if(this->
get_x() == v_z2) {
742 m_curve.swap(other.m_curve);
749 if(m_curve != other.m_curve) {
764 return std::vector<uint8_t>(1);
767 const size_t p_bytes = m_curve.group().
p_bytes();
774 std::vector<uint8_t> result(1 + parts * p_bytes);
798 const BigInt g = ((x * x + a) * x +
b) % p;
816 return OS2ECP(data.data(), data.size(), curve);
820 if(data_len == 1 && data[0] == 0) {
830 throw Decoding_Error(
"OS2ECP: Decoded point was not on the curve");
841 const uint8_t pc = pt[0];
842 const size_t p_bytes = p.
bytes();
846 if(pc == 2 || pc == 3) {
847 if(pt_len != 1 + p_bytes) {
852 const bool y_mod_2 = ((pc & 0x01) == 1);
853 y = decompress_point(y_mod_2, x, p, a,
b);
855 if(pt_len != 1 + 2 * p_bytes) {
861 }
else if(pc == 6 || pc == 7) {
862 if(pt_len != 1 + 2 * p_bytes) {
869 const bool y_mod_2 = ((pc & 0x01) == 1);
871 if(decompress_point(y_mod_2, x, p, a,
b) != y) {
875 throw Decoding_Error(
"OS2ECP: Unknown format type " + std::to_string(
static_cast<int>(pc)));
878 if(x >= p || y >= p) {
882 return std::make_pair(x, y);
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_ASSERT_NONNULL(ptr)
#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)
const BigInt & get_z() const
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)
const BigInt & get_x() const
std::vector< uint8_t > encode(EC_Point_Format format) const
bool _is_x_eq_to_v_mod_order(const BigInt &v) const
virtual bool is_seeded() const =0
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
void fe_mul(fe &x, const fe &a, const fe &b)
BigInt inverse_mod_public_prime(const BigInt &x, const BigInt &p)
std::vector< T, secure_allocator< T > > secure_vector
BigInt sqrt_modulo_prime(const BigInt &a, const BigInt &p)
EC_Point OS2ECP(std::span< const uint8_t > data, const CurveGFp &curve)