/src/botan/build/include/public/botan/ec_apoint.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * (C) 2024 Jack Lloyd |
3 | | * |
4 | | * Botan is released under the Simplified BSD License (see license.txt) |
5 | | */ |
6 | | |
7 | | #ifndef BOTAN_EC_APOINT_H_ |
8 | | #define BOTAN_EC_APOINT_H_ |
9 | | |
10 | | #include <botan/concepts.h> |
11 | | #include <botan/ec_point_format.h> |
12 | | #include <botan/secmem.h> |
13 | | #include <botan/types.h> |
14 | | #include <memory> |
15 | | #include <optional> |
16 | | #include <span> |
17 | | #include <string_view> |
18 | | #include <vector> |
19 | | |
20 | | namespace Botan { |
21 | | |
22 | | class BigInt; |
23 | | class RandomNumberGenerator; |
24 | | class EC_Group; |
25 | | class EC_Scalar; |
26 | | |
27 | | #if defined(BOTAN_HAS_LEGACY_EC_POINT) |
28 | | class EC_Point; |
29 | | #endif |
30 | | |
31 | | class EC_Group_Data; |
32 | | class EC_AffinePoint_Data; |
33 | | |
34 | | /// Elliptic Curve Point in Affine Representation |
35 | | /// |
36 | | class BOTAN_PUBLIC_API(3, 6) EC_AffinePoint final { |
37 | | public: |
38 | | /// Point deserialization. Throws if wrong length or not a valid point |
39 | | /// |
40 | | /// This accepts SEC1 compressed or uncompressed formats |
41 | | EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes); |
42 | | |
43 | | /// Point deserialization. Returns nullopt if wrong length or not a valid point |
44 | | /// |
45 | | /// This accepts SEC1 compressed or uncompressed formats |
46 | | static std::optional<EC_AffinePoint> deserialize(const EC_Group& group, std::span<const uint8_t> bytes); |
47 | | |
48 | | /// Create a point from a pair (x,y) of integers |
49 | | /// |
50 | | /// The integers must be within the field - in the range [0,p) and must |
51 | | /// satisfy the curve equation |
52 | | static std::optional<EC_AffinePoint> from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y); |
53 | | |
54 | | /// Multiply by the group generator returning a complete point |
55 | | static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng); |
56 | | |
57 | | /// Return the identity element |
58 | | static EC_AffinePoint identity(const EC_Group& group); |
59 | | |
60 | | /// Return the standard group generator |
61 | | static EC_AffinePoint generator(const EC_Group& group); |
62 | | |
63 | | /// Hash to curve (RFC 9380), random oracle variant |
64 | | /// |
65 | | /// Only supported for specific groups |
66 | | static EC_AffinePoint hash_to_curve_ro(const EC_Group& group, |
67 | | std::string_view hash_fn, |
68 | | std::span<const uint8_t> input, |
69 | | std::span<const uint8_t> domain_sep); |
70 | | |
71 | | /// Hash to curve (RFC 9380), random oracle variant |
72 | | /// |
73 | | /// Only supported for specific groups |
74 | | static EC_AffinePoint hash_to_curve_ro(const EC_Group& group, |
75 | | std::string_view hash_fn, |
76 | | std::span<const uint8_t> input, |
77 | | std::string_view domain_sep); |
78 | | |
79 | | /// Hash to curve (RFC 9380), non uniform variant |
80 | | /// |
81 | | /// Only supported for specific groups |
82 | | static EC_AffinePoint hash_to_curve_nu(const EC_Group& group, |
83 | | std::string_view hash_fn, |
84 | | std::span<const uint8_t> input, |
85 | | std::span<const uint8_t> domain_sep); |
86 | | |
87 | | /// Hash to curve (RFC 9380), non uniform variant |
88 | | /// |
89 | | /// Only supported for specific groups |
90 | | static EC_AffinePoint hash_to_curve_nu(const EC_Group& group, |
91 | | std::string_view hash_fn, |
92 | | std::span<const uint8_t> input, |
93 | | std::string_view domain_sep); |
94 | | |
95 | | /// Multiply a point by a scalar returning a complete point |
96 | | EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const; |
97 | | |
98 | | /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only |
99 | | secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const; |
100 | | |
101 | | /// Compute 2-ary multiscalar multiplication - p*x + q*y |
102 | | /// |
103 | | /// This operation runs in constant time with respect to p, x, q, and y |
104 | | /// |
105 | | /// @returns p*x+q*y, or nullopt if the result was the point at infinity |
106 | | static std::optional<EC_AffinePoint> mul_px_qy(const EC_AffinePoint& p, |
107 | | const EC_Scalar& x, |
108 | | const EC_AffinePoint& q, |
109 | | const EC_Scalar& y, |
110 | | RandomNumberGenerator& rng); |
111 | | |
112 | | /// Point addition |
113 | | /// |
114 | | /// Note that this is quite slow since it converts the resulting |
115 | | /// projective point immediately to affine coordinates, which requires a |
116 | | /// field inversion. This can be sufficient when implementing protocols |
117 | | /// that just need to perform a few additions. |
118 | | /// |
119 | | /// In the future a cooresponding EC_ProjectivePoint type may be added |
120 | | /// which would avoid the expensive affine conversions |
121 | | EC_AffinePoint add(const EC_AffinePoint& q) const; |
122 | | |
123 | | /// Point negation |
124 | | EC_AffinePoint negate() const; |
125 | | |
126 | | /// Return the number of bytes of a field element |
127 | | /// |
128 | | /// A point consists of two field elements, plus possibly a header |
129 | | size_t field_element_bytes() const; |
130 | | |
131 | | /// Return true if this point is the identity element |
132 | | bool is_identity() const; |
133 | | |
134 | | /// Write the fixed length encoding of affine x coordinate |
135 | | /// |
136 | | /// The output span must be exactly field_element_bytes long |
137 | | /// |
138 | | /// This function will fail if this point is the identity element |
139 | | void serialize_x_to(std::span<uint8_t> bytes) const; |
140 | | |
141 | | /// Write the fixed length encoding of affine y coordinate |
142 | | /// |
143 | | /// The output span must be exactly field_element_bytes long |
144 | | /// |
145 | | /// This function will fail if this point is the identity element |
146 | | void serialize_y_to(std::span<uint8_t> bytes) const; |
147 | | |
148 | | /// Write the fixed length encoding of affine x and y coordinates |
149 | | /// |
150 | | /// The output span must be exactly 2*field_element_bytes long |
151 | | /// |
152 | | /// This function will fail if this point is the identity element |
153 | | void serialize_xy_to(std::span<uint8_t> bytes) const; |
154 | | |
155 | | /// Write the fixed length SEC1 compressed encoding |
156 | | /// |
157 | | /// The output span must be exactly 1 + field_element_bytes long |
158 | | /// |
159 | | /// This function will fail if this point is the identity element |
160 | | void serialize_compressed_to(std::span<uint8_t> bytes) const; |
161 | | |
162 | | /// Return the fixed length encoding of SEC1 uncompressed encoding |
163 | | /// |
164 | | /// The output span must be exactly 1 + 2*field_element_bytes long |
165 | | /// |
166 | | /// This function will fail if this point is the identity element |
167 | | void serialize_uncompressed_to(std::span<uint8_t> bytes) const; |
168 | | |
169 | | /// Return the bytes of the affine x coordinate in a container |
170 | | /// |
171 | | /// This function will fail if this point is the identity element |
172 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
173 | 0 | T x_bytes() const { |
174 | 0 | T bytes(this->field_element_bytes()); |
175 | 0 | this->serialize_x_to(bytes); |
176 | 0 | return bytes; |
177 | 0 | } |
178 | | |
179 | | /// Return the bytes of the affine y coordinate in a container |
180 | | /// |
181 | | /// This function will fail if this point is the identity element |
182 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
183 | 0 | T y_bytes() const { |
184 | 0 | T bytes(this->field_element_bytes()); |
185 | 0 | this->serialize_y_to(bytes); |
186 | 0 | return bytes; |
187 | 0 | } |
188 | | |
189 | | /// Return the bytes of the affine x and y coordinates in a container |
190 | | /// |
191 | | /// This function will fail if this point is the identity element |
192 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
193 | 0 | T xy_bytes() const { |
194 | 0 | T bytes(2 * this->field_element_bytes()); |
195 | 0 | this->serialize_xy_to(bytes); |
196 | 0 | return bytes; |
197 | 0 | } Unexecuted instantiation: _ZNK5Botan14EC_AffinePoint8xy_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEET_v Unexecuted instantiation: _ZNK5Botan14EC_AffinePoint8xy_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS3_9allocatorIhEEEEEET_v |
198 | | |
199 | | /// Return the bytes of the affine x and y coordinates in a container |
200 | | /// |
201 | | /// This function will fail if this point is the identity element |
202 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
203 | 20.2k | T serialize_uncompressed() const { |
204 | 20.2k | T bytes(1 + 2 * this->field_element_bytes()); |
205 | 20.2k | this->serialize_uncompressed_to(bytes); |
206 | 20.2k | return bytes; |
207 | 20.2k | } |
208 | | |
209 | | /// Return the bytes of the affine x and y coordinates in a container |
210 | | /// |
211 | | /// This function will fail if this point is the identity element |
212 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
213 | 9 | T serialize_compressed() const { |
214 | 9 | T bytes(1 + this->field_element_bytes()); |
215 | 9 | this->serialize_compressed_to(bytes); |
216 | 9 | return bytes; |
217 | 9 | } |
218 | | |
219 | | bool operator==(const EC_AffinePoint& other) const; |
220 | | |
221 | 668 | bool operator!=(const EC_AffinePoint& other) const { return !(*this == other); } |
222 | | |
223 | | /// Return an encoding depending on the requested format |
224 | | std::vector<uint8_t> serialize(EC_Point_Format format) const; |
225 | | |
226 | | EC_AffinePoint(const EC_AffinePoint& other); |
227 | | EC_AffinePoint(EC_AffinePoint&& other) noexcept; |
228 | | |
229 | | EC_AffinePoint& operator=(const EC_AffinePoint& other); |
230 | | EC_AffinePoint& operator=(EC_AffinePoint&& other) noexcept; |
231 | | |
232 | | #if defined(BOTAN_HAS_LEGACY_EC_POINT) |
233 | | /** |
234 | | * Deprecated conversion |
235 | | */ |
236 | | EC_AffinePoint(const EC_Group& group, const EC_Point& pt); |
237 | | |
238 | | /** |
239 | | * Deprecated conversion |
240 | | */ |
241 | | EC_Point to_legacy_point() const; |
242 | | #endif |
243 | | |
244 | | BOTAN_DEPRECATED("Use version without workspace arg") |
245 | 501 | static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& /*ws*/) { |
246 | 501 | return EC_AffinePoint::g_mul(scalar, rng); |
247 | 501 | } |
248 | | |
249 | | BOTAN_DEPRECATED("Use version without workspace arg") |
250 | 501 | EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& /*ws*/) const { |
251 | 501 | return this->mul(scalar, rng); |
252 | 501 | } |
253 | | |
254 | | /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only |
255 | | secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, |
256 | | RandomNumberGenerator& rng, |
257 | 0 | std::vector<BigInt>& /*ws*/) const { |
258 | 0 | return this->mul_x_only(scalar, rng); |
259 | 0 | } |
260 | | |
261 | | ~EC_AffinePoint(); |
262 | | |
263 | 2.97k | const EC_AffinePoint_Data& _inner() const { return inner(); } |
264 | | |
265 | | static EC_AffinePoint _from_inner(std::unique_ptr<EC_AffinePoint_Data> inner); |
266 | | |
267 | | const std::shared_ptr<const EC_Group_Data>& _group() const; |
268 | | |
269 | | private: |
270 | | friend class EC_Mul2Table; |
271 | | |
272 | | explicit EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point); |
273 | | |
274 | 94.5k | const EC_AffinePoint_Data& inner() const { return *m_point; } |
275 | | |
276 | | std::unique_ptr<EC_AffinePoint_Data> m_point; |
277 | | }; |
278 | | |
279 | | } // namespace Botan |
280 | | |
281 | | #endif |