Botan 3.13.0
Crypto and TLS for C&
ec_point.h
Go to the documentation of this file.
1/*
2* Point arithmetic on elliptic curves over GF(p)
3*
4* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
5* 2008-2011,2014,2015,2024 Jack Lloyd
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#ifndef BOTAN_EC_POINT_H_
11#define BOTAN_EC_POINT_H_
12
13// TODO(Botan4) delete this header
14
15#include <botan/curve_gfp.h>
16#include <botan/ec_point_format.h>
17#include <vector>
18
19namespace Botan {
20
21/**
22* Deprecated elliptic curve type
23*
24* Use EC_AffinePoint in new code; this type is no longer used internally at all
25* except to support very unfortunate (and deprecated) curve types, specifically
26* those with a cofactor, or with unreasonable sizes (above 521 bits), which
27* cannot be accommodated by the new faster EC library in math/pcurves. For
28* normal curves EC_AffinePoint will typically be 2 or 3 times faster.
29*
30* This type will be completely removed in Botan4
31*/
32class BOTAN_PUBLIC_API(2, 0) EC_Point final {
33 public:
37
38 /**
39 * The format used to encode a point as an octet string
40 */
42 using enum EC_Point_Format;
43
44 enum : uint8_t /* NOLINT(*-use-enum-class) */ { WORKSPACE_SIZE = 8 };
45
46 /**
47 * Construct an uninitialized EC_Point
48 */
49 EC_Point() = default;
50
51 /**
52 * Construct the zero point
53 * @param curve The base curve
54 */
55 BOTAN_DEPRECATED("Deprecated no replacement") explicit EC_Point(const CurveGFp& curve);
56
57 /**
58 * Copy constructor
59 */
60 EC_Point(const EC_Point&) = default;
61
62 /**
63 * Move Constructor
64 */
65 EC_Point(EC_Point&& other) noexcept { this->swap(other); }
66
67 /**
68 * Standard Assignment
69 */
70 EC_Point& operator=(const EC_Point&) = default;
71
72 /**
73 * Move Assignment
74 */
75 EC_Point& operator=(EC_Point&& other) noexcept {
76 if(this != &other) {
77 this->swap(other);
78 }
79 return (*this);
80 }
81
82 ~EC_Point() = default;
83
84 /**
85 * Point multiplication operator
86 *
87 * Simple unblinded Montgomery ladder
88 *
89 * Warning: prefer the functions on EC_Group such as
90 * blinded_var_point_multiply
91 *
92 * @param scalar the scalar value
93 * @return *this multiplied by the scalar value
94 */
95 EC_Point mul(const BigInt& scalar) const;
96
97 /**
98 * Construct a point from its affine coordinates
99 * @param curve the base curve
100 * @param x affine x coordinate
101 * @param y affine y coordinate
102 */
103 BOTAN_DEPRECATED("Use EC_AffinePoint::from_bigint_xy") EC_Point(const CurveGFp& curve, BigInt x, BigInt y);
104
105 /**
106 * EC2OSP - elliptic curve to octet string primitive
107 * @param format which format to encode using
108 */
109 std::vector<uint8_t> encode(EC_Point_Format format) const;
110
111 /**
112 * += Operator
113 * @param rhs the EC_Point to add to the local value
114 * @result resulting EC_Point
115 */
116 EC_Point& operator+=(const EC_Point& rhs);
117
118 /**
119 * -= Operator
120 * @param rhs the EC_Point to subtract from the local value
121 * @result resulting EC_Point
122 */
123 EC_Point& operator-=(const EC_Point& rhs);
124
125 /**
126 * *= Operator
127 * @param scalar the EC_Point to multiply with *this
128 * @result resulting EC_Point
129 */
130 EC_Point& operator*=(const BigInt& scalar);
131
132 /**
133 * Negate this point
134 * @return *this
135 */
137 if(!is_zero()) {
138 m_y = m_curve.get_p() - m_y;
139 }
140 return *this;
141 }
142
143 /**
144 * Force this point to affine coordinates
145 *
146 * Convert the point to its equivalent affine coordinates. Throws if this
147 * is the point at infinity.
148 */
149 void force_affine();
150
151 /**
152 * Force all points on the list to affine coordinates
153 *
154 * Force several points to be affine at once. Uses Montgomery's trick to
155 * reduce number of inversions required, so this is much faster than
156 * calling ``force_affine`` on each point in sequence.
157 */
158 static void force_all_affine(std::span<EC_Point> points, secure_vector<word>& ws);
159
160 /**
161 * Is this point already in affine form?
162 * @result true, if the internal representation is affine, false otherwise
163 */
164 bool is_affine() const;
165
166 /**
167 * Is this the point at infinity?
168 * @result true, if this point is at infinity, false otherwise.
169 */
170 bool is_zero() const { return m_z.is_zero(); }
171
172 /**
173 * Checks whether the point is to be found on the underlying
174 * curve; used to prevent fault attacks.
175 * @return if the point is on the curve
176 */
177 bool on_the_curve() const;
178
179 /**
180 * Return the fixed length big endian encoding of x coordinate
181 */
182 secure_vector<uint8_t> x_bytes() const;
183
184 /**
185 * Return the fixed length big endian encoding of y coordinate
186 */
187 secure_vector<uint8_t> y_bytes() const;
188
189 /**
190 * Return the fixed length concatenation of the x and y coordinates
191 */
192 secure_vector<uint8_t> xy_bytes() const;
193
194 /**
195 * get affine x coordinate
196 * @result affine x coordinate
197 */
198 BigInt get_affine_x() const;
199
200 /**
201 * get affine y coordinate
202 * @result affine y coordinate
203 */
204 BigInt get_affine_y() const;
205
206 /**
207 * Return the zero (aka infinite) point associated with this curve
208 */
209 EC_Point zero() const;
210
211 /**
212 * Randomize the point representation
213 * The actual value (get_affine_x, get_affine_y) does not change
214 */
215 void randomize_repr(RandomNumberGenerator& rng);
216
217 /**
218 * Equality operator
219 */
220 bool operator==(const EC_Point& other) const;
221
222 /**
223 * Inequality operator
224 */
225 bool operator!=(const EC_Point& other) const = default;
226
227 /**
228 * swaps the states of *this and other
229 * @param other the object to swap values with
230 */
231 void swap(EC_Point& other) noexcept;
232
233 /**
234 * For internal use only
235 */
236 bool _is_x_eq_to_v_mod_order(const BigInt& v) const;
237
238#if defined(BOTAN_DISABLE_DEPRECATED_FEATURES)
239
240 private:
241#endif
242
243 /**
244 * Return the internal x coordinate
245 *
246 * Note this may be in Montgomery form
247 */
248 BOTAN_DEPRECATED("Use affine coordinates only") const BigInt& get_x() const { return m_x; }
249
250 /**
251 * Return the internal y coordinate
252 *
253 * Note this may be in Montgomery form
254 */
255 BOTAN_DEPRECATED("Use affine coordinates only") const BigInt& get_y() const { return m_y; }
256
257 /**
258 * Return the internal z coordinate
259 *
260 * Note this may be in Montgomery form
261 */
262 BOTAN_DEPRECATED("Use affine coordinates only") const BigInt& get_z() const { return m_z; }
263
264 /**
265 * Swap the internal projective coordinates with the provided values
266 *
267 * Note these may be in Montgomery form
268 *
269 * @param new_x swapped with the internal x coordinate
270 * @param new_y swapped with the internal y coordinate
271 * @param new_z swapped with the internal z coordinate
272 */
273 BOTAN_DEPRECATED("Deprecated no replacement")
274
275 void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z) {
276 m_x.swap(new_x);
277 m_y.swap(new_y);
278 m_z.swap(new_z);
279 }
280
281 friend void swap(EC_Point& x, EC_Point& y) noexcept { x.swap(y); }
282
283 /**
284 * Randomize the point representation
285 * The actual value (get_affine_x, get_affine_y) does not change
286 */
287 void randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws);
288
289 /**
290 * Point addition
291 * @param other the point to add to *this
292 * @param workspace temp space, at least WORKSPACE_SIZE elements
293 */
294 void add(const EC_Point& other, std::vector<BigInt>& workspace);
295
296 /**
297 * Point addition. Array version.
298 *
299 * @param x_words the words of the x coordinate of the other point
300 * @param x_size size of x_words
301 * @param y_words the words of the y coordinate of the other point
302 * @param y_size size of y_words
303 * @param z_words the words of the z coordinate of the other point
304 * @param z_size size of z_words
305 * @param workspace temp space, at least WORKSPACE_SIZE elements
306 */
307 void add(const word x_words[],
308 size_t x_size,
309 const word y_words[],
310 size_t y_size,
311 const word z_words[],
312 size_t z_size,
313 std::vector<BigInt>& workspace);
314
315 /**
316 * Point addition - mixed J+A
317 *
318 * @warning This function assumes that @p other is affine, if this is not
319 * correct the result will be invalid.
320 *
321 * @param other affine point to add - assumed to be affine!
322 * @param workspace temp space, at least WORKSPACE_SIZE elements
323 */
324 void add_affine(const EC_Point& other, std::vector<BigInt>& workspace);
325
326 /**
327 * Point addition - mixed J+A. Array version.
328 *
329 * @param x_words the words of the x coordinate of the other point
330 * @param x_size size of x_words
331 * @param y_words the words of the y coordinate of the other point
332 * @param y_size size of y_words
333 * @param workspace temp space, at least WORKSPACE_SIZE elements
334 */
335 void add_affine(
336 const word x_words[], size_t x_size, const word y_words[], size_t y_size, std::vector<BigInt>& workspace);
337
338 /**
339 * Point doubling
340 * @param workspace temp space, at least WORKSPACE_SIZE elements
341 */
342 void mult2(std::vector<BigInt>& workspace);
343
344 /**
345 * Repeated point doubling
346 * @param i number of doublings to perform
347 * @param workspace temp space, at least WORKSPACE_SIZE elements
348 */
349 void mult2i(size_t i, std::vector<BigInt>& workspace);
350
351 /**
352 * Point addition
353 * @param other the point to add to *this
354 * @param workspace temp space, at least WORKSPACE_SIZE elements
355 * @return other plus *this
356 */
357 EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const {
358 EC_Point x = (*this);
359 x.add(other, workspace);
360 return x;
361 }
362
363 /**
364 * Point doubling
365 * @param workspace temp space, at least WORKSPACE_SIZE elements
366 * @return *this doubled
367 */
368 EC_Point double_of(std::vector<BigInt>& workspace) const {
369 EC_Point x = (*this);
370 x.mult2(workspace);
371 return x;
372 }
373
374 /**
375 * Return base curve of this point
376 * @result the curve over GF(p) of this point
377 *
378 * You should not need to use this
379 */
380 BOTAN_DEPRECATED("Deprecated no replacement") const CurveGFp& get_curve() const { return m_curve; }
381
382 private:
383 CurveGFp m_curve;
384 BigInt m_x, m_y, m_z;
385};
386
387/**
388* ECC point multiexponentiation - not constant time!
389* @param p1 a point
390* @param z1 a scalar
391* @param p2 a point
392* @param z2 a scalar
393* @result (p1 * z1 + p2 * z2)
394*/
395BOTAN_DEPRECATED("Use EC_AffinePoint::mul_px_qy")
396EC_Point BOTAN_PUBLIC_API(2, 0)
397 multi_exponentiate(const EC_Point& p1, const BigInt& z1, const EC_Point& p2, const BigInt& z2);
398
399// arithmetic operators
400
401/**
402* Negate a point
403* @param lhs the point to negate
404* @result the additive inverse of lhs
405*/
406inline EC_Point operator-(const EC_Point& lhs) {
407 return EC_Point(lhs).negate();
408}
409
410/**
411* Add two points
412* @param lhs the first point
413* @param rhs the second point
414* @result (lhs + rhs)
415*/
416inline EC_Point operator+(const EC_Point& lhs, const EC_Point& rhs) {
417 EC_Point tmp(lhs);
418 return tmp += rhs;
419}
420
421/**
422* Subtract one point from another
423* @param lhs the minuend
424* @param rhs the subtrahend
425* @result (lhs - rhs)
426*/
427inline EC_Point operator-(const EC_Point& lhs, const EC_Point& rhs) {
428 EC_Point tmp(lhs);
429 return tmp -= rhs;
430}
431
432/**
433* Multiply a point by a scalar
434* @param point the point
435* @param scalar the scalar
436* @result (point * scalar)
437*/
438inline EC_Point operator*(const EC_Point& point, const BigInt& scalar) {
439 return point.mul(scalar);
440}
441
442/**
443* Multiply a point by a scalar
444* @param scalar the scalar
445* @param point the point
446* @result (point * scalar)
447*/
448inline EC_Point operator*(const BigInt& scalar, const EC_Point& point) {
449 return point.mul(scalar);
450}
451
452/**
453* Perform point decoding
454* Use EC_Group::OS2ECP instead
455*/
456BOTAN_DEPRECATED("Use EC_AffinePoint::deserialize")
457EC_Point BOTAN_PUBLIC_API(2, 0) OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp& curve);
458
459/**
460* Perform point decoding
461*
462* This is an internal function which was accidentally made public.
463* Do not use it; it will be removed in Botan4.
464*
465* @param data the encoded point
466* @param data_len length of data in bytes
467* @param curve_p the curve equation prime
468* @param curve_a the curve equation a parameter
469* @param curve_b the curve equation b parameter
470*/
471BOTAN_DEPRECATED("Use EC_AffinePoint::deserialize")
472std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API
473 OS2ECP(const uint8_t data[], size_t data_len, const BigInt& curve_p, const BigInt& curve_a, const BigInt& curve_b);
474
475/**
476* Perform point decoding
477*
478* @param data the encoded point
479* @param curve the curve the point is on
480* @result the decoded point
481*/
482BOTAN_DEPRECATED("Use EC_AffinePoint::deserialize")
483EC_Point BOTAN_UNSTABLE_API OS2ECP(std::span<const uint8_t> data, const CurveGFp& curve);
484
485/**
486* The name used for the EC_Point type in older versions
487*/
489
490} // namespace Botan
491
492#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_UNSTABLE_API
Definition api.h:34
#define BOTAN_DEPRECATED(msg)
Definition api.h:73
~EC_Point()=default
EC_Point & negate()
Definition ec_point.h:136
void swap(EC_Point &other) noexcept
Definition ec_point.cpp:792
bool operator!=(const EC_Point &other) const =default
EC_Point plus(const EC_Point &other, std::vector< BigInt > &workspace) const
Definition ec_point.h:357
void add(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.cpp:266
void mult2(std::vector< BigInt > &workspace)
Definition ec_point.cpp:388
EC_Point double_of(std::vector< BigInt > &workspace) const
Definition ec_point.h:368
const BigInt & get_y() const
Definition ec_point.h:255
bool is_zero() const
Definition ec_point.h:170
friend class EC_Point_Var_Point_Precompute
Definition ec_point.h:34
const BigInt & get_z() const
Definition ec_point.h:262
void swap_coords(BigInt &new_x, BigInt &new_y, BigInt &new_z)
Definition ec_point.h:275
EC_Point & operator=(EC_Point &&other) noexcept
Definition ec_point.h:75
friend class EC_Point_Base_Point_Precompute
Definition ec_point.h:36
friend class EC_Point_Multi_Point_Precompute
Definition ec_point.h:35
EC_Point mul(const BigInt &scalar) const
Definition ec_point.cpp:497
friend void swap(EC_Point &x, EC_Point &y) noexcept
Definition ec_point.h:281
const CurveGFp & get_curve() const
Definition ec_point.h:380
EC_Point & operator=(const EC_Point &)=default
const BigInt & get_x() const
Definition ec_point.h:248
EC_Point()=default
EC_Point_Format Compression_Type
Definition ec_point.h:41
std::vector< uint8_t > encode(EC_Point_Format format) const
Definition ec_point.cpp:813
bool _is_x_eq_to_v_mod_order(const BigInt &v) const
Definition ec_point.cpp:714
BigInt operator*(const BigInt &x, const BigInt &y)
Definition big_ops3.cpp:57
EC_Point PointGFp
Definition ec_point.h:488
OctetString operator+(const OctetString &k1, const OctetString &k2)
Definition symkey.cpp:99
EC_Point multi_exponentiate(const EC_Point &p1, const BigInt &z1, const EC_Point &p2, const BigInt &z2)
Definition point_mul.cpp:36
BigInt operator-(const BigInt &x, const BigInt &y)
Definition bigint.h:1219
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
bool operator==(const AlgorithmIdentifier &x, const AlgorithmIdentifier &y)
Definition alg_id.cpp:54
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
The native machine word, used as the limb type for multiprecision integers.
Definition types.h:131
EC_Point OS2ECP(std::span< const uint8_t > data, const CurveGFp &curve)
Definition ec_point.cpp:866