Botan 3.13.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/barrett.h>
11#include <botan/internal/ec_inner_pc.h>
12#include <botan/internal/fmt.h>
13#include <botan/internal/pcurves.h>
14#include <algorithm>
15
16#if defined(BOTAN_HAS_LEGACY_EC_POINT)
17 #include <botan/internal/ec_inner_bn.h>
18 #include <botan/internal/point_mul.h>
19#endif
20
21#if defined(BOTAN_HAS_XMD)
22 #include <botan/hash.h>
23 #include <botan/internal/xmd.h>
24#endif
25
26namespace Botan {
27
29
30// Note this constructor *does not* initialize m_curve, m_base_point or m_base_mult
32 const BigInt& a,
33 const BigInt& b,
34 const BigInt& g_x,
35 const BigInt& g_y,
36 const BigInt& order,
37 const BigInt& cofactor,
38 const OID& oid,
40 m_p(p),
41 m_a(a),
42 m_b(b),
43 m_g_x(g_x),
44 m_g_y(g_y),
45 m_order(order),
46 m_cofactor(cofactor),
48 m_mod_field(Barrett_Reduction::for_public_modulus(p)),
49 m_mod_order(Barrett_Reduction::for_public_modulus(order)),
50 m_monty(m_p, m_mod_field),
51#endif
52 m_oid(oid),
53 m_p_words(p.sig_words()),
54 m_p_bits(p.bits()),
55 m_order_bits(order.bits()),
56 m_order_bytes((m_order_bits + 7) / 8),
57 m_a_is_minus_3(a == p - 3),
58 m_a_is_zero(a.is_zero()),
59 m_has_cofactor(m_cofactor != 1),
60 m_order_is_less_than_p(m_order < p),
61 m_source(source) {
62 // Verify the generator (x, y) satisfies y^2 = x^3 + a*x + b (mod p)
64 const BigInt y2 = mod_p.square(g_y);
65 const BigInt x3_ax_b = mod_p.reduce(mod_p.cube(g_x) + mod_p.multiply(a, g_x) + b);
66 if(y2 != x3_ax_b) {
67 throw Invalid_Argument("EC_Group generator is not on the curve");
68 }
69
70 // TODO(Botan4) we can assume/assert the OID is set
71 if(!m_oid.empty()) {
72 DER_Encoder der(m_der_named_curve);
73 der.encode(m_oid);
74
75 if(const auto name = m_oid.registered_name()) {
76 // returns nullptr if unknown or not supported
78 }
79 if(m_pcurve) {
81 }
82 }
83
84 // Try a generic pcurves instance
85 if(!m_pcurve && !m_has_cofactor) {
87 if(m_pcurve) {
88 m_engine = EC_Group_Engine::Generic;
89 }
90 // possibly still null here, if parameters unsuitable or if the
91 // pcurves_generic module wasn't included in the build
92 }
93
94#if defined(BOTAN_HAS_LEGACY_EC_POINT)
96 m_a_r = m_monty.mul(a, m_monty.R2(), ws);
97 m_b_r = m_monty.mul(b, m_monty.R2(), ws);
98 if(!m_pcurve) {
99 m_engine = EC_Group_Engine::Legacy;
100 }
101#else
102 if(!m_pcurve) {
103 if(m_oid.empty()) {
104 throw Not_Implemented("EC_Group this group is not supported in this build configuration");
105 } else {
106 throw Not_Implemented(
107 fmt("EC_Group the group {} is not supported in this build configuration", oid.to_string()));
108 }
109 }
110#endif
111}
112
113std::shared_ptr<EC_Group_Data> EC_Group_Data::create(const BigInt& p,
114 const BigInt& a,
115 const BigInt& b,
116 const BigInt& g_x,
117 const BigInt& g_y,
118 const BigInt& order,
119 const BigInt& cofactor,
120 const OID& oid,
122 auto group = std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, source);
123
124#if defined(BOTAN_HAS_LEGACY_EC_POINT)
125 group->m_curve = CurveGFp(group.get());
126 group->m_base_point = EC_Point(group->m_curve, g_x, g_y);
127 if(!group->m_pcurve) {
128 group->m_base_mult = std::make_unique<EC_Point_Base_Point_Precompute>(group->m_base_point, group->m_mod_order);
129 }
130#endif
131
132 return group;
133}
134
136 const BigInt& a,
137 const BigInt& b,
138 const BigInt& g_x,
139 const BigInt& g_y,
140 const BigInt& order,
141 const BigInt& cofactor) const {
142 if(p != this->p()) {
143 return false;
144 }
145 if(a != this->a()) {
146 return false;
147 }
148 if(b != this->b()) {
149 return false;
150 }
151 if(order != this->order()) {
152 return false;
153 }
154 if(cofactor != this->cofactor()) {
155 return false;
156 }
157 if(g_x != this->g_x()) {
158 return false;
159 }
160 if(g_y != this->g_y()) {
161 return false;
162 }
163
164 return true;
165}
166
168 const BigInt& a,
169 const BigInt& b,
170 std::span<const uint8_t> base_pt,
171 const BigInt& order,
172 const BigInt& cofactor) const {
173 if(p != this->p()) {
174 return false;
175 }
176 if(a != this->a()) {
177 return false;
178 }
179 if(b != this->b()) {
180 return false;
181 }
182 if(order != this->order()) {
183 return false;
184 }
185 if(cofactor != this->cofactor()) {
186 return false;
187 }
188
189 const size_t field_len = this->p_bytes();
190
191 if(base_pt.size() == 1 + field_len && (base_pt[0] == 0x02 || base_pt[0] == 0x03)) {
192 // compressed
193
194 const auto g_x = m_g_x.serialize(field_len);
195 const auto g_y = m_g_y.is_odd();
196
197 const auto sec1_x = base_pt.subspan(1, field_len);
198 const bool sec1_y = (base_pt[0] == 0x03);
199
200 if(!std::ranges::equal(sec1_x, g_x)) {
201 return false;
202 }
203
204 if(sec1_y != g_y) {
205 return false;
206 }
207
208 return true;
209 } else if(base_pt.size() == 1 + 2 * field_len && base_pt[0] == 0x04) {
210 const auto g_x = m_g_x.serialize(field_len);
211 const auto g_y = m_g_y.serialize(field_len);
212
213 const auto sec1_x = base_pt.subspan(1, field_len);
214 const auto sec1_y = base_pt.subspan(1 + field_len, field_len);
215
216 if(!std::ranges::equal(sec1_x, g_x)) {
217 return false;
218 }
219
220 if(!std::ranges::equal(sec1_y, g_y)) {
221 return false;
222 }
223
224 return true;
225 } else {
226 throw Decoding_Error("Invalid base point encoding in explicit group");
227 }
228}
229
231 return params_match(other.p(), other.a(), other.b(), other.g_x(), other.g_y(), other.order(), other.cofactor());
232}
233
235 BOTAN_ARG_CHECK(!oid.empty(), "OID should be set");
236 BOTAN_STATE_CHECK(m_oid.empty() && m_der_named_curve.empty());
237 m_oid = oid;
238
239 DER_Encoder der(m_der_named_curve);
240 der.encode(m_oid);
241}
242
243std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_with_trunc(std::span<const uint8_t> bytes) const {
244 const size_t bit_length = 8 * bytes.size();
245
246 if(bit_length < order_bits()) {
247 // No shifting required, but might still need to reduce by modulus
248 return this->scalar_from_bytes_mod_order(bytes);
249 } else {
250 const size_t shift = bit_length - order_bits();
251
252 const size_t new_length = bytes.size() - (shift / 8);
253 const size_t bit_shift = shift % 8;
254
255 if(bit_shift == 0) {
256 // Easy case just read different bytes
257 return this->scalar_from_bytes_mod_order(bytes.first(new_length));
258 } else {
259 std::vector<uint8_t> sbytes(new_length);
260
261 uint8_t carry = 0;
262 for(size_t i = 0; i != new_length; ++i) {
263 const uint8_t w = bytes[i];
264 sbytes[i] = (w >> bit_shift) | carry;
265 carry = w << (8 - bit_shift);
266 }
267
268 return this->scalar_from_bytes_mod_order(sbytes);
269 }
270 }
271}
272
273std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_mod_order(std::span<const uint8_t> bytes) const {
274 if(bytes.size() > 2 * order_bytes()) {
275 return {};
276 }
277
278 if(m_pcurve) {
279 if(auto s = m_pcurve->scalar_from_wide_bytes(bytes)) {
280 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), std::move(*s));
281 } else {
282 return {};
283 }
284 } else {
285#if defined(BOTAN_HAS_LEGACY_EC_POINT)
286 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(BigInt(bytes)));
287#else
288 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
289#endif
290 }
291}
292
293std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_random(RandomNumberGenerator& rng) const {
294 if(m_pcurve) {
295 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->random_scalar(rng));
296 } else {
297#if defined(BOTAN_HAS_LEGACY_EC_POINT)
298 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(),
299 BigInt::random_integer(rng, BigInt::one(), m_order));
300#else
301 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
302#endif
303 }
304}
305
306std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_one() const {
307 if(m_pcurve) {
308 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->scalar_one());
309 } else {
310#if defined(BOTAN_HAS_LEGACY_EC_POINT)
311 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::one());
312#else
313 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
314#endif
315 }
316}
317
318std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bigint(const BigInt& bn) const {
319 if(bn <= 0 || bn >= m_order) {
320 return {};
321 }
322
323 if(m_pcurve) {
324 return this->scalar_deserialize(bn.serialize(m_order_bytes));
325 } else {
326#if defined(BOTAN_HAS_LEGACY_EC_POINT)
327 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), bn);
328#else
329 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
330#endif
331 }
332}
333
334std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(const EC_Scalar_Data& scalar,
335 RandomNumberGenerator& rng) const {
336 if(m_pcurve) {
337 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
338 auto gk_x_mod_order = m_pcurve->base_point_mul_x_mod_order(k.value(), rng);
339 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), gk_x_mod_order);
340 } else {
341#if defined(BOTAN_HAS_LEGACY_EC_POINT)
342 const auto& k = EC_Scalar_Data_BN::checked_ref(scalar);
343 BOTAN_STATE_CHECK(m_base_mult != nullptr);
344 std::vector<BigInt> ws;
345 const auto pt = m_base_mult->mul(k.value(), rng, m_order, ws);
346
347 if(pt.is_zero()) {
348 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::zero());
349 } else {
350 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(pt.get_affine_x()));
351 }
352#else
353 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
354#endif
355 }
356}
357
358std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_deserialize(std::span<const uint8_t> bytes) const {
359 if(bytes.size() != m_order_bytes) {
360 return nullptr;
361 }
362
363 if(m_pcurve) {
364 if(auto s = m_pcurve->deserialize_scalar(bytes)) {
365 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), *s);
366 } else {
367 return nullptr;
368 }
369 } else {
370#if defined(BOTAN_HAS_LEGACY_EC_POINT)
371 BigInt r(bytes);
372
373 if(r.is_zero() || r >= m_order) {
374 return nullptr;
375 }
376
377 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), std::move(r));
378#else
379 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
380#endif
381 }
382}
383
384std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_deserialize_uncompressed(
385 std::span<const uint8_t> bytes) const {
386 if(bytes.size() != 1 + 2 * p_bytes() || bytes[0] != 0x04) {
387 return {};
388 }
389
390 if(m_pcurve) {
391 if(auto pt = m_pcurve->deserialize_point_uncompressed(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 try {
399 auto pt = Botan::OS2ECP(bytes, m_curve);
400 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
401 } catch(...) {
402 return {};
403 }
404#else
405 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
406#endif
407 }
408}
409
410std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_deserialize_compressed(std::span<const uint8_t> bytes) const {
411 if(bytes.size() != 1 + p_bytes() || (bytes[0] != 0x02 && bytes[0] != 0x03)) {
412 return {};
413 }
414
415 if(m_pcurve) {
416 if(auto pt = m_pcurve->deserialize_point_compressed(bytes)) {
417 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(*pt));
418 } else {
419 return {};
420 }
421 } else {
422#if defined(BOTAN_HAS_LEGACY_EC_POINT)
423 try {
424 auto pt = Botan::OS2ECP(bytes, m_curve);
425 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
426 } catch(...) {
427 return {};
428 }
429#else
430 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
431#endif
432 }
433}
434
435std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_identity() const {
436 if(m_pcurve) {
437 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_identity());
438 } else {
439#if defined(BOTAN_HAS_LEGACY_EC_POINT)
440 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), EC_Point(m_curve));
441#else
442 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
443#endif
444 }
445}
446
447std::function<void(std::span<uint8_t>)> h2c_expand_message(std::string_view hash_fn,
448 size_t order_bits,
449 std::span<const uint8_t> input,
450 std::span<const uint8_t> domain_sep) {
451 /*
452 * This could be extended to support expand_message_xof or a MHF like Argon2
453 */
454
455 if(hash_fn.starts_with("SHAKE")) {
456 throw Not_Implemented("Hash to curve currently does not support expand_message_xof");
457 }
458
459#if defined(BOTAN_HAS_XMD)
460 // Here we capture the HashFunction by shared_ptr because it will be owned by
461 // the returned std::function
462 const std::shared_ptr<HashFunction> hash = HashFunction::create_or_throw(hash_fn);
463
464 /*
465 * RFC 9380 Section 5.3.1: "The number of bits output by H MUST be b >= 2 * k,
466 * where k is the target security level in bits", as this "ensures k-bit
467 * collision resistance". Checking the hash's collision resistance estimate
468 * covers this, and also rejects hashes with known collision attacks. The
469 * target level is capped at 256 since the RFC 9380 suites for P-521 use k = 256.
470 */
471 const size_t k = std::min<size_t>((order_bits + 1) / 2, 256);
472
473 if(hash->security_level() < k) {
474 throw Invalid_Argument(fmt("Hash {} is too weak for use with a {} bit group", hash->name(), order_bits));
475 }
476
477 return [hash, input, domain_sep](std::span<uint8_t> uniform_bytes) {
478 expand_message_xmd(*hash, uniform_bytes, input, domain_sep);
479 };
480#else
481 BOTAN_UNUSED(order_bits, input, domain_sep);
482 throw Not_Implemented("Hash to curve is not implemented due to XMD being disabled");
483#endif
484}
485
486bool EC_Group_Data::hash_to_curve_supported(std::string_view hash_fn) const {
487#if defined(BOTAN_HAS_XMD)
488 if(!m_pcurve || !m_pcurve->supports_hash_to_curve()) {
489 return false;
490 }
491
492 // Consistent with h2c_expand_message; XOF based expansion is not implemented
493 if(hash_fn.starts_with("SHAKE")) {
494 return false;
495 }
496
497 auto hash = HashFunction::create(hash_fn);
498 if(hash == nullptr) {
499 return false;
500 }
501
502 // The same hash strength requirement enforced by h2c_expand_message
503 const size_t k = std::min<size_t>((order_bits() + 1) / 2, 256);
504 if(hash->security_level() < k) {
505 return false;
506 }
507
508 // The same requirements enforced by expand_message_xmd
509 return hash->hash_block_size() > 0 && hash->output_length() <= hash->hash_block_size();
510#else
511 BOTAN_UNUSED(hash_fn);
512 return false;
513#endif
514}
515
516std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_ro(std::string_view hash_fn,
517 std::span<const uint8_t> input,
518 std::span<const uint8_t> domain_sep) const {
519 if(m_pcurve && m_pcurve->supports_hash_to_curve()) {
520 auto pt = m_pcurve->hash_to_curve_ro(h2c_expand_message(hash_fn, order_bits(), input, domain_sep));
521 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(pt));
522 } else {
523 throw Not_Implemented("Hash to curve is not implemented for this curve");
524 }
525}
526
527std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_nu(std::string_view hash_fn,
528 std::span<const uint8_t> input,
529 std::span<const uint8_t> domain_sep) const {
530 if(m_pcurve && m_pcurve->supports_hash_to_curve()) {
531 auto pt = m_pcurve->hash_to_curve_nu(h2c_expand_message(hash_fn, order_bits(), input, domain_sep));
532 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
533 } else {
534 throw Not_Implemented("Hash to curve is not implemented for this curve");
535 }
536}
537
538std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_g_mul(const EC_Scalar_Data& scalar,
539 RandomNumberGenerator& rng) const {
540 if(m_pcurve) {
541 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
542 auto pt = m_pcurve->point_to_affine(m_pcurve->mul_by_g(k.value(), rng));
543 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
544 } else {
545#if defined(BOTAN_HAS_LEGACY_EC_POINT)
546 const auto& group = scalar.group();
547 const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);
548
549 BOTAN_STATE_CHECK(group->m_base_mult != nullptr);
550 std::vector<BigInt> ws;
551 auto pt = group->m_base_mult->mul(bn.value(), rng, m_order, ws);
552 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
553#else
554 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
555#endif
556 }
557}
558
559std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::mul_px_qy(const EC_AffinePoint_Data& p,
560 const EC_Scalar_Data& x,
561 const EC_AffinePoint_Data& q,
562 const EC_Scalar_Data& y,
563 RandomNumberGenerator& rng) const {
564 if(m_pcurve) {
565 auto pt = m_pcurve->mul_px_qy(EC_AffinePoint_Data_PC::checked_ref(p).value(),
569 rng);
570
571 if(pt) {
572 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(*pt));
573 } else {
574 return nullptr;
575 }
576 } else {
577#if defined(BOTAN_HAS_LEGACY_EC_POINT)
578 std::vector<BigInt> ws;
579 const auto& group = p.group();
580
581 // TODO this could be better!
582 const EC_Point_Var_Point_Precompute p_mul(p.to_legacy_point(), rng, ws);
583 const EC_Point_Var_Point_Precompute q_mul(q.to_legacy_point(), rng, ws);
584
585 const auto order = group->order() * group->cofactor(); // See #3800
586
587 auto px = p_mul.mul(EC_Scalar_Data_BN::checked_ref(x).value(), rng, order, ws);
588 auto qy = q_mul.mul(EC_Scalar_Data_BN::checked_ref(y).value(), rng, order, ws);
589
590 auto px_qy = px + qy;
591
592 if(!px_qy.is_zero()) {
593 px_qy.force_affine();
594 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(px_qy));
595 } else {
596 return nullptr;
597 }
598#else
599 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
600#endif
601 }
602}
603
604std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::affine_add(const EC_AffinePoint_Data& p,
605 const EC_AffinePoint_Data& q) const {
606 if(m_pcurve) {
607 auto pt = m_pcurve->point_add(EC_AffinePoint_Data_PC::checked_ref(p).value(),
609
610 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(pt));
611 } else {
612#if defined(BOTAN_HAS_LEGACY_EC_POINT)
613 auto pt = p.to_legacy_point() + q.to_legacy_point();
614 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
615#else
616 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
617#endif
618 }
619}
620
621std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::affine_neg(const EC_AffinePoint_Data& p) const {
622 if(m_pcurve) {
623 auto pt = m_pcurve->point_negate(EC_AffinePoint_Data_PC::checked_ref(p).value());
624 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt);
625 } else {
626#if defined(BOTAN_HAS_LEGACY_EC_POINT)
627 auto pt = p.to_legacy_point();
628 pt.negate(); // negates in place
629 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
630#else
631 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
632#endif
633 }
634}
635
636std::unique_ptr<EC_Mul2Table_Data> EC_Group_Data::make_mul2_table(const EC_AffinePoint_Data& h) const {
637 if(m_pcurve) {
638 return std::make_unique<EC_Mul2Table_Data_PC>(h);
639 } else {
640#if defined(BOTAN_HAS_LEGACY_EC_POINT)
641 const EC_AffinePoint_Data_BN g(shared_from_this(), this->base_point());
642 return std::make_unique<EC_Mul2Table_Data_BN>(g, h);
643#else
644 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
645#endif
646 }
647}
648
649} // 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 Barrett_Reduction for_public_modulus(const BigInt &m)
Definition barrett.cpp: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:510
BigInt & square(secure_vector< word > &ws)
Definition big_ops2.cpp:191
T serialize(size_t len) const
Definition bigint.h:790
DER_Encoder & encode(bool b)
Definition der_enc.cpp:313
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_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_AffinePoint_Data > point_deserialize_compressed(std::span< const uint8_t > bytes) 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
std::unique_ptr< EC_AffinePoint_Data > point_identity() const
Return the identity element (aka the point at infinity).
std::unique_ptr< EC_AffinePoint_Data > point_deserialize_uncompressed(std::span< const uint8_t > bytes) 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)
bool hash_to_curve_supported(std::string_view hash_fn) const
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::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:308
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:111
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:21
static std::shared_ptr< const PrimeOrderCurve > for_named_curve(std::string_view name)
Definition pcurves.cpp:32
#define BOTAN_HAS_LEGACY_EC_POINT
Definition build.h:238
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::function< void(std::span< uint8_t >)> h2c_expand_message(std::string_view hash_fn, size_t order_bits, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)
void expand_message_xmd(HashFunction &hash, std::span< uint8_t > output, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)
Definition xmd.cpp:17
@ Optimized
Using per curve implementation; fastest available.
Definition ec_group.h:50
@ 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:128
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