Botan 3.7.1
Crypto and TLS for C&
Botan::EC_Point Class Referencefinal

#include <ec_point.h>

Public Types

enum  { WORKSPACE_SIZE = 8 }
 
typedef EC_Point_Format Compression_Type
 

Public Member Functions

bool _is_x_eq_to_v_mod_order (const BigInt &v) const
 
void add (const EC_Point &other, std::vector< BigInt > &workspace)
 
void add (const word x_words[], size_t x_size, const word y_words[], size_t y_size, const word z_words[], size_t z_size, std::vector< BigInt > &workspace)
 
void add_affine (const EC_Point &other, std::vector< BigInt > &workspace)
 
void add_affine (const word x_words[], size_t x_size, const word y_words[], size_t y_size, std::vector< BigInt > &workspace)
 
EC_Point double_of (std::vector< BigInt > &workspace) const
 
 EC_Point ()=default
 
 EC_Point (const CurveGFp &curve)
 
 EC_Point (const CurveGFp &curve, BigInt x, BigInt y)
 
 EC_Point (const EC_Point &)=default
 
 EC_Point (EC_Point &&other)
 
std::vector< uint8_t > encode (EC_Point_Format format) const
 
void force_affine ()
 
BigInt get_affine_x () const
 
BigInt get_affine_y () const
 
const CurveGFpget_curve () const
 
const BigIntget_x () const
 
const BigIntget_y () const
 
const BigIntget_z () const
 
bool is_affine () const
 
bool is_zero () const
 
EC_Point mul (const BigInt &scalar) const
 
void mult2 (std::vector< BigInt > &workspace)
 
void mult2i (size_t i, std::vector< BigInt > &workspace)
 
EC_Pointnegate ()
 
bool on_the_curve () const
 
bool operator!= (const EC_Point &other) const =default
 
EC_Pointoperator*= (const BigInt &scalar)
 
EC_Pointoperator+= (const EC_Point &rhs)
 
EC_Pointoperator-= (const EC_Point &rhs)
 
EC_Pointoperator= (const EC_Point &)=default
 
EC_Pointoperator= (EC_Point &&other)
 
bool operator== (const EC_Point &other) const
 
EC_Point plus (const EC_Point &other, std::vector< BigInt > &workspace) const
 
void randomize_repr (RandomNumberGenerator &rng)
 
void randomize_repr (RandomNumberGenerator &rng, secure_vector< word > &ws)
 
void swap (EC_Point &other) noexcept
 
void swap_coords (BigInt &new_x, BigInt &new_y, BigInt &new_z)
 
secure_vector< uint8_t > x_bytes () const
 
secure_vector< uint8_t > xy_bytes () const
 
secure_vector< uint8_t > y_bytes () const
 
EC_Point zero () const
 

Static Public Member Functions

static void force_all_affine (std::span< EC_Point > points, secure_vector< word > &ws)
 

Friends

class EC_Point_Base_Point_Precompute
 
class EC_Point_Multi_Point_Precompute
 
class EC_Point_Var_Point_Precompute
 
void swap (EC_Point &x, EC_Point &y)
 

Detailed Description

Deprecated elliptic curve type

Use EC_AffinePoint in new code; this type is no longer used internally at all except to support very unfortunate (and deprecated) curve types, specifically those with a cofactor, or with unreasonable sizes (above 521 bits), which cannot be accomodated by the new faster EC library in math/pcurves. For normal curves EC_AffinePoint will typically be 2 or 3 times faster.

This type will be completely removed in Botan4

Definition at line 33 of file ec_point.h.

Member Typedef Documentation

◆ Compression_Type

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
WORKSPACE_SIZE 

Definition at line 42 of file ec_point.h.

42{ WORKSPACE_SIZE = 8 };

Constructor & Destructor Documentation

◆ EC_Point() [1/5]

Botan::EC_Point::EC_Point ( )
default

Construct an uninitialized EC_Point

Referenced by mult2(), mult2i(), operator-=(), and zero().

◆ EC_Point() [2/5]

Botan::EC_Point::EC_Point ( const CurveGFp & curve)
explicit

Construct the zero point

Parameters
curveThe base curve

Definition at line 97 of file ec_point.cpp.

97: m_curve(curve), m_x(0), m_y(curve.group().monty().R1()), m_z(0) {}

◆ EC_Point() [3/5]

Botan::EC_Point::EC_Point ( const EC_Point & )
default

Copy constructor

◆ EC_Point() [4/5]

Botan::EC_Point::EC_Point ( EC_Point && other)
inline

Move Constructor

Definition at line 63 of file ec_point.h.

63{ this->swap(other); }
friend void swap(EC_Point &x, EC_Point &y)
Definition ec_point.h:261

◆ EC_Point() [5/5]

Botan::EC_Point::EC_Point ( const CurveGFp & curve,
BigInt x,
BigInt y )

Construct a point from its affine coordinates

Parameters
curvethe base curve
xaffine x coordinate
yaffine y coordinate

Definition at line 103 of file ec_point.cpp.

103 :
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();
106
107 if(m_x < 0 || m_x >= group.p()) {
108 throw Invalid_Argument("Invalid EC_Point affine x");
109 }
110 if(m_y < 0 || m_y >= group.p()) {
111 throw Invalid_Argument("Invalid EC_Point affine y");
112 }
113
114 secure_vector<word> monty_ws(monty_ws_size(group));
115
116 to_rep(group, m_x, monty_ws);
117 to_rep(group, m_y, monty_ws);
118}
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61

Member Function Documentation

◆ _is_x_eq_to_v_mod_order()

bool Botan::EC_Point::_is_x_eq_to_v_mod_order ( const BigInt & v) const

For internal use only

Definition at line 675 of file ec_point.cpp.

675 {
676 if(this->is_zero()) {
677 return false;
678 }
679
680 const auto& group = m_curve.group();
681
682 /*
683 * The trick used below doesn't work for curves with cofactors
684 */
685 if(group.has_cofactor()) {
686 return group.mod_order().reduce(this->get_affine_x()) == v;
687 }
688
689 /*
690 * Note we're working with the projective coordinate directly here!
691 * Nominally we're comparing v with the affine x coordinate.
692 *
693 * return group.mod_order(this->get_affine_x()) == v;
694 *
695 * However by instead projecting r to an identical z as the x
696 * coordinate, we can compare without having to perform an
697 * expensive inversion in the field.
698 *
699 * That is, given (x*z2) and r, instead of checking if
700 * (x*z2)*z2^-1 == r,
701 * we check if
702 * (x*z2) == (r*z2)
703 */
705 BigInt vr = v;
706 to_rep(group, vr, ws);
707 BigInt z2, v_z2;
708 fe_sqr(group, z2, this->get_z(), ws);
709 fe_mul(group, v_z2, vr, z2, ws);
710
711 /*
712 * Since (typically) the group order is slightly less than the size
713 * of the field elements, its possible the signer had to reduce the
714 * r component. If they did not reduce r, then this value is correct.
715 *
716 * Due to the Hasse bound, this case occurs almost always; the
717 * probability that a reduction was actually required is
718 * approximately 1 in 2^(n/2) where n is the bit length of the curve.
719 */
720 if(this->get_x() == v_z2) {
721 return true;
722 }
723
724 if(group.order_is_less_than_p()) {
725 vr = v + group.order();
726 if(vr < group.p()) {
727 to_rep(group, vr, ws);
728 fe_mul(group, v_z2, vr, z2, ws);
729
730 if(this->get_x() == v_z2) {
731 return true;
732 }
733 }
734 }
735
736 // Reject:
737 return false;
738}
BigInt get_affine_x() const
Definition ec_point.cpp:592
bool is_zero() const
Definition ec_point.h:162
const BigInt & get_z() const
Definition ec_point.h:251
const BigInt & get_x() const
Definition ec_point.h:237
void fe_mul(fe &x, const fe &a, const fe &b)
Definition ed25519_fe.h:190

References Botan::fe_mul(), get_affine_x(), get_x(), get_z(), and is_zero().

Referenced by Botan::EC_Mul2Table_Data_BN::mul2_vartime_x_mod_order_eq().

◆ add() [1/2]

void Botan::EC_Point::add ( const EC_Point & other,
std::vector< BigInt > & workspace )
inline

Point addition

Parameters
otherthe point to add to *this
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 274 of file ec_point.h.

274 {
275 BOTAN_ARG_CHECK(m_curve == other.m_curve, "cannot add points on different curves");
276
277 const size_t p_words = m_curve.get_p_words();
278
279 add(other.m_x._data(),
280 std::min(p_words, other.m_x.size()),
281 other.m_y._data(),
282 std::min(p_words, other.m_y.size()),
283 other.m_z._data(),
284 std::min(p_words, other.m_z.size()),
285 workspace);
286 }
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
size_t get_p_words() const
Definition ec_point.cpp:44
void add(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.h:274

References Botan::BigInt::_data(), BOTAN_ARG_CHECK, and Botan::BigInt::size().

Referenced by mul(), Botan::EC_Point_Var_Point_Precompute::mul(), Botan::EC_Point_Multi_Point_Precompute::multi_exp(), operator+=(), and plus().

◆ add() [2/2]

void Botan::EC_Point::add ( const word x_words[],
size_t x_size,
const word y_words[],
size_t y_size,
const word z_words[],
size_t z_size,
std::vector< BigInt > & workspace )

Point addition. Array version.

Parameters
x_wordsthe words of the x coordinate of the other point
x_sizesize of x_words
y_wordsthe words of the y coordinate of the other point
y_sizesize of y_words
z_wordsthe words of the z coordinate of the other point
z_sizesize of z_words
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 243 of file ec_point.cpp.

249 {
250 if((CT::all_zeros(x_words, x_size) & CT::all_zeros(z_words, z_size)).as_bool()) {
251 return;
252 }
253
254 const auto& group = m_curve.group();
255
256 if(is_zero()) {
257 m_x.set_words(x_words, x_size);
258 m_y.set_words(y_words, y_size);
259 m_z.set_words(z_words, z_size);
260 return;
261 }
262
263 resize_ws(ws_bn, monty_ws_size(group));
264
265 secure_vector<word>& ws = ws_bn[0].get_word_vector();
266 secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
267
268 BigInt& T0 = ws_bn[2];
269 BigInt& T1 = ws_bn[3];
270 BigInt& T2 = ws_bn[4];
271 BigInt& T3 = ws_bn[5];
272 BigInt& T4 = ws_bn[6];
273 BigInt& T5 = ws_bn[7];
274
275 /*
276 https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
277 */
278
279 const BigInt& p = group.p();
280
281 fe_sqr(group, T0, z_words, z_size, ws); // z2^2
282 fe_mul(group, T1, m_x, T0, ws); // x1*z2^2
283 fe_mul(group, T3, z_words, z_size, T0, ws); // z2^3
284 fe_mul(group, T2, m_y, T3, ws); // y1*z2^3
285
286 fe_sqr(group, T3, m_z, ws); // z1^2
287 fe_mul(group, T4, x_words, x_size, T3, ws); // x2*z1^2
288
289 fe_mul(group, T5, m_z, T3, ws); // z1^3
290 fe_mul(group, T0, y_words, y_size, T5, ws); // y2*z1^3
291
292 T4.mod_sub(T1, p, sub_ws); // x2*z1^2 - x1*z2^2
293
294 T0.mod_sub(T2, p, sub_ws);
295
296 if(T4.is_zero()) {
297 if(T0.is_zero()) {
298 mult2(ws_bn);
299 return;
300 }
301
302 // setting to zero:
303 m_x.clear();
304 m_y = group.monty().R1();
305 m_z.clear();
306 return;
307 }
308
309 fe_sqr(group, T5, T4, ws);
310
311 fe_mul(group, T3, T1, T5, ws);
312
313 fe_mul(group, T1, T5, T4, ws);
314
315 fe_sqr(group, m_x, T0, ws);
316 m_x.mod_sub(T1, p, sub_ws);
317 m_x.mod_sub(T3, p, sub_ws);
318 m_x.mod_sub(T3, p, sub_ws);
319
320 T3.mod_sub(m_x, p, sub_ws);
321
322 fe_mul(group, m_y, T0, T3, ws);
323 fe_mul(group, T3, T2, T1, ws);
324
325 m_y.mod_sub(T3, p, sub_ws);
326
327 fe_mul(group, T3, z_words, z_size, m_z, ws);
328 fe_mul(group, m_z, T3, T4, ws);
329}
void set_words(const word w[], size_t len)
Definition bigint.h:552
BigInt & mod_sub(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:90
void clear()
Definition bigint.h:400
void mult2(std::vector< BigInt > &workspace)
Definition ec_point.cpp:351
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
Definition ct_utils.h:775

References Botan::CT::all_zeros(), Botan::BigInt::clear(), Botan::fe_mul(), Botan::BigInt::is_zero(), is_zero(), Botan::BigInt::mod_sub(), mult2(), and Botan::BigInt::set_words().

◆ add_affine() [1/2]

void Botan::EC_Point::add_affine ( const EC_Point & other,
std::vector< BigInt > & workspace )
inline

Point addition - mixed J+A

Warning
This function assumes that other is affine, if this is not correct the result will be invalid.
Parameters
otheraffine point to add - assumed to be affine!
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 316 of file ec_point.h.

316 {
317 BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
318 BOTAN_DEBUG_ASSERT(other.is_affine());
319
320 const size_t p_words = m_curve.get_p_words();
321 add_affine(other.m_x._data(),
322 std::min(p_words, other.m_x.size()),
323 other.m_y._data(),
324 std::min(p_words, other.m_y.size()),
325 workspace);
326 }
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
void add_affine(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.h:316

References Botan::BigInt::_data(), BOTAN_ASSERT_NOMSG, BOTAN_DEBUG_ASSERT, is_affine(), and Botan::BigInt::size().

Referenced by Botan::EC_Point_Base_Point_Precompute::mul(), and Botan::EC_Point_Multi_Point_Precompute::multi_exp().

◆ add_affine() [2/2]

void Botan::EC_Point::add_affine ( const word x_words[],
size_t x_size,
const word y_words[],
size_t y_size,
std::vector< BigInt > & workspace )

Point addition - mixed J+A. Array version.

Parameters
x_wordsthe words of the x coordinate of the other point
x_sizesize of x_words
y_wordsthe words of the y coordinate of the other point
y_sizesize of y_words
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 164 of file ec_point.cpp.

165 {
166 if((CT::all_zeros(x_words, x_size) & CT::all_zeros(y_words, y_size)).as_bool()) {
167 return;
168 }
169
170 const auto& group = m_curve.group();
171
172 if(is_zero()) {
173 m_x.set_words(x_words, x_size);
174 m_y.set_words(y_words, y_size);
175 m_z = group.monty().R1();
176 return;
177 }
178
179 resize_ws(ws_bn, monty_ws_size(group));
180
181 secure_vector<word>& ws = ws_bn[0].get_word_vector();
182 secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
183
184 BigInt& T0 = ws_bn[2];
185 BigInt& T1 = ws_bn[3];
186 BigInt& T2 = ws_bn[4];
187 BigInt& T3 = ws_bn[5];
188 BigInt& T4 = ws_bn[6];
189
190 /*
191 https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
192 simplified with Z2 = 1
193 */
194
195 const BigInt& p = group.p();
196
197 fe_sqr(group, T3, m_z, ws); // z1^2
198 fe_mul(group, T4, x_words, x_size, T3, ws); // x2*z1^2
199
200 fe_mul(group, T2, m_z, T3, ws); // z1^3
201 fe_mul(group, T0, y_words, y_size, T2, ws); // y2*z1^3
202
203 T4.mod_sub(m_x, p, sub_ws); // x2*z1^2 - x1*z2^2
204
205 T0.mod_sub(m_y, p, sub_ws);
206
207 if(T4.is_zero()) {
208 if(T0.is_zero()) {
209 mult2(ws_bn);
210 return;
211 }
212
213 // setting to zero:
214 m_x.clear();
215 m_y = group.monty().R1();
216 m_z.clear();
217 return;
218 }
219
220 fe_sqr(group, T2, T4, ws);
221
222 fe_mul(group, T3, m_x, T2, ws);
223
224 fe_mul(group, T1, T2, T4, ws);
225
226 fe_sqr(group, m_x, T0, ws);
227 m_x.mod_sub(T1, p, sub_ws);
228
229 m_x.mod_sub(T3, p, sub_ws);
230 m_x.mod_sub(T3, p, sub_ws);
231
232 T3.mod_sub(m_x, p, sub_ws);
233
234 fe_mul(group, T2, T0, T3, ws);
235 fe_mul(group, T0, m_y, T1, ws);
236 T2.mod_sub(T0, p, sub_ws);
237 m_y.swap(T2);
238
239 fe_mul(group, T0, m_z, T4, ws);
240 m_z.swap(T0);
241}
void swap(BigInt &other)
Definition bigint.h:192

References Botan::CT::all_zeros(), Botan::BigInt::clear(), Botan::fe_mul(), Botan::BigInt::is_zero(), is_zero(), Botan::BigInt::mod_sub(), mult2(), Botan::BigInt::set_words(), and Botan::BigInt::swap().

◆ double_of()

EC_Point Botan::EC_Point::double_of ( std::vector< BigInt > & workspace) const
inline

Point doubling

Parameters
workspacetemp space, at least WORKSPACE_SIZE elements
Returns
*this doubled

Definition at line 370 of file ec_point.h.

370 {
371 EC_Point x = (*this);
372 x.mult2(workspace);
373 return x;
374 }
EC_Point()=default

References mult2().

◆ encode()

std::vector< uint8_t > Botan::EC_Point::encode ( EC_Point_Format format) const

EC2OSP - elliptic curve to octet string primitive

Parameters
formatwhich format to encode using

Definition at line 762 of file ec_point.cpp.

762 {
763 if(is_zero()) {
764 return std::vector<uint8_t>(1); // single 0 byte
765 }
766
767 const size_t p_bytes = m_curve.group().p_bytes();
768
769 const BigInt x = get_affine_x();
770 const BigInt y = get_affine_y();
771
772 const size_t parts = (format == EC_Point_Format::Compressed) ? 1 : 2;
773
774 std::vector<uint8_t> result(1 + parts * p_bytes);
775 BufferStuffer stuffer(result);
776
777 if(format == EC_Point_Format::Uncompressed) {
778 stuffer.append(0x04);
779 x.serialize_to(stuffer.next(p_bytes));
780 y.serialize_to(stuffer.next(p_bytes));
781 } else if(format == EC_Point_Format::Compressed) {
782 stuffer.append(0x02 | static_cast<uint8_t>(y.get_bit(0)));
783 x.serialize_to(stuffer.next(p_bytes));
784 } else if(format == EC_Point_Format::Hybrid) {
785 stuffer.append(0x06 | static_cast<uint8_t>(y.get_bit(0)));
786 x.serialize_to(stuffer.next(p_bytes));
787 y.serialize_to(stuffer.next(p_bytes));
788 } else {
789 throw Invalid_Argument("EC2OSP illegal point encoding");
790 }
791
792 return result;
793}
size_t p_bytes() const
BigInt get_affine_y() const
Definition ec_point.cpp:614

References Botan::BufferStuffer::append(), Botan::Compressed, get_affine_x(), get_affine_y(), Botan::BigInt::get_bit(), Botan::Hybrid, is_zero(), Botan::BufferStuffer::next(), Botan::EC_Group_Data::p_bytes(), Botan::BigInt::serialize_to(), and Botan::Uncompressed.

◆ force_affine()

void Botan::EC_Point::force_affine ( )

Force this point to affine coordinates

Convert the point to its equivalent affine coordinates. Throws if this is the point at infinity.

Definition at line 545 of file ec_point.cpp.

545 {
546 if(is_zero()) {
547 throw Invalid_State("Cannot convert zero ECC point to affine");
548 }
549
551
552 const auto& group = m_curve.group();
553
554 const BigInt z_inv = invert_element(group, m_z, ws);
555 const BigInt z2_inv = fe_sqr(group, z_inv, ws);
556 const BigInt z3_inv = fe_mul(group, z_inv, z2_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();
560}

References Botan::fe_mul(), and is_zero().

◆ force_all_affine()

void Botan::EC_Point::force_all_affine ( std::span< EC_Point > points,
secure_vector< word > & ws )
static

Force all points on the list to affine coordinates

Force several points to be affine at once. Uses Montgomery's trick to reduce number of inversions required, so this is much faster than calling force_affine on each point in sequence.

Definition at line 483 of file ec_point.cpp.

483 {
484 if(points.size() <= 1) {
485 for(auto& point : points) {
486 point.force_affine();
487 }
488 return;
489 }
490
491 for(auto& point : points) {
492 if(point.is_zero()) {
493 throw Invalid_State("Cannot convert zero ECC point to affine");
494 }
495 }
496
497 /*
498 For >= 2 points use Montgomery's trick
499
500 See Algorithm 2.26 in "Guide to Elliptic Curve Cryptography"
501 (Hankerson, Menezes, Vanstone)
502
503 TODO is it really necessary to save all k points in c?
504 */
505
506 const auto& group = points[0].m_curve.group();
507 const BigInt& rep_1 = group.monty().R1();
508
509 if(ws.size() < monty_ws_size(group)) {
510 ws.resize(monty_ws_size(group));
511 }
512
513 std::vector<BigInt> c(points.size());
514 c[0] = points[0].m_z;
515
516 for(size_t i = 1; i != points.size(); ++i) {
517 fe_mul(group, c[i], c[i - 1], points[i].m_z, ws);
518 }
519
520 BigInt s_inv = invert_element(group, c[c.size() - 1], ws);
521
522 BigInt z_inv, z2_inv, z3_inv;
523
524 for(size_t i = points.size() - 1; i != 0; i--) {
525 EC_Point& point = points[i];
526
527 fe_mul(group, z_inv, s_inv, c[i - 1], ws);
528
529 s_inv = fe_mul(group, s_inv, point.m_z, ws);
530
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);
535 point.m_z = rep_1;
536 }
537
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;
543}

References Botan::fe_mul().

Referenced by Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute().

◆ get_affine_x()

BigInt Botan::EC_Point::get_affine_x ( ) const

get affine x coordinate

Returns
affine x coordinate

Definition at line 592 of file ec_point.cpp.

592 {
593 if(is_zero()) {
594 throw Invalid_State("Cannot convert zero point to affine");
595 }
596
597 secure_vector<word> monty_ws;
598
599 const auto& group = m_curve.group();
600
601 if(is_affine()) {
602 return from_rep_to_tmp(group, m_x, monty_ws);
603 }
604
605 BigInt z2 = fe_sqr(group, m_z, monty_ws);
606 z2 = invert_element(group, z2, monty_ws);
607
608 BigInt r;
609 fe_mul(group, r, m_x, z2, monty_ws);
610 from_rep(group, r, monty_ws);
611 return r;
612}
bool is_affine() const
Definition ec_point.cpp:562

References Botan::fe_mul(), is_affine(), and is_zero().

Referenced by _is_x_eq_to_v_mod_order(), encode(), operator==(), and xy_bytes().

◆ get_affine_y()

BigInt Botan::EC_Point::get_affine_y ( ) const

get affine y coordinate

Returns
affine y coordinate

Definition at line 614 of file ec_point.cpp.

614 {
615 if(is_zero()) {
616 throw Invalid_State("Cannot convert zero point to affine");
617 }
618
619 const auto& group = m_curve.group();
620 secure_vector<word> monty_ws;
621
622 if(is_affine()) {
623 return from_rep_to_tmp(group, m_y, monty_ws);
624 }
625
626 const BigInt z2 = fe_sqr(group, m_z, monty_ws);
627 const BigInt z3 = fe_mul(group, m_z, z2, monty_ws);
628 const BigInt z3_inv = invert_element(group, z3, monty_ws);
629
630 BigInt r;
631 fe_mul(group, r, m_y, z3_inv, monty_ws);
632 from_rep(group, r, monty_ws);
633 return r;
634}

References Botan::fe_mul(), is_affine(), and is_zero().

Referenced by encode(), operator==(), and xy_bytes().

◆ get_curve()

const CurveGFp & Botan::EC_Point::get_curve ( ) const
inline

Return base curve of this point

Returns
the curve over GF(p) of this point

You should not need to use this

Definition at line 382 of file ec_point.h.

382{ return m_curve; }

◆ get_x()

const BigInt & Botan::EC_Point::get_x ( ) const
inline

Return the internal x coordinate

Note this may be in Montgomery form

Definition at line 237 of file ec_point.h.

237{ return m_x; }

Referenced by _is_x_eq_to_v_mod_order().

◆ get_y()

const BigInt & Botan::EC_Point::get_y ( ) const
inline

Return the internal y coordinate

Note this may be in Montgomery form

Definition at line 244 of file ec_point.h.

244{ return m_y; }

◆ get_z()

const BigInt & Botan::EC_Point::get_z ( ) const
inline

Return the internal z coordinate

Note this may be in Montgomery form

Definition at line 251 of file ec_point.h.

251{ return m_z; }

Referenced by _is_x_eq_to_v_mod_order().

◆ is_affine()

bool Botan::EC_Point::is_affine ( ) const

Definition at line 562 of file ec_point.cpp.

562 {
563 const auto& group = m_curve.group();
564 return m_z == group.monty().R1();
565}

Referenced by add_affine(), get_affine_x(), and get_affine_y().

◆ is_zero()

bool Botan::EC_Point::is_zero ( ) const
inline

Is this the point at infinity?

Returns
true, if this point is at infinity, false otherwise.

Definition at line 162 of file ec_point.h.

162{ return m_z.is_zero(); }
bool is_zero() const
Definition bigint.h:458

Referenced by _is_x_eq_to_v_mod_order(), add(), add_affine(), Botan::EC_AffinePoint_Data_BN::EC_AffinePoint_Data_BN(), Botan::EC_AffinePoint_Data_BN::EC_AffinePoint_Data_BN(), encode(), force_affine(), get_affine_x(), get_affine_y(), mult2(), on_the_curve(), operator-=(), and operator==().

◆ mul()

EC_Point Botan::EC_Point::mul ( const BigInt & scalar) const

Point multiplication operator

Simple unblinded Montgomery ladder

Warning: prefer the functions on EC_Group such as blinded_var_point_multiply

Parameters
scalarthe scalar value
Returns
*this multiplied by the scalar value

Definition at line 460 of file ec_point.cpp.

460 {
461 const size_t scalar_bits = scalar.bits();
462
463 std::vector<BigInt> ws(EC_Point::WORKSPACE_SIZE);
464
465 EC_Point R[2] = {this->zero(), *this};
466
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);
470 R[b].mult2(ws);
471 }
472
473 if(scalar.is_negative()) {
474 R[0].negate();
475 }
476
478
479 return R[0];
480}
bool on_the_curve() const
Definition ec_point.cpp:636
EC_Point zero() const
Definition ec_point.cpp:99
const SIMD_8x32 & b

References add(), Botan::b, Botan::BigInt::bits(), BOTAN_DEBUG_ASSERT, Botan::BigInt::get_bit(), Botan::BigInt::is_negative(), mult2(), negate(), on_the_curve(), WORKSPACE_SIZE, and zero().

Referenced by Botan::operator*(), and Botan::operator*().

◆ mult2()

void Botan::EC_Point::mult2 ( std::vector< BigInt > & workspace)

Point doubling

Parameters
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 351 of file ec_point.cpp.

351 {
352 if(is_zero()) {
353 return;
354 }
355
356 const auto& group = m_curve.group();
357
358 if(m_y.is_zero()) {
359 *this = EC_Point(m_curve); // setting myself to zero
360 return;
361 }
362
363 resize_ws(ws_bn, monty_ws_size(group));
364
365 secure_vector<word>& ws = ws_bn[0].get_word_vector();
366 secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
367
368 BigInt& T0 = ws_bn[2];
369 BigInt& T1 = ws_bn[3];
370 BigInt& T2 = ws_bn[4];
371 BigInt& T3 = ws_bn[5];
372 BigInt& T4 = ws_bn[6];
373
374 /*
375 https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc
376 */
377 const BigInt& p = group.p();
378
379 fe_sqr(group, T0, m_y, ws);
380
381 fe_mul(group, T1, m_x, T0, ws);
382 T1.mod_mul(4, p, sub_ws);
383
384 if(group.a_is_zero()) {
385 // if a == 0 then 3*x^2 + a*z^4 is just 3*x^2
386 fe_sqr(group, T4, m_x, ws); // x^2
387 T4.mod_mul(3, p, sub_ws); // 3*x^2
388 } else if(group.a_is_minus_3()) {
389 /*
390 if a == -3 then
391 3*x^2 + a*z^4 == 3*x^2 - 3*z^4 == 3*(x^2-z^4) == 3*(x-z^2)*(x+z^2)
392 */
393 fe_sqr(group, T3, m_z, ws); // z^2
394
395 // (x-z^2)
396 T2 = m_x;
397 T2.mod_sub(T3, p, sub_ws);
398
399 // (x+z^2)
400 T3.mod_add(m_x, p, sub_ws);
401
402 fe_mul(group, T4, T2, T3, ws); // (x-z^2)*(x+z^2)
403
404 T4.mod_mul(3, p, sub_ws); // 3*(x-z^2)*(x+z^2)
405 } else {
406 fe_sqr(group, T3, m_z, ws); // z^2
407 fe_sqr(group, T4, T3, ws); // z^4
408 fe_mul(group, T3, group.monty_a(), T4, ws); // a*z^4
409
410 fe_sqr(group, T4, m_x, ws); // x^2
411 T4.mod_mul(3, p, sub_ws);
412 T4.mod_add(T3, p, sub_ws); // 3*x^2 + a*z^4
413 }
414
415 fe_sqr(group, T2, T4, ws);
416 T2.mod_sub(T1, p, sub_ws);
417 T2.mod_sub(T1, p, sub_ws);
418
419 fe_sqr(group, T3, T0, ws);
420 T3.mod_mul(8, p, sub_ws);
421
422 T1.mod_sub(T2, p, sub_ws);
423
424 fe_mul(group, T0, T4, T1, ws);
425 T0.mod_sub(T3, p, sub_ws);
426
427 m_x.swap(T2);
428
429 fe_mul(group, T2, m_y, m_z, ws);
430 T2.mod_mul(2, p, sub_ws);
431
432 m_y.swap(T0);
433 m_z.swap(T2);
434}
BigInt & mod_add(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:45

References EC_Point(), Botan::fe_mul(), Botan::BigInt::is_zero(), is_zero(), Botan::BigInt::mod_add(), Botan::BigInt::mod_mul(), Botan::BigInt::mod_sub(), and Botan::BigInt::swap().

Referenced by add(), add_affine(), double_of(), Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute(), Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute(), mul(), and mult2i().

◆ mult2i()

void Botan::EC_Point::mult2i ( size_t i,
std::vector< BigInt > & workspace )

Repeated point doubling

Parameters
inumber of doublings to perform
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 331 of file ec_point.cpp.

331 {
332 if(iterations == 0) {
333 return;
334 }
335
336 if(m_y.is_zero()) {
337 *this = EC_Point(m_curve); // setting myself to zero
338 return;
339 }
340
341 /*
342 TODO we can save 2 squarings per iteration by computing
343 a*Z^4 using values cached from previous iteration
344 */
345 for(size_t i = 0; i != iterations; ++i) {
346 mult2(ws_bn);
347 }
348}

References EC_Point(), Botan::BigInt::is_zero(), and mult2().

Referenced by Botan::EC_Point_Var_Point_Precompute::mul(), and Botan::EC_Point_Multi_Point_Precompute::multi_exp().

◆ negate()

EC_Point & Botan::EC_Point::negate ( )
inline

Negate this point

Returns
*this

Definition at line 132 of file ec_point.h.

132 {
133 if(!is_zero()) {
134 m_y = m_curve.get_p() - m_y;
135 }
136 return *this;
137 }
const BigInt & get_p() const
Definition ec_point.cpp:40

Referenced by mul(), Botan::EC_Point_Multi_Point_Precompute::multi_exp(), Botan::operator-(), and operator-=().

◆ on_the_curve()

bool Botan::EC_Point::on_the_curve ( ) const

Checks whether the point is to be found on the underlying curve; used to prevent fault attacks.

Returns
if the point is on the curve

Definition at line 636 of file ec_point.cpp.

636 {
637 /*
638 Is the point still on the curve?? (If everything is correct, the
639 point is always on its curve; then the function will return true.
640 If somehow the state is corrupted, which suggests a fault attack
641 (or internal computational error), then return false.
642 */
643 if(is_zero()) {
644 return true;
645 }
646
647 const auto& group = m_curve.group();
648 secure_vector<word> monty_ws;
649
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);
654
655 const BigInt& monty_b = group.monty_b();
656
657 // Is z equal to 1 (in Montgomery form)?
658 if(m_z == z2) {
659 if(y2 != from_rep_to_tmp(group, x3 + ax + monty_b, monty_ws)) {
660 return false;
661 }
662 }
663
664 const BigInt z3 = fe_mul(group, m_z, z2, 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);
667
668 if(y2 != from_rep_to_tmp(group, x3 + ax_z4 + b_z6, monty_ws)) {
669 return false;
670 }
671
672 return true;
673}

References Botan::fe_mul(), and is_zero().

Referenced by Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute(), mul(), Botan::EC_Point_Base_Point_Precompute::mul(), Botan::EC_Point_Var_Point_Precompute::mul(), Botan::OS2ECP(), and Botan::EC_Group::verify_group().

◆ operator!=()

bool Botan::EC_Point::operator!= ( const EC_Point & other) const
default

◆ operator*=()

EC_Point & Botan::EC_Point::operator*= ( const BigInt & scalar)

*= Operator

Parameters
scalarthe EC_Point to multiply with *this
Returns
resulting EC_Point

Definition at line 455 of file ec_point.cpp.

455 {
456 *this = scalar * *this;
457 return *this;
458}

◆ operator+=()

EC_Point & Botan::EC_Point::operator+= ( const EC_Point & rhs)

+= Operator

Parameters
rhsthe EC_Point to add to the local value
Returns
resulting EC_Point

Definition at line 437 of file ec_point.cpp.

437 {
438 std::vector<BigInt> ws(EC_Point::WORKSPACE_SIZE);
439 add(rhs, ws);
440 return *this;
441}

References add(), and WORKSPACE_SIZE.

◆ operator-=()

EC_Point & Botan::EC_Point::operator-= ( const EC_Point & rhs)

-= Operator

Parameters
rhsthe EC_Point to subtract from the local value
Returns
resulting EC_Point

Definition at line 443 of file ec_point.cpp.

443 {
444 EC_Point minus_rhs = EC_Point(rhs).negate();
445
446 if(is_zero()) {
447 *this = minus_rhs;
448 } else {
449 *this += minus_rhs;
450 }
451
452 return *this;
453}

References EC_Point(), is_zero(), and negate().

◆ operator=() [1/2]

EC_Point & Botan::EC_Point::operator= ( const EC_Point & )
default

Standard Assignment

◆ operator=() [2/2]

EC_Point & Botan::EC_Point::operator= ( EC_Point && other)
inline

Move Assignment

Definition at line 73 of file ec_point.h.

73 {
74 if(this != &other) {
75 this->swap(other);
76 }
77 return (*this);
78 }

◆ operator==()

bool Botan::EC_Point::operator== ( const EC_Point & other) const

Equality operator

Definition at line 748 of file ec_point.cpp.

748 {
749 if(m_curve != other.m_curve) {
750 return false;
751 }
752
753 // If this is zero, only equal if other is also zero
754 if(is_zero()) {
755 return other.is_zero();
756 }
757
758 return (get_affine_x() == other.get_affine_x() && get_affine_y() == other.get_affine_y());
759}

References get_affine_x(), get_affine_y(), and is_zero().

◆ plus()

EC_Point Botan::EC_Point::plus ( const EC_Point & other,
std::vector< BigInt > & workspace ) const
inline

Point addition

Parameters
otherthe point to add to *this
workspacetemp space, at least WORKSPACE_SIZE elements
Returns
other plus *this

Definition at line 359 of file ec_point.h.

359 {
360 EC_Point x = (*this);
361 x.add(other, workspace);
362 return x;
363 }

References add().

Referenced by Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute(), and Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute().

◆ randomize_repr() [1/2]

void Botan::EC_Point::randomize_repr ( RandomNumberGenerator & rng)

Randomize the point representation The actual value (get_affine_x, get_affine_y) does not change

Definition at line 120 of file ec_point.cpp.

120 {
121 const auto& group = m_curve.group();
122 secure_vector<word> ws(monty_ws_size(group));
123 randomize_repr(rng, ws);
124}
void randomize_repr(RandomNumberGenerator &rng)
Definition ec_point.cpp:120

References randomize_repr().

Referenced by Botan::EC_Point_Var_Point_Precompute::EC_Point_Var_Point_Precompute(), Botan::EC_Point_Base_Point_Precompute::mul(), Botan::EC_Point_Var_Point_Precompute::mul(), and randomize_repr().

◆ randomize_repr() [2/2]

void Botan::EC_Point::randomize_repr ( RandomNumberGenerator & rng,
secure_vector< word > & ws )

Randomize the point representation The actual value (get_affine_x, get_affine_y) does not change

Definition at line 126 of file ec_point.cpp.

126 {
127 if(!rng.is_seeded()) {
128 return;
129 }
130
131 const auto& group = m_curve.group();
132
133 const BigInt mask = BigInt::random_integer(rng, 2, group.p());
134
135 /*
136 * No reason to convert this to Montgomery representation first,
137 * just pretend the random mask was chosen as Redc(mask) and the
138 * random mask we generated above is in the Montgomery
139 * representation.
140 */
141
142 const BigInt mask2 = fe_sqr(group, mask, ws);
143 const BigInt mask3 = fe_mul(group, mask2, mask, ws);
144
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);
148}
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition big_rand.cpp:43

References Botan::fe_mul(), Botan::RandomNumberGenerator::is_seeded(), and Botan::BigInt::random_integer().

◆ swap()

void Botan::EC_Point::swap ( EC_Point & other)
noexcept

swaps the states of *this and other

Parameters
otherthe object to swap values with

Definition at line 741 of file ec_point.cpp.

741 {
742 m_curve.swap(other.m_curve);
743 m_x.swap(other.m_x);
744 m_y.swap(other.m_y);
745 m_z.swap(other.m_z);
746}

Referenced by Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute().

◆ swap_coords()

void Botan::EC_Point::swap_coords ( BigInt & new_x,
BigInt & new_y,
BigInt & new_z )
inline

Definition at line 255 of file ec_point.h.

255 {
256 m_x.swap(new_x);
257 m_y.swap(new_y);
258 m_z.swap(new_z);
259 }

◆ x_bytes()

secure_vector< uint8_t > Botan::EC_Point::x_bytes ( ) const

Return the fixed length big endian encoding of x coordinate

Definition at line 567 of file ec_point.cpp.

567 {
568 const auto& group = m_curve.group();
569 const size_t p_bytes = group.p_bytes();
570 secure_vector<uint8_t> b(p_bytes);
571 BigInt::encode_1363(b.data(), b.size(), this->get_affine_x());
572 return b;
573}
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition bigint.h:905

References Botan::b, Botan::BigInt::encode_1363(), and Botan::EC_Group_Data::p_bytes().

◆ xy_bytes()

secure_vector< uint8_t > Botan::EC_Point::xy_bytes ( ) const

Return the fixed length concatenation of the x and y coordinates

Definition at line 583 of file ec_point.cpp.

583 {
584 const auto& group = m_curve.group();
585 const size_t p_bytes = group.p_bytes();
586 secure_vector<uint8_t> b(2 * p_bytes);
587 BigInt::encode_1363(&b[0], p_bytes, this->get_affine_x());
588 BigInt::encode_1363(&b[p_bytes], p_bytes, this->get_affine_y());
589 return b;
590}

References Botan::b, Botan::BigInt::encode_1363(), get_affine_x(), get_affine_y(), and Botan::EC_Group_Data::p_bytes().

Referenced by Botan::EC_AffinePoint_Data_BN::EC_AffinePoint_Data_BN().

◆ y_bytes()

secure_vector< uint8_t > Botan::EC_Point::y_bytes ( ) const

Return the fixed length big endian encoding of y coordinate

Definition at line 575 of file ec_point.cpp.

575 {
576 const auto& group = m_curve.group();
577 const size_t p_bytes = group.p_bytes();
578 secure_vector<uint8_t> b(p_bytes);
579 BigInt::encode_1363(b.data(), b.size(), this->get_affine_y());
580 return b;
581}

References Botan::b, Botan::BigInt::encode_1363(), and Botan::EC_Group_Data::p_bytes().

◆ zero()

EC_Point Botan::EC_Point::zero ( ) const

Return the zero (aka infinite) point associated with this curve

Definition at line 99 of file ec_point.cpp.

99 {
100 return EC_Point(m_curve);
101}

References EC_Point().

Referenced by Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute(), mul(), Botan::EC_Point_Base_Point_Precompute::mul(), and Botan::EC_Point_Multi_Point_Precompute::multi_exp().

Friends And Related Symbol Documentation

◆ EC_Point_Base_Point_Precompute

friend class EC_Point_Base_Point_Precompute
friend

Definition at line 37 of file ec_point.h.

◆ EC_Point_Multi_Point_Precompute

friend class EC_Point_Multi_Point_Precompute
friend

Definition at line 36 of file ec_point.h.

◆ EC_Point_Var_Point_Precompute

friend class EC_Point_Var_Point_Precompute
friend

Definition at line 35 of file ec_point.h.

◆ swap

void swap ( EC_Point & x,
EC_Point & y )
friend

Definition at line 261 of file ec_point.h.

261{ x.swap(y); }

The documentation for this class was generated from the following files: