/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_UNSTABLE_API 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), non uniform variant |
72 | | /// |
73 | | /// Only supported for specific groups |
74 | | static EC_AffinePoint hash_to_curve_nu(const EC_Group& group, |
75 | | std::string_view hash_fn, |
76 | | std::span<const uint8_t> input, |
77 | | std::span<const uint8_t> domain_sep); |
78 | | |
79 | | /// Multiply a point by a scalar returning a complete point |
80 | | EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const; |
81 | | |
82 | | /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only |
83 | | secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const; |
84 | | |
85 | | /// Compute 2-ary multiscalar multiplication - p*x + q*y |
86 | | /// |
87 | | /// This operation runs in constant time with respect to p, x, q, and y |
88 | | /// |
89 | | /// @returns p*x+q*y, or nullopt if the result was the point at infinity |
90 | | static std::optional<EC_AffinePoint> mul_px_qy(const EC_AffinePoint& p, |
91 | | const EC_Scalar& x, |
92 | | const EC_AffinePoint& q, |
93 | | const EC_Scalar& y, |
94 | | RandomNumberGenerator& rng); |
95 | | |
96 | | /// Point addition |
97 | | /// |
98 | | /// Note that this is quite slow since it converts the resulting |
99 | | /// projective point immediately to affine coordinates, which requires a |
100 | | /// field inversion. This can be sufficient when implementing protocols |
101 | | /// that just need to perform a few additions. |
102 | | /// |
103 | | /// In the future a cooresponding EC_ProjectivePoint type may be added |
104 | | /// which would avoid the expensive affine conversions |
105 | | EC_AffinePoint add(const EC_AffinePoint& q) const; |
106 | | |
107 | | /// Point negation |
108 | | EC_AffinePoint negate() const; |
109 | | |
110 | | /// Return the number of bytes of a field element |
111 | | /// |
112 | | /// A point consists of two field elements, plus possibly a header |
113 | | size_t field_element_bytes() const; |
114 | | |
115 | | /// Return true if this point is the identity element |
116 | | bool is_identity() const; |
117 | | |
118 | | /// Write the fixed length encoding of affine x coordinate |
119 | | /// |
120 | | /// The output span must be exactly field_element_bytes long |
121 | | /// |
122 | | /// This function will fail if this point is the identity element |
123 | | void serialize_x_to(std::span<uint8_t> bytes) const; |
124 | | |
125 | | /// Write the fixed length encoding of affine y coordinate |
126 | | /// |
127 | | /// The output span must be exactly field_element_bytes long |
128 | | /// |
129 | | /// This function will fail if this point is the identity element |
130 | | void serialize_y_to(std::span<uint8_t> bytes) const; |
131 | | |
132 | | /// Write the fixed length encoding of affine x and y coordinates |
133 | | /// |
134 | | /// The output span must be exactly 2*field_element_bytes long |
135 | | /// |
136 | | /// This function will fail if this point is the identity element |
137 | | void serialize_xy_to(std::span<uint8_t> bytes) const; |
138 | | |
139 | | /// Write the fixed length SEC1 compressed encoding |
140 | | /// |
141 | | /// The output span must be exactly 1 + field_element_bytes long |
142 | | /// |
143 | | /// This function will fail if this point is the identity element |
144 | | void serialize_compressed_to(std::span<uint8_t> bytes) const; |
145 | | |
146 | | /// Return the fixed length encoding of SEC1 uncompressed encoding |
147 | | /// |
148 | | /// The output span must be exactly 1 + 2*field_element_bytes long |
149 | | /// |
150 | | /// This function will fail if this point is the identity element |
151 | | void serialize_uncompressed_to(std::span<uint8_t> bytes) const; |
152 | | |
153 | | /// Return the bytes of the affine x coordinate in a container |
154 | | /// |
155 | | /// This function will fail if this point is the identity element |
156 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
157 | 0 | T x_bytes() const { |
158 | 0 | T bytes(this->field_element_bytes()); |
159 | 0 | this->serialize_x_to(bytes); |
160 | 0 | return bytes; |
161 | 0 | } |
162 | | |
163 | | /// Return the bytes of the affine y coordinate in a container |
164 | | /// |
165 | | /// This function will fail if this point is the identity element |
166 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
167 | | T y_bytes() const { |
168 | | T bytes(this->field_element_bytes()); |
169 | | this->serialize_y_to(bytes); |
170 | | return bytes; |
171 | | } |
172 | | |
173 | | /// Return the bytes of the affine x and y coordinates in a container |
174 | | /// |
175 | | /// This function will fail if this point is the identity element |
176 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
177 | | T xy_bytes() const { |
178 | | T bytes(2 * this->field_element_bytes()); |
179 | | this->serialize_xy_to(bytes); |
180 | | return bytes; |
181 | | } |
182 | | |
183 | | /// Return the bytes of the affine x and y coordinates in a container |
184 | | /// |
185 | | /// This function will fail if this point is the identity element |
186 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
187 | 0 | T serialize_uncompressed() const { |
188 | 0 | T bytes(1 + 2 * this->field_element_bytes()); |
189 | 0 | this->serialize_uncompressed_to(bytes); |
190 | 0 | return bytes; |
191 | 0 | } |
192 | | |
193 | | /// Return the bytes of the affine x and y coordinates in a container |
194 | | /// |
195 | | /// This function will fail if this point is the identity element |
196 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
197 | 0 | T serialize_compressed() const { |
198 | 0 | T bytes(1 + this->field_element_bytes()); |
199 | 0 | this->serialize_compressed_to(bytes); |
200 | 0 | return bytes; |
201 | 0 | } |
202 | | |
203 | | bool operator==(const EC_AffinePoint& other) const; |
204 | | |
205 | 0 | bool operator!=(const EC_AffinePoint& other) const { return !(*this == other); } |
206 | | |
207 | | /// Return an encoding depending on the requested format |
208 | | std::vector<uint8_t> serialize(EC_Point_Format format) const; |
209 | | |
210 | | EC_AffinePoint(const EC_AffinePoint& other); |
211 | | EC_AffinePoint(EC_AffinePoint&& other) noexcept; |
212 | | |
213 | | EC_AffinePoint& operator=(const EC_AffinePoint& other); |
214 | | EC_AffinePoint& operator=(EC_AffinePoint&& other) noexcept; |
215 | | |
216 | | #if defined(BOTAN_HAS_LEGACY_EC_POINT) |
217 | | /** |
218 | | * Deprecated conversion |
219 | | */ |
220 | | EC_AffinePoint(const EC_Group& group, const EC_Point& pt); |
221 | | |
222 | | /** |
223 | | * Deprecated conversion |
224 | | */ |
225 | | EC_Point to_legacy_point() const; |
226 | | #endif |
227 | | |
228 | | BOTAN_DEPRECATED("Use version without workspace arg") |
229 | 0 | static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>&) { |
230 | 0 | return EC_AffinePoint::g_mul(scalar, rng); |
231 | 0 | } |
232 | | |
233 | | BOTAN_DEPRECATED("Use version without workspace arg") |
234 | 0 | EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>&) const { |
235 | 0 | return this->mul(scalar, rng); |
236 | 0 | } |
237 | | |
238 | | /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only |
239 | | secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, |
240 | | RandomNumberGenerator& rng, |
241 | 0 | std::vector<BigInt>&) const { |
242 | 0 | return this->mul_x_only(scalar, rng); |
243 | 0 | } |
244 | | |
245 | | ~EC_AffinePoint(); |
246 | | |
247 | 1.18k | const EC_AffinePoint_Data& _inner() const { return inner(); } |
248 | | |
249 | | static EC_AffinePoint _from_inner(std::unique_ptr<EC_AffinePoint_Data> inner); |
250 | | |
251 | | const std::shared_ptr<const EC_Group_Data>& _group() const; |
252 | | |
253 | | private: |
254 | | friend class EC_Mul2Table; |
255 | | |
256 | | EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point); |
257 | | |
258 | 4.66k | const EC_AffinePoint_Data& inner() const { return *m_point; } |
259 | | |
260 | | std::unique_ptr<EC_AffinePoint_Data> m_point; |
261 | | }; |
262 | | |
263 | | } // namespace Botan |
264 | | |
265 | | #endif |