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