/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/secmem.h> |
12 | | #include <botan/types.h> |
13 | | #include <optional> |
14 | | #include <span> |
15 | | #include <string_view> |
16 | | #include <vector> |
17 | | |
18 | | namespace Botan { |
19 | | |
20 | | class BigInt; |
21 | | class RandomNumberGenerator; |
22 | | class EC_Group; |
23 | | class EC_Scalar; |
24 | | class EC_Point; |
25 | | |
26 | | class EC_Group_Data; |
27 | | class EC_AffinePoint_Data; |
28 | | |
29 | | class BOTAN_UNSTABLE_API EC_AffinePoint final { |
30 | | public: |
31 | | /// Point deserialization. Throws if wrong length or not a valid point |
32 | | /// |
33 | | /// This accepts SEC1 compressed or uncompressed formats |
34 | | EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes); |
35 | | |
36 | | /// Point deserialization. Returns nullopt if wrong length or not a valid point |
37 | | /// |
38 | | /// This accepts SEC1 compressed or uncompressed formats |
39 | | static std::optional<EC_AffinePoint> deserialize(const EC_Group& group, std::span<const uint8_t> bytes); |
40 | | |
41 | | /// Create a point from a pair (x,y) of integers |
42 | | /// |
43 | | /// The integers must be within the field - in the range [0,p) and must |
44 | | /// satisfy the curve equation |
45 | | static std::optional<EC_AffinePoint> from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y); |
46 | | |
47 | | /// Multiply by the group generator returning a complete point |
48 | | /// |
49 | | /// Workspace argument is transitional |
50 | | static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws); |
51 | | |
52 | | /// Return the identity element |
53 | | static EC_AffinePoint identity(const EC_Group& group); |
54 | | |
55 | | /// Return the standard group generator |
56 | | static EC_AffinePoint generator(const EC_Group& group); |
57 | | |
58 | | /// Hash to curve (RFC 9380), random oracle variant |
59 | | /// |
60 | | /// Only supported for specific groups |
61 | | static EC_AffinePoint hash_to_curve_ro(const EC_Group& group, |
62 | | std::string_view hash_fn, |
63 | | std::span<const uint8_t> input, |
64 | | std::span<const uint8_t> domain_sep); |
65 | | |
66 | | /// Hash to curve (RFC 9380), non uniform variant |
67 | | /// |
68 | | /// Only supported for specific groups |
69 | | static EC_AffinePoint hash_to_curve_nu(const EC_Group& group, |
70 | | std::string_view hash_fn, |
71 | | std::span<const uint8_t> input, |
72 | | std::span<const uint8_t> domain_sep); |
73 | | |
74 | | /// Multiply a point by a scalar returning a complete point |
75 | | /// |
76 | | /// Workspace argument is transitional |
77 | | EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const; |
78 | | |
79 | | /// Compute 2-ary multiscalar multiplication - p*x + q*y |
80 | | /// |
81 | | /// This operation runs in constant time with respect to p, x, q, and y |
82 | | static EC_AffinePoint mul_px_qy(const EC_AffinePoint& p, |
83 | | const EC_Scalar& x, |
84 | | const EC_AffinePoint& q, |
85 | | const EC_Scalar& y, |
86 | | RandomNumberGenerator& rng); |
87 | | |
88 | | /// Return the number of bytes of a field element |
89 | | /// |
90 | | /// A point consists of two field elements, plus possibly a header |
91 | | size_t field_element_bytes() const; |
92 | | |
93 | | /// Return true if this point is the identity element |
94 | | bool is_identity() const; |
95 | | |
96 | | /// Write the fixed length encoding of affine x coordinate |
97 | | /// |
98 | | /// The output span must be exactly field_element_bytes long |
99 | | /// |
100 | | /// This function will fail if this point is the identity element |
101 | | void serialize_x_to(std::span<uint8_t> bytes) const; |
102 | | |
103 | | /// Write the fixed length encoding of affine y coordinate |
104 | | /// |
105 | | /// The output span must be exactly field_element_bytes long |
106 | | /// |
107 | | /// This function will fail if this point is the identity element |
108 | | void serialize_y_to(std::span<uint8_t> bytes) const; |
109 | | |
110 | | /// Write the fixed length encoding of affine x and y coordinates |
111 | | /// |
112 | | /// The output span must be exactly 2*field_element_bytes long |
113 | | /// |
114 | | /// This function will fail if this point is the identity element |
115 | | void serialize_xy_to(std::span<uint8_t> bytes) const; |
116 | | |
117 | | /// Write the fixed length SEC1 compressed encoding |
118 | | /// |
119 | | /// The output span must be exactly 1 + field_element_bytes long |
120 | | /// |
121 | | /// This function will fail if this point is the identity element |
122 | | void serialize_compressed_to(std::span<uint8_t> bytes) const; |
123 | | |
124 | | /// Return the fixed length encoding of SEC1 uncompressed encoding |
125 | | /// |
126 | | /// The output span must be exactly 1 + 2*field_element_bytes long |
127 | | /// |
128 | | /// This function will fail if this point is the identity element |
129 | | void serialize_uncompressed_to(std::span<uint8_t> bytes) const; |
130 | | |
131 | | /// Return the bytes of the affine x coordinate in a container |
132 | | /// |
133 | | /// This function will fail if this point is the identity element |
134 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
135 | 0 | T x_bytes() const { |
136 | 0 | T bytes(this->field_element_bytes()); |
137 | 0 | this->serialize_x_to(bytes); |
138 | 0 | return bytes; |
139 | 0 | } |
140 | | |
141 | | /// Return the bytes of the affine y coordinate in a container |
142 | | /// |
143 | | /// This function will fail if this point is the identity element |
144 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
145 | | T y_bytes() const { |
146 | | T bytes(this->field_element_bytes()); |
147 | | this->serialize_y_to(bytes); |
148 | | return bytes; |
149 | | } |
150 | | |
151 | | /// Return the bytes of the affine x and y coordinates in a container |
152 | | /// |
153 | | /// This function will fail if this point is the identity element |
154 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
155 | | T xy_bytes() const { |
156 | | T bytes(2 * this->field_element_bytes()); |
157 | | this->serialize_xy_to(bytes); |
158 | | return bytes; |
159 | | } |
160 | | |
161 | | /// Return the bytes of the affine x and y coordinates in a container |
162 | | /// |
163 | | /// This function will fail if this point is the identity element |
164 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
165 | 0 | T serialize_uncompressed() const { |
166 | 0 | T bytes(1 + 2 * this->field_element_bytes()); |
167 | 0 | this->serialize_uncompressed_to(bytes); |
168 | 0 | return bytes; |
169 | 0 | } |
170 | | |
171 | | /// Return the bytes of the affine x and y coordinates in a container |
172 | | /// |
173 | | /// This function will fail if this point is the identity element |
174 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
175 | | T serialize_compressed() const { |
176 | | T bytes(1 + this->field_element_bytes()); |
177 | | this->serialize_compressed_to(bytes); |
178 | | return bytes; |
179 | | } |
180 | | |
181 | | EC_AffinePoint(const EC_AffinePoint& other); |
182 | | EC_AffinePoint(EC_AffinePoint&& other) noexcept; |
183 | | |
184 | | EC_AffinePoint& operator=(const EC_AffinePoint& other); |
185 | | EC_AffinePoint& operator=(EC_AffinePoint&& other) noexcept; |
186 | | |
187 | | /** |
188 | | * Deprecated conversion |
189 | | */ |
190 | | EC_AffinePoint(const EC_Group& group, const EC_Point& pt); |
191 | | |
192 | | /** |
193 | | * Deprecated conversion |
194 | | */ |
195 | | EC_Point to_legacy_point() const; |
196 | | |
197 | | ~EC_AffinePoint(); |
198 | | |
199 | 0 | const EC_AffinePoint_Data& _inner() const { return inner(); } |
200 | | |
201 | | static EC_AffinePoint _from_inner(std::unique_ptr<EC_AffinePoint_Data> inner); |
202 | | |
203 | | const std::shared_ptr<const EC_Group_Data>& _group() const; |
204 | | |
205 | | private: |
206 | | friend class EC_Mul2Table; |
207 | | |
208 | | EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point); |
209 | | |
210 | 0 | const EC_AffinePoint_Data& inner() const { return *m_point; } |
211 | | |
212 | | std::unique_ptr<EC_AffinePoint_Data> m_point; |
213 | | }; |
214 | | |
215 | | } // namespace Botan |
216 | | |
217 | | #endif |