Botan 3.11.0
Crypto and TLS for C&
ec_inner_data.cpp
Go to the documentation of this file.
1/*
2* (C) 2024 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/internal/ec_inner_data.h>
8
9#include <botan/der_enc.h>
10#include <botan/internal/ec_inner_pc.h>
11#include <botan/internal/fmt.h>
12#include <botan/internal/pcurves.h>
13#include <algorithm>
14
15#if defined(BOTAN_HAS_LEGACY_EC_POINT)
16 #include <botan/internal/ec_inner_bn.h>
17 #include <botan/internal/point_mul.h>
18#endif
19
20#if defined(BOTAN_HAS_XMD)
21 #include <botan/internal/xmd.h>
22#endif
23
24namespace Botan {
25
27
28// Note this constructor *does not* initialize m_curve, m_base_point or m_base_mult
30 const BigInt& a,
31 const BigInt& b,
32 const BigInt& g_x,
33 const BigInt& g_y,
34 const BigInt& order,
35 const BigInt& cofactor,
36 const OID& oid,
38 m_p(p),
39 m_a(a),
40 m_b(b),
41 m_g_x(g_x),
42 m_g_y(g_y),
43 m_order(order),
44 m_cofactor(cofactor),
46 m_mod_field(Barrett_Reduction::for_public_modulus(p)),
47 m_mod_order(Barrett_Reduction::for_public_modulus(order)),
48 m_monty(m_p, m_mod_field),
49#endif
50 m_oid(oid),
51 m_p_words(p.sig_words()),
52 m_p_bits(p.bits()),
53 m_order_bits(order.bits()),
54 m_order_bytes((m_order_bits + 7) / 8),
55 m_a_is_minus_3(a == p - 3),
56 m_a_is_zero(a.is_zero()),
57 m_has_cofactor(m_cofactor != 1),
58 m_order_is_less_than_p(m_order < p),
59 m_source(source) {
60 // TODO(Botan4) we can assume/assert the OID is set
61 if(!m_oid.empty()) {
62 DER_Encoder der(m_der_named_curve);
63 der.encode(m_oid);
64
65 const std::string name = m_oid.human_name_or_empty();
66 if(!name.empty()) {
67 // returns nullptr if unknown or not supported
68 m_pcurve = PCurve::PrimeOrderCurve::for_named_curve(name);
69 }
70 if(m_pcurve) {
71 m_engine = EC_Group_Engine::Optimized;
72 }
73 }
74
75 // Try a generic pcurves instance
76 if(!m_pcurve && !m_has_cofactor) {
77 m_pcurve = PCurve::PrimeOrderCurve::from_params(p, a, b, g_x, g_y, order);
78 if(m_pcurve) {
79 m_engine = EC_Group_Engine::Generic;
80 }
81 // possibly still null here, if parameters unsuitable or if the
82 // pcurves_generic module wasn't included in the build
83 }
84
85#if defined(BOTAN_HAS_LEGACY_EC_POINT)
87 m_a_r = m_monty.mul(a, m_monty.R2(), ws);
88 m_b_r = m_monty.mul(b, m_monty.R2(), ws);
89 if(!m_pcurve) {
90 m_engine = EC_Group_Engine::Legacy;
91 }
92#else
93 if(!m_pcurve) {
94 if(m_oid.empty()) {
95 throw Not_Implemented("EC_Group this group is not supported in this build configuration");
96 } else {
97 throw Not_Implemented(
98 fmt("EC_Group the group {} is not supported in this build configuration", oid.to_string()));
99 }
100 }
101#endif
102}
103
104std::shared_ptr<EC_Group_Data> EC_Group_Data::create(const BigInt& p,
105 const BigInt& a,
106 const BigInt& b,
107 const BigInt& g_x,
108 const BigInt& g_y,
109 const BigInt& order,
110 const BigInt& cofactor,
111 const OID& oid,
113 auto group = std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, source);
114
115#if defined(BOTAN_HAS_LEGACY_EC_POINT)
116 group->m_curve = CurveGFp(group.get());
117 group->m_base_point = EC_Point(group->m_curve, g_x, g_y);
118 if(!group->m_pcurve) {
119 group->m_base_mult = std::make_unique<EC_Point_Base_Point_Precompute>(group->m_base_point, group->m_mod_order);
120 }
121#endif
122
123 return group;
124}
125
127 const BigInt& a,
128 const BigInt& b,
129 const BigInt& g_x,
130 const BigInt& g_y,
131 const BigInt& order,
132 const BigInt& cofactor) const {
133 if(p != this->p()) {
134 return false;
135 }
136 if(a != this->a()) {
137 return false;
138 }
139 if(b != this->b()) {
140 return false;
141 }
142 if(order != this->order()) {
143 return false;
144 }
145 if(cofactor != this->cofactor()) {
146 return false;
147 }
148 if(g_x != this->g_x()) {
149 return false;
150 }
151 if(g_y != this->g_y()) {
152 return false;
153 }
154
155 return true;
156}
157
159 const BigInt& a,
160 const BigInt& b,
161 std::span<const uint8_t> base_pt,
162 const BigInt& order,
163 const BigInt& cofactor) const {
164 if(p != this->p()) {
165 return false;
166 }
167 if(a != this->a()) {
168 return false;
169 }
170 if(b != this->b()) {
171 return false;
172 }
173 if(order != this->order()) {
174 return false;
175 }
176 if(cofactor != this->cofactor()) {
177 return false;
178 }
179
180 const size_t field_len = this->p_bytes();
181
182 if(base_pt.size() == 1 + field_len && (base_pt[0] == 0x02 || base_pt[0] == 0x03)) {
183 // compressed
184
185 const auto g_x = m_g_x.serialize(field_len);
186 const auto g_y = m_g_y.is_odd();
187
188 const auto sec1_x = base_pt.subspan(1, field_len);
189 const bool sec1_y = (base_pt[0] == 0x03);
190
191 if(!std::ranges::equal(sec1_x, g_x)) {
192 return false;
193 }
194
195 if(sec1_y != g_y) {
196 return false;
197 }
198
199 return true;
200 } else if(base_pt.size() == 1 + 2 * field_len && base_pt[0] == 0x04) {
201 const auto g_x = m_g_x.serialize(field_len);
202 const auto g_y = m_g_y.serialize(field_len);
203
204 const auto sec1_x = base_pt.subspan(1, field_len);
205 const auto sec1_y = base_pt.subspan(1 + field_len, field_len);
206
207 if(!std::ranges::equal(sec1_x, g_x)) {
208 return false;
209 }
210
211 if(!std::ranges::equal(sec1_y, g_y)) {
212 return false;
213 }
214
215 return true;
216 } else {
217 throw Decoding_Error("Invalid base point encoding in explicit group");
218 }
219}
220
222 return params_match(other.p(), other.a(), other.b(), other.g_x(), other.g_y(), other.order(), other.cofactor());
223}
224
226 BOTAN_ARG_CHECK(!oid.empty(), "OID should be set");
227 BOTAN_STATE_CHECK(m_oid.empty() && m_der_named_curve.empty());
228 m_oid = oid;
229
230 DER_Encoder der(m_der_named_curve);
231 der.encode(m_oid);
232}
233
234std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_with_trunc(std::span<const uint8_t> bytes) const {
235 const size_t bit_length = 8 * bytes.size();
236
237 if(bit_length < order_bits()) {
238 // No shifting required, but might still need to reduce by modulus
239 return this->scalar_from_bytes_mod_order(bytes);
240 } else {
241 const size_t shift = bit_length - order_bits();
242
243 const size_t new_length = bytes.size() - (shift / 8);
244 const size_t bit_shift = shift % 8;
245
246 if(bit_shift == 0) {
247 // Easy case just read different bytes
248 return this->scalar_from_bytes_mod_order(bytes.first(new_length));
249 } else {
250 std::vector<uint8_t> sbytes(new_length);
251
252 uint8_t carry = 0;
253 for(size_t i = 0; i != new_length; ++i) {
254 const uint8_t w = bytes[i];
255 sbytes[i] = (w >> bit_shift) | carry;
256 carry = w << (8 - bit_shift);
257 }
258
259 return this->scalar_from_bytes_mod_order(sbytes);
260 }
261 }
262}
263
264std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_mod_order(std::span<const uint8_t> bytes) const {
265 if(bytes.size() > 2 * order_bytes()) {
266 return {};
267 }
268
269 if(m_pcurve) {
270 if(auto s = m_pcurve->scalar_from_wide_bytes(bytes)) {
271 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), std::move(*s));
272 } else {
273 return {};
274 }
275 } else {
276#if defined(BOTAN_HAS_LEGACY_EC_POINT)
277 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(BigInt(bytes)));
278#else
279 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
280#endif
281 }
282}
283
284std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_random(RandomNumberGenerator& rng) const {
285 if(m_pcurve) {
286 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->random_scalar(rng));
287 } else {
288#if defined(BOTAN_HAS_LEGACY_EC_POINT)
289 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(),
290 BigInt::random_integer(rng, BigInt::one(), m_order));
291#else
292 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
293#endif
294 }
295}
296
297std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_one() const {
298 if(m_pcurve) {
299 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->scalar_one());
300 } else {
301#if defined(BOTAN_HAS_LEGACY_EC_POINT)
302 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::one());
303#else
304 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
305#endif
306 }
307}
308
309std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bigint(const BigInt& bn) const {
310 if(bn <= 0 || bn >= m_order) {
311 return {};
312 }
313
314 if(m_pcurve) {
315 return this->scalar_deserialize(bn.serialize(m_order_bytes));
316 } else {
317#if defined(BOTAN_HAS_LEGACY_EC_POINT)
318 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), bn);
319#else
320 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
321#endif
322 }
323}
324
325std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(const EC_Scalar_Data& scalar,
326 RandomNumberGenerator& rng) const {
327 if(m_pcurve) {
328 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
329 auto gk_x_mod_order = m_pcurve->base_point_mul_x_mod_order(k.value(), rng);
330 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), gk_x_mod_order);
331 } else {
332#if defined(BOTAN_HAS_LEGACY_EC_POINT)
333 const auto& k = EC_Scalar_Data_BN::checked_ref(scalar);
334 BOTAN_STATE_CHECK(m_base_mult != nullptr);
335 std::vector<BigInt> ws;
336 const auto pt = m_base_mult->mul(k.value(), rng, m_order, ws);
337
338 if(pt.is_zero()) {
339 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::zero());
340 } else {
341 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(pt.get_affine_x()));
342 }
343#else
344 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
345#endif
346 }
347}
348
349std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_deserialize(std::span<const uint8_t> bytes) const {
350 if(bytes.size() != m_order_bytes) {
351 return nullptr;
352 }
353
354 if(m_pcurve) {
355 if(auto s = m_pcurve->deserialize_scalar(bytes)) {
356 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), *s);
357 } else {
358 return nullptr;
359 }
360 } else {
361#if defined(BOTAN_HAS_LEGACY_EC_POINT)
362 BigInt r(bytes);
363
364 if(r.is_zero() || r >= m_order) {
365 return nullptr;
366 }
367
368 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), std::move(r));
369#else
370 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
371#endif
372 }
373}
374
375std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_deserialize(std::span<const uint8_t> bytes) const {
376 // The deprecated "hybrid" point format
377 // TODO(Botan4) remove this
378 if(bytes.size() >= 1 + 2 * 4 && (bytes[0] == 0x06 || bytes[0] == 0x07)) {
379 const bool hdr_y_is_even = bytes[0] == 0x06;
380 const bool y_is_even = (bytes.back() & 0x01) == 0;
381
382 if(hdr_y_is_even == y_is_even) {
383 std::vector<uint8_t> sec1(bytes.begin(), bytes.end());
384 sec1[0] = 0x04;
385 return this->point_deserialize(sec1);
386 }
387 }
388
389 try {
390 if(m_pcurve) {
391 if(auto pt = m_pcurve->deserialize_point(bytes)) {
392 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(*pt));
393 } else {
394 return {};
395 }
396 } else {
397#if defined(BOTAN_HAS_LEGACY_EC_POINT)
398 auto pt = Botan::OS2ECP(bytes, m_curve);
399 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
400#else
401 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
402#endif
403 }
404 } catch(...) {
405 return {};
406 }
407}
408
409namespace {
410
411std::function<void(std::span<uint8_t>)> h2c_expand_message(std::string_view hash_fn,
412 std::span<const uint8_t> input,
413 std::span<const uint8_t> domain_sep) {
414 /*
415 * This could be extended to support expand_message_xof or a MHF like Argon2
416 */
417
418 if(hash_fn.starts_with("SHAKE")) {
419 throw Not_Implemented("Hash to curve currently does not support expand_message_xof");
420 }
421
422 return [=](std::span<uint8_t> uniform_bytes) {
423#if defined(BOTAN_HAS_XMD)
424 expand_message_xmd(hash_fn, uniform_bytes, input, domain_sep);
425#else
426 BOTAN_UNUSED(hash_fn, uniform_bytes, input, domain_sep);
427 throw Not_Implemented("Hash to curve is not implemented due to XMD being disabled");
428#endif
429 };
430}
431
432} // namespace
433
434std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_ro(std::string_view hash_fn,
435 std::span<const uint8_t> input,
436 std::span<const uint8_t> domain_sep) const {
437 if(m_pcurve) {
438 auto pt = m_pcurve->hash_to_curve_ro(h2c_expand_message(hash_fn, input, domain_sep));
439 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(pt));
440 } else {
441 throw Not_Implemented("Hash to curve is not implemented for this curve");
442 }
443}
444
445std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_nu(std::string_view hash_fn,
446 std::span<const uint8_t> input,
447 std::span<const uint8_t> domain_sep) const {
448 if(m_pcurve) {
449 auto pt = m_pcurve->hash_to_curve_nu(h2c_expand_message(hash_fn, input, domain_sep));
450 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
451 } else {
452 throw Not_Implemented("Hash to curve is not implemented for this curve");
453 }
454}
455
456std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_g_mul(const EC_Scalar_Data& scalar,
457 RandomNumberGenerator& rng) const {
458 if(m_pcurve) {
459 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
460 auto pt = m_pcurve->point_to_affine(m_pcurve->mul_by_g(k.value(), rng));
461 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
462 } else {
463#if defined(BOTAN_HAS_LEGACY_EC_POINT)
464 const auto& group = scalar.group();
465 const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);
466
467 BOTAN_STATE_CHECK(group->m_base_mult != nullptr);
468 std::vector<BigInt> ws;
469 auto pt = group->m_base_mult->mul(bn.value(), rng, m_order, ws);
470 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
471#else
472 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
473#endif
474 }
475}
476
477std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::mul_px_qy(const EC_AffinePoint_Data& p,
478 const EC_Scalar_Data& x,
479 const EC_AffinePoint_Data& q,
480 const EC_Scalar_Data& y,
481 RandomNumberGenerator& rng) const {
482 if(m_pcurve) {
483 auto pt = m_pcurve->mul_px_qy(EC_AffinePoint_Data_PC::checked_ref(p).value(),
487 rng);
488
489 if(pt) {
490 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(*pt));
491 } else {
492 return nullptr;
493 }
494 } else {
495#if defined(BOTAN_HAS_LEGACY_EC_POINT)
496 std::vector<BigInt> ws;
497 const auto& group = p.group();
498
499 // TODO this could be better!
500 const EC_Point_Var_Point_Precompute p_mul(p.to_legacy_point(), rng, ws);
501 const EC_Point_Var_Point_Precompute q_mul(q.to_legacy_point(), rng, ws);
502
503 const auto order = group->order() * group->cofactor(); // See #3800
504
505 auto px = p_mul.mul(EC_Scalar_Data_BN::checked_ref(x).value(), rng, order, ws);
506 auto qy = q_mul.mul(EC_Scalar_Data_BN::checked_ref(y).value(), rng, order, ws);
507
508 auto px_qy = px + qy;
509
510 if(!px_qy.is_zero()) {
511 px_qy.force_affine();
512 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(px_qy));
513 } else {
514 return nullptr;
515 }
516#else
517 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
518#endif
519 }
520}
521
522std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::affine_add(const EC_AffinePoint_Data& p,
523 const EC_AffinePoint_Data& q) const {
524 if(m_pcurve) {
525 auto pt = m_pcurve->point_add(EC_AffinePoint_Data_PC::checked_ref(p).value(),
527
528 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(pt));
529 } else {
530#if defined(BOTAN_HAS_LEGACY_EC_POINT)
531 auto pt = p.to_legacy_point() + q.to_legacy_point();
532 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
533#else
534 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
535#endif
536 }
537}
538
539std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::affine_neg(const EC_AffinePoint_Data& p) const {
540 if(m_pcurve) {
541 auto pt = m_pcurve->point_negate(EC_AffinePoint_Data_PC::checked_ref(p).value());
542 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt);
543 } else {
544#if defined(BOTAN_HAS_LEGACY_EC_POINT)
545 auto pt = p.to_legacy_point();
546 pt.negate(); // negates in place
547 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
548#else
549 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
550#endif
551 }
552}
553
554std::unique_ptr<EC_Mul2Table_Data> EC_Group_Data::make_mul2_table(const EC_AffinePoint_Data& h) const {
555 if(m_pcurve) {
556 return std::make_unique<EC_Mul2Table_Data_PC>(h);
557 } else {
558#if defined(BOTAN_HAS_LEGACY_EC_POINT)
559 const EC_AffinePoint_Data_BN g(shared_from_this(), this->base_point());
560 return std::make_unique<EC_Mul2Table_Data_BN>(g, h);
561#else
562 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
563#endif
564 }
565}
566
567} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
static BigInt zero()
Definition bigint.h:50
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition big_rand.cpp:44
static BigInt one()
Definition bigint.h:55
bool is_zero() const
Definition bigint.h:473
T serialize(size_t len) const
Definition bigint.h:727
DER_Encoder & encode(bool b)
Definition der_enc.cpp:252
static const EC_AffinePoint_Data_PC & checked_ref(const EC_AffinePoint_Data &data)
std::unique_ptr< EC_Scalar_Data > gk_x_mod_order(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng) const
const BigInt & p() const
const BigInt & g_x() const
std::unique_ptr< EC_AffinePoint_Data > affine_neg(const EC_AffinePoint_Data &p) const
const BigInt & a() const
std::unique_ptr< EC_Scalar_Data > scalar_from_bytes_mod_order(std::span< const uint8_t > bytes) const
std::unique_ptr< EC_AffinePoint_Data > point_deserialize(std::span< const uint8_t > bytes) const
std::unique_ptr< EC_Scalar_Data > scalar_random(RandomNumberGenerator &rng) const
std::unique_ptr< EC_Scalar_Data > scalar_deserialize(std::span< const uint8_t > bytes) const
bool params_match(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &g_x, const BigInt &g_y, const BigInt &order, const BigInt &cofactor) const
static std::shared_ptr< EC_Group_Data > create(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &g_x, const BigInt &g_y, const BigInt &order, const BigInt &cofactor, const OID &oid, EC_Group_Source source)
std::unique_ptr< EC_AffinePoint_Data > affine_add(const EC_AffinePoint_Data &p, const EC_AffinePoint_Data &q) const
std::unique_ptr< EC_Scalar_Data > scalar_from_bytes_with_trunc(std::span< const uint8_t > bytes) const
std::unique_ptr< EC_Mul2Table_Data > make_mul2_table(const EC_AffinePoint_Data &pt) const
std::unique_ptr< EC_AffinePoint_Data > mul_px_qy(const EC_AffinePoint_Data &p, const EC_Scalar_Data &x, const EC_AffinePoint_Data &q, const EC_Scalar_Data &y, RandomNumberGenerator &rng) const
std::unique_ptr< EC_Scalar_Data > scalar_one() const
const OID & oid() const
std::unique_ptr< EC_AffinePoint_Data > point_g_mul(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng) const
size_t order_bits() const
const BigInt & cofactor() const
EC_Group_Data(const EC_Group_Data &other)=delete
size_t p_bytes() const
EC_Group_Source source() const
void set_oid(const OID &oid)
const BigInt & g_y() const
size_t order_bytes() const
std::unique_ptr< EC_Scalar_Data > scalar_from_bigint(const BigInt &bn) const
std::unique_ptr< EC_AffinePoint_Data > point_hash_to_curve_ro(std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep) const
const BigInt & b() const
std::unique_ptr< EC_AffinePoint_Data > point_hash_to_curve_nu(std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep) const
const BigInt & order() const
EC_Point mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
static const EC_Scalar_Data_BN & checked_ref(const EC_Scalar_Data &data)
static const EC_Scalar_Data_PC & checked_ref(const EC_Scalar_Data &data)
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
static std::shared_ptr< const PrimeOrderCurve > from_params(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &base_x, const BigInt &base_y, const BigInt &order)
Definition pcurves.cpp:20
#define BOTAN_HAS_LEGACY_EC_POINT
Definition build.h:233
@ Generic
A generic implementation that handles many curves in one implementation.
Definition ec_group.h:52
void carry(int64_t &h0, int64_t &h1)
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68
EC_Group_Source
Definition ec_group.h:38
EC_Point OS2ECP(std::span< const uint8_t > data, const CurveGFp &curve)
Definition ec_point.cpp:866