/src/Botan-3.4.0/build/include/public/botan/ec_point.h
Line | Count | Source (jump to first uncovered line) |
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 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 | | #include <botan/curve_gfp.h> |
14 | | #include <botan/exceptn.h> |
15 | | #include <vector> |
16 | | |
17 | | namespace Botan { |
18 | | |
19 | | enum class EC_Point_Format { |
20 | | Uncompressed = 0, |
21 | | Compressed = 1, |
22 | | |
23 | | UNCOMPRESSED BOTAN_DEPRECATED("Use EC_Point_Format::Uncompressed") = Uncompressed, |
24 | | COMPRESSED BOTAN_DEPRECATED("Use EC_Point_Format::Compressed") = Compressed, |
25 | | |
26 | | Hybrid BOTAN_DEPRECATED("Hybrid point encoding is deprecated") = 2, |
27 | | HYBRID BOTAN_DEPRECATED("Hybrid point encoding is deprecated") = 2 |
28 | | }; |
29 | | |
30 | | /** |
31 | | * This class represents one point on a curve of GF(p) |
32 | | */ |
33 | | class BOTAN_PUBLIC_API(2, 0) EC_Point final { |
34 | | public: |
35 | | typedef EC_Point_Format Compression_Type; |
36 | | using enum EC_Point_Format; |
37 | | |
38 | | enum { WORKSPACE_SIZE = 8 }; |
39 | | |
40 | | /** |
41 | | * Construct an uninitialized EC_Point |
42 | | */ |
43 | 29.8k | EC_Point() = default; |
44 | | |
45 | | /** |
46 | | * Construct the zero point |
47 | | * @param curve The base curve |
48 | | */ |
49 | | explicit EC_Point(const CurveGFp& curve); |
50 | | |
51 | | /** |
52 | | * Copy constructor |
53 | | */ |
54 | 1.24M | EC_Point(const EC_Point&) = default; |
55 | | |
56 | | /** |
57 | | * Move Constructor |
58 | | */ |
59 | 548k | EC_Point(EC_Point&& other) { this->swap(other); } |
60 | | |
61 | | /** |
62 | | * Standard Assignment |
63 | | */ |
64 | 17.0k | EC_Point& operator=(const EC_Point&) = default; |
65 | | |
66 | | /** |
67 | | * Move Assignment |
68 | | */ |
69 | 21.3k | EC_Point& operator=(EC_Point&& other) { |
70 | 21.3k | if(this != &other) { |
71 | 21.3k | this->swap(other); |
72 | 21.3k | } |
73 | 21.3k | return (*this); |
74 | 21.3k | } |
75 | | |
76 | | /** |
77 | | * Construct a point from its affine coordinates |
78 | | * Prefer EC_Group::point(x,y) for this operation. |
79 | | * @param curve the base curve |
80 | | * @param x affine x coordinate |
81 | | * @param y affine y coordinate |
82 | | */ |
83 | | EC_Point(const CurveGFp& curve, const BigInt& x, const BigInt& y); |
84 | | |
85 | | /** |
86 | | * EC2OSP - elliptic curve to octet string primitive |
87 | | * @param format which format to encode using |
88 | | */ |
89 | | std::vector<uint8_t> encode(EC_Point_Format format) const; |
90 | | |
91 | | /** |
92 | | * += Operator |
93 | | * @param rhs the EC_Point to add to the local value |
94 | | * @result resulting EC_Point |
95 | | */ |
96 | | EC_Point& operator+=(const EC_Point& rhs); |
97 | | |
98 | | /** |
99 | | * -= Operator |
100 | | * @param rhs the EC_Point to subtract from the local value |
101 | | * @result resulting EC_Point |
102 | | */ |
103 | | EC_Point& operator-=(const EC_Point& rhs); |
104 | | |
105 | | /** |
106 | | * *= Operator |
107 | | * @param scalar the EC_Point to multiply with *this |
108 | | * @result resulting EC_Point |
109 | | */ |
110 | | EC_Point& operator*=(const BigInt& scalar); |
111 | | |
112 | | /** |
113 | | * Negate this point |
114 | | * @return *this |
115 | | */ |
116 | 0 | EC_Point& negate() { |
117 | 0 | if(!is_zero()) { |
118 | 0 | m_coord_y = m_curve.get_p() - m_coord_y; |
119 | 0 | } |
120 | 0 | return *this; |
121 | 0 | } |
122 | | |
123 | | /** |
124 | | * get affine x coordinate |
125 | | * @result affine x coordinate |
126 | | */ |
127 | | BigInt get_affine_x() const; |
128 | | |
129 | | /** |
130 | | * get affine y coordinate |
131 | | * @result affine y coordinate |
132 | | */ |
133 | | BigInt get_affine_y() const; |
134 | | |
135 | | /** |
136 | | * Return the internal x coordinate |
137 | | * |
138 | | * Note this may be in Montgomery form |
139 | | */ |
140 | 29.8k | const BigInt& get_x() const { return m_coord_x; } |
141 | | |
142 | | /** |
143 | | * Return the internal y coordinate |
144 | | * |
145 | | * Note this may be in Montgomery form |
146 | | */ |
147 | 29.8k | const BigInt& get_y() const { return m_coord_y; } |
148 | | |
149 | | /** |
150 | | * Return the internal z coordinate |
151 | | * |
152 | | * Note this may be in Montgomery form |
153 | | */ |
154 | 0 | const BigInt& get_z() const { return m_coord_z; } |
155 | | |
156 | 0 | void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z) { |
157 | 0 | m_coord_x.swap(new_x); |
158 | 0 | m_coord_y.swap(new_y); |
159 | 0 | m_coord_z.swap(new_z); |
160 | 0 | } |
161 | | |
162 | | /** |
163 | | * Force this point to affine coordinates |
164 | | */ |
165 | | void force_affine(); |
166 | | |
167 | | /** |
168 | | * Force all points on the list to affine coordinates |
169 | | */ |
170 | | static void force_all_affine(std::vector<EC_Point>& points, secure_vector<word>& ws); |
171 | | |
172 | | bool is_affine() const; |
173 | | |
174 | | /** |
175 | | * Is this the point at infinity? |
176 | | * @result true, if this point is at infinity, false otherwise. |
177 | | */ |
178 | 30.2M | bool is_zero() const { return m_coord_z.is_zero(); } |
179 | | |
180 | | /** |
181 | | * Checks whether the point is to be found on the underlying |
182 | | * curve; used to prevent fault attacks. |
183 | | * @return if the point is on the curve |
184 | | */ |
185 | | bool on_the_curve() const; |
186 | | |
187 | | /** |
188 | | * swaps the states of *this and other, does not throw! |
189 | | * @param other the object to swap values with |
190 | | */ |
191 | | void swap(EC_Point& other); |
192 | | |
193 | 0 | friend void swap(EC_Point& x, EC_Point& y) { x.swap(y); } |
194 | | |
195 | | /** |
196 | | * Randomize the point representation |
197 | | * The actual value (get_affine_x, get_affine_y) does not change |
198 | | */ |
199 | | void randomize_repr(RandomNumberGenerator& rng); |
200 | | |
201 | | /** |
202 | | * Randomize the point representation |
203 | | * The actual value (get_affine_x, get_affine_y) does not change |
204 | | */ |
205 | | void randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws); |
206 | | |
207 | | /** |
208 | | * Equality operator |
209 | | */ |
210 | | bool operator==(const EC_Point& other) const; |
211 | | |
212 | | /** |
213 | | * Point addition |
214 | | * @param other the point to add to *this |
215 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
216 | | */ |
217 | 681k | void add(const EC_Point& other, std::vector<BigInt>& workspace) { |
218 | 681k | BOTAN_ARG_CHECK(m_curve == other.m_curve, "cannot add points on different curves"); |
219 | | |
220 | 681k | const size_t p_words = m_curve.get_p_words(); |
221 | | |
222 | 681k | add(other.m_coord_x.data(), |
223 | 681k | std::min(p_words, other.m_coord_x.size()), |
224 | 681k | other.m_coord_y.data(), |
225 | 681k | std::min(p_words, other.m_coord_y.size()), |
226 | 681k | other.m_coord_z.data(), |
227 | 681k | std::min(p_words, other.m_coord_z.size()), |
228 | 681k | workspace); |
229 | 681k | } |
230 | | |
231 | | /** |
232 | | * Point addition. Array version. |
233 | | * |
234 | | * @param x_words the words of the x coordinate of the other point |
235 | | * @param x_size size of x_words |
236 | | * @param y_words the words of the y coordinate of the other point |
237 | | * @param y_size size of y_words |
238 | | * @param z_words the words of the z coordinate of the other point |
239 | | * @param z_size size of z_words |
240 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
241 | | */ |
242 | | void add(const word x_words[], |
243 | | size_t x_size, |
244 | | const word y_words[], |
245 | | size_t y_size, |
246 | | const word z_words[], |
247 | | size_t z_size, |
248 | | std::vector<BigInt>& workspace); |
249 | | |
250 | | /** |
251 | | * Point addition - mixed J+A |
252 | | * @param other affine point to add - assumed to be affine! |
253 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
254 | | */ |
255 | 8.77M | void add_affine(const EC_Point& other, std::vector<BigInt>& workspace) { |
256 | 8.77M | BOTAN_ASSERT_NOMSG(m_curve == other.m_curve); |
257 | 8.77M | BOTAN_DEBUG_ASSERT(other.is_affine()); |
258 | | |
259 | 8.77M | const size_t p_words = m_curve.get_p_words(); |
260 | 8.77M | add_affine(other.m_coord_x.data(), |
261 | 8.77M | std::min(p_words, other.m_coord_x.size()), |
262 | 8.77M | other.m_coord_y.data(), |
263 | 8.77M | std::min(p_words, other.m_coord_y.size()), |
264 | 8.77M | workspace); |
265 | 8.77M | } |
266 | | |
267 | | /** |
268 | | * Point addition - mixed J+A. Array version. |
269 | | * |
270 | | * @param x_words the words of the x coordinate of the other point |
271 | | * @param x_size size of x_words |
272 | | * @param y_words the words of the y coordinate of the other point |
273 | | * @param y_size size of y_words |
274 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
275 | | */ |
276 | | void add_affine( |
277 | | const word x_words[], size_t x_size, const word y_words[], size_t y_size, std::vector<BigInt>& workspace); |
278 | | |
279 | | /** |
280 | | * Point doubling |
281 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
282 | | */ |
283 | | void mult2(std::vector<BigInt>& workspace); |
284 | | |
285 | | /** |
286 | | * Repeated point doubling |
287 | | * @param i number of doublings to perform |
288 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
289 | | */ |
290 | | void mult2i(size_t i, std::vector<BigInt>& workspace); |
291 | | |
292 | | /** |
293 | | * Point addition |
294 | | * @param other the point to add to *this |
295 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
296 | | * @return other plus *this |
297 | | */ |
298 | 681k | EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const { |
299 | 681k | EC_Point x = (*this); |
300 | 681k | x.add(other, workspace); |
301 | 681k | return x; |
302 | 681k | } |
303 | | |
304 | | /** |
305 | | * Point doubling |
306 | | * @param workspace temp space, at least WORKSPACE_SIZE elements |
307 | | * @return *this doubled |
308 | | */ |
309 | 0 | EC_Point double_of(std::vector<BigInt>& workspace) const { |
310 | 0 | EC_Point x = (*this); |
311 | 0 | x.mult2(workspace); |
312 | 0 | return x; |
313 | 0 | } |
314 | | |
315 | | /** |
316 | | * Return the zero (aka infinite) point associated with this curve |
317 | | */ |
318 | 59.7k | EC_Point zero() const { return EC_Point(m_curve); } |
319 | | |
320 | | /** |
321 | | * Return base curve of this point |
322 | | * @result the curve over GF(p) of this point |
323 | | * |
324 | | * You should not need to use this |
325 | | */ |
326 | 48 | const CurveGFp& get_curve() const { return m_curve; } |
327 | | |
328 | | private: |
329 | | CurveGFp m_curve; |
330 | | BigInt m_coord_x, m_coord_y, m_coord_z; |
331 | | }; |
332 | | |
333 | | /** |
334 | | * Point multiplication operator |
335 | | * @param scalar the scalar value |
336 | | * @param point the point value |
337 | | * @return scalar*point on the curve |
338 | | */ |
339 | | BOTAN_PUBLIC_API(2, 0) EC_Point operator*(const BigInt& scalar, const EC_Point& point); |
340 | | |
341 | | /** |
342 | | * ECC point multiexponentiation - not constant time! |
343 | | * @param p1 a point |
344 | | * @param z1 a scalar |
345 | | * @param p2 a point |
346 | | * @param z2 a scalar |
347 | | * @result (p1 * z1 + p2 * z2) |
348 | | */ |
349 | | BOTAN_PUBLIC_API(2, 0) |
350 | | EC_Point multi_exponentiate(const EC_Point& p1, const BigInt& z1, const EC_Point& p2, const BigInt& z2); |
351 | | |
352 | | // relational operators |
353 | 0 | inline bool operator!=(const EC_Point& lhs, const EC_Point& rhs) { |
354 | 0 | return !(rhs == lhs); |
355 | 0 | } |
356 | | |
357 | | // arithmetic operators |
358 | 0 | inline EC_Point operator-(const EC_Point& lhs) { |
359 | 0 | return EC_Point(lhs).negate(); |
360 | 0 | } |
361 | | |
362 | 0 | inline EC_Point operator+(const EC_Point& lhs, const EC_Point& rhs) { |
363 | 0 | EC_Point tmp(lhs); |
364 | 0 | return tmp += rhs; |
365 | 0 | } |
366 | | |
367 | 0 | inline EC_Point operator-(const EC_Point& lhs, const EC_Point& rhs) { |
368 | 0 | EC_Point tmp(lhs); |
369 | 0 | return tmp -= rhs; |
370 | 0 | } |
371 | | |
372 | 0 | inline EC_Point operator*(const EC_Point& point, const BigInt& scalar) { |
373 | 0 | return scalar * point; |
374 | 0 | } |
375 | | |
376 | | /** |
377 | | * Perform point decoding |
378 | | * Use EC_Group::OS2ECP instead |
379 | | */ |
380 | | EC_Point BOTAN_PUBLIC_API(2, 0) OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp& curve); |
381 | | |
382 | | /** |
383 | | * Perform point decoding |
384 | | * Use EC_Group::OS2ECP instead |
385 | | * |
386 | | * @param data the encoded point |
387 | | * @param data_len length of data in bytes |
388 | | * @param curve_p the curve equation prime |
389 | | * @param curve_a the curve equation a parameter |
390 | | * @param curve_b the curve equation b parameter |
391 | | */ |
392 | | std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API |
393 | | OS2ECP(const uint8_t data[], size_t data_len, const BigInt& curve_p, const BigInt& curve_a, const BigInt& curve_b); |
394 | | |
395 | | template <typename Alloc> |
396 | | EC_Point OS2ECP(const std::vector<uint8_t, Alloc>& data, const CurveGFp& curve) { |
397 | | return OS2ECP(data.data(), data.size(), curve); |
398 | | } |
399 | | |
400 | | class EC_Point_Var_Point_Precompute; |
401 | | |
402 | | // The name used for this type in older versions |
403 | | typedef EC_Point PointGFp; |
404 | | |
405 | | } // namespace Botan |
406 | | |
407 | | #endif |