Botan 3.7.1
Crypto and TLS for C&
ec_group.cpp
Go to the documentation of this file.
1/*
2* ECC Domain Parameters
3*
4* (C) 2007 Falko Strenzke, FlexSecure GmbH
5* (C) 2008,2018,2024 Jack Lloyd
6* (C) 2018 Tobias Niemann
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/ec_group.h>
12
13#include <botan/ber_dec.h>
14#include <botan/der_enc.h>
15#include <botan/mutex.h>
16#include <botan/numthry.h>
17#include <botan/pem.h>
18#include <botan/reducer.h>
19#include <botan/rng.h>
20#include <botan/internal/ec_inner_data.h>
21#include <botan/internal/fmt.h>
22#include <botan/internal/primality.h>
23#include <vector>
24
25namespace Botan {
26
27class EC_Group_Data_Map final {
28 public:
29 EC_Group_Data_Map() = default;
30
31 size_t clear() {
33 size_t count = m_registered_curves.size();
34 m_registered_curves.clear();
35 return count;
36 }
37
38 std::shared_ptr<EC_Group_Data> lookup(const OID& oid) {
40
41 for(auto i : m_registered_curves) {
42 if(i->oid() == oid) {
43 return i;
44 }
45 }
46
47 // Not found, check hardcoded data
48 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
49
50 if(data) {
51 for(auto curve : m_registered_curves) {
52 if(curve->oid().empty() == true && curve->params_match(*data)) {
53 curve->set_oid(oid);
54 return curve;
55 }
56 }
57
58 m_registered_curves.push_back(data);
59 return data;
60 }
61
62 // Nope, unknown curve
63 return std::shared_ptr<EC_Group_Data>();
64 }
65
66 std::shared_ptr<EC_Group_Data> lookup_or_create(const BigInt& p,
67 const BigInt& a,
68 const BigInt& b,
69 const BigInt& g_x,
70 const BigInt& g_y,
71 const BigInt& order,
72 const BigInt& cofactor,
73 const OID& oid,
74 EC_Group_Source source) {
76
77 for(auto i : m_registered_curves) {
78 /*
79 * The params may be the same but you are trying to register under a
80 * different OID than the one we are using, so using a different
81 * group, since EC_Group's model assumes a single OID per group.
82 */
83 if(!oid.empty() && !i->oid().empty() && i->oid() != oid) {
84 continue;
85 }
86
87 const bool same_oid = !oid.empty() && i->oid() == oid;
88 const bool same_params = i->params_match(p, a, b, g_x, g_y, order, cofactor);
89
90 /*
91 * If the params and OID are the same then we are done, just return
92 * the already registered curve obj.
93 */
94 if(same_params && same_oid) {
95 return i;
96 }
97
98 /*
99 * If same params and the new OID is empty, then that's ok too
100 */
101 if(same_params && oid.empty()) {
102 return i;
103 }
104
105 /*
106 * Check for someone trying to reuse an already in-use OID
107 */
108 if(same_oid && !same_params) {
109 throw Invalid_Argument("Attempting to register a curve using OID " + oid.to_string() +
110 " but a distinct curve is already registered using that OID");
111 }
112
113 /*
114 * If the same curve was previously created without an OID but is now
115 * being registered again using an OID, save that OID.
116 */
117 if(same_params && i->oid().empty() && !oid.empty()) {
118 i->set_oid(oid);
119 return i;
120 }
121 }
122
123 /*
124 Not found in current list, so we need to create a new entry
125
126 If an OID is set, try to look up relative our static tables to detect a duplicate
127 registration under an OID
128 */
129
130 auto new_group = EC_Group_Data::create(p, a, b, g_x, g_y, order, cofactor, oid, source);
131
132 if(oid.has_value()) {
133 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
134 if(data != nullptr && !new_group->params_match(*data)) {
135 throw Invalid_Argument("Attempting to register an EC group under OID of hardcoded group");
136 }
137 } else {
138 // Here try to use the order as a hint to look up the group id, to identify common groups
139 const OID oid_from_store = EC_Group::EC_group_identity_from_order(order);
140 if(oid_from_store.has_value()) {
141 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid_from_store);
142
143 /*
144 If EC_group_identity_from_order returned an OID then looking up that OID
145 must always return a result.
146 */
147 BOTAN_ASSERT_NOMSG(data != nullptr);
148
149 /*
150 It is possible (if unlikely) that someone is registering another group
151 that happens to have an order equal to that of a well known group -
152 so verify all values before assigning the OID.
153 */
154 if(new_group->params_match(*data)) {
155 new_group->set_oid(oid_from_store);
156 }
157 }
158 }
159
160 m_registered_curves.push_back(new_group);
161 return new_group;
162 }
163
164 private:
165 mutex_type m_mutex;
166 std::vector<std::shared_ptr<EC_Group_Data>> m_registered_curves;
167};
168
169//static
170EC_Group_Data_Map& EC_Group::ec_group_data() {
171 /*
172 * This exists purely to ensure the allocator is constructed before g_ec_data,
173 * which ensures that its destructor runs after ~g_ec_data is complete.
174 */
175
176 static Allocator_Initializer g_init_allocator;
177 static EC_Group_Data_Map g_ec_data;
178 return g_ec_data;
179}
180
181//static
183 return ec_group_data().clear();
184}
185
186//static
187std::shared_ptr<EC_Group_Data> EC_Group::load_EC_group_info(const char* p_str,
188 const char* a_str,
189 const char* b_str,
190 const char* g_x_str,
191 const char* g_y_str,
192 const char* order_str,
193 const OID& oid) {
194 const BigInt p(p_str);
195 const BigInt a(a_str);
196 const BigInt b(b_str);
197 const BigInt g_x(g_x_str);
198 const BigInt g_y(g_y_str);
199 const BigInt order(order_str);
200 const BigInt cofactor(1); // implicit
201
202 return EC_Group_Data::create(p, a, b, g_x, g_y, order, cofactor, oid, EC_Group_Source::Builtin);
203}
204
205//static
206std::pair<std::shared_ptr<EC_Group_Data>, bool> EC_Group::BER_decode_EC_group(std::span<const uint8_t> bits,
207 EC_Group_Source source) {
208 BER_Decoder ber(bits);
209
210 auto next_obj_type = ber.peek_next_object().type_tag();
211
212 if(next_obj_type == ASN1_Type::ObjectId) {
213 OID oid;
214 ber.decode(oid);
215
216 auto data = ec_group_data().lookup(oid);
217 if(!data) {
218 throw Decoding_Error(fmt("Unknown namedCurve OID '{}'", oid.to_string()));
219 }
220
221 return std::make_pair(data, false);
222 } else if(next_obj_type == ASN1_Type::Sequence) {
223 BigInt p, a, b, order, cofactor;
224 std::vector<uint8_t> base_pt;
225 std::vector<uint8_t> seed;
226
227 ber.start_sequence()
228 .decode_and_check<size_t>(1, "Unknown ECC param version code")
229 .start_sequence()
230 .decode_and_check(OID("1.2.840.10045.1.1"), "Only prime ECC fields supported")
231 .decode(p)
232 .end_cons()
233 .start_sequence()
234 .decode_octet_string_bigint(a)
235 .decode_octet_string_bigint(b)
236 .decode_optional_string(seed, ASN1_Type::BitString, ASN1_Type::BitString)
237 .end_cons()
238 .decode(base_pt, ASN1_Type::OctetString)
239 .decode(order)
240 .decode(cofactor)
241 .end_cons()
242 .verify_end();
243
244 if(p.bits() < 112 || p.bits() > 521 || p.is_negative()) {
245 throw Decoding_Error("ECC p parameter is invalid size");
246 }
247
249 if(!is_bailie_psw_probable_prime(p, mod_p)) {
250 throw Decoding_Error("ECC p parameter is not a prime");
251 }
252
253 if(a.is_negative() || a >= p) {
254 throw Decoding_Error("Invalid ECC a parameter");
255 }
256
257 if(b <= 0 || b >= p) {
258 throw Decoding_Error("Invalid ECC b parameter");
259 }
260
261 if(order.is_negative() || order.is_zero() || order >= 2 * p) {
262 throw Decoding_Error("Invalid ECC group order");
263 }
264
267 throw Decoding_Error("Invalid ECC order parameter");
268 }
269
270 if(cofactor <= 0 || cofactor >= 16) {
271 throw Decoding_Error("Invalid ECC cofactor parameter");
272 }
273
274 const size_t p_bytes = p.bytes();
275 if(base_pt.size() != 1 + p_bytes && base_pt.size() != 1 + 2 * p_bytes) {
276 throw Decoding_Error("Invalid ECC base point encoding");
277 }
278
279 auto [g_x, g_y] = [&]() {
280 const uint8_t hdr = base_pt[0];
281
282 if(hdr == 0x04 && base_pt.size() == 1 + 2 * p_bytes) {
283 BigInt x = BigInt::decode(&base_pt[1], p_bytes);
284 BigInt y = BigInt::decode(&base_pt[p_bytes + 1], p_bytes);
285
286 if(x < p && y < p) {
287 return std::make_pair(x, y);
288 }
289 } else if((hdr == 0x02 || hdr == 0x03) && base_pt.size() == 1 + p_bytes) {
290 BigInt x = BigInt::decode(&base_pt[1], p_bytes);
291 BigInt y = sqrt_modulo_prime(((x * x + a) * x + b) % p, p);
292
293 if(x < p && y >= 0) {
294 const bool y_mod_2 = (hdr & 0x01) == 1;
295 if(y.get_bit(0) != y_mod_2) {
296 y = p - y;
297 }
298
299 return std::make_pair(x, y);
300 }
301 }
302
303 throw Decoding_Error("Invalid ECC base point encoding");
304 }();
305
306 auto y2 = mod_p.square(g_y);
307 auto x3_ax_b = mod_p.reduce(mod_p.cube(g_x) + mod_p.multiply(a, g_x) + b);
308 if(y2 != x3_ax_b) {
309 throw Decoding_Error("Invalid ECC base point");
310 }
311
312 auto data = ec_group_data().lookup_or_create(p, a, b, g_x, g_y, order, cofactor, OID(), source);
313 return std::make_pair(data, true);
314 } else if(next_obj_type == ASN1_Type::Null) {
315 throw Decoding_Error("Decoding ImplicitCA ECC parameters is not supported");
316 } else {
317 throw Decoding_Error(
318 fmt("Unexpected tag {} while decoding ECC domain params", asn1_tag_to_string(next_obj_type)));
319 }
320}
321
322EC_Group::EC_Group() = default;
323
324EC_Group::~EC_Group() = default;
325
326EC_Group::EC_Group(const EC_Group&) = default;
327
328EC_Group& EC_Group::operator=(const EC_Group&) = default;
329
330// Internal constructor
331EC_Group::EC_Group(std::shared_ptr<EC_Group_Data>&& data) : m_data(std::move(data)) {}
332
333//static
335#if defined(BOTAN_HAS_LEGACY_EC_POINT) || defined(BOTAN_HAS_PCURVES_GENERIC)
336 return true;
337#else
338 return false;
339#endif
340}
341
342//static
344 auto data = ec_group_data().lookup(oid);
345
346 if(!data) {
347 throw Invalid_Argument(fmt("No EC_Group associated with OID '{}'", oid.to_string()));
348 }
349
350 return EC_Group(std::move(data));
351}
352
353//static
355 std::shared_ptr<EC_Group_Data> data;
356
357 if(auto oid = OID::from_name(name)) {
358 data = ec_group_data().lookup(oid.value());
359 }
360
361 if(!data) {
362 throw Invalid_Argument(fmt("Unknown EC_Group '{}'", name));
363 }
364
365 return EC_Group(std::move(data));
366}
367
368EC_Group::EC_Group(std::string_view str) {
369 if(str.empty()) {
370 return; // no initialization / uninitialized
371 }
372
373 try {
374 const OID oid = OID::from_string(str);
375 if(oid.has_value()) {
376 m_data = ec_group_data().lookup(oid);
377 }
378 } catch(...) {}
379
380 if(m_data == nullptr) {
381 if(str.size() > 30 && str.substr(0, 29) == "-----BEGIN EC PARAMETERS-----") {
382 // OK try it as PEM ...
383 const auto ber = PEM_Code::decode_check_label(str, "EC PARAMETERS");
384
385 auto data = BER_decode_EC_group(ber, EC_Group_Source::ExternalSource);
386 this->m_data = data.first;
387 this->m_explicit_encoding = data.second;
388 }
389 }
390
391 if(m_data == nullptr) {
392 throw Invalid_Argument(fmt("Unknown ECC group '{}'", str));
393 }
394}
395
396//static
397EC_Group EC_Group::from_PEM(std::string_view pem) {
398 const auto ber = PEM_Code::decode_check_label(pem, "EC PARAMETERS");
399 return EC_Group(ber);
400}
401
403 const BigInt& a,
404 const BigInt& b,
405 const BigInt& base_x,
406 const BigInt& base_y,
407 const BigInt& order,
408 const BigInt& cofactor,
409 const OID& oid) {
410 m_data =
411 ec_group_data().lookup_or_create(p, a, b, base_x, base_y, order, cofactor, oid, EC_Group_Source::ExternalSource);
412}
413
415 const BigInt& p,
416 const BigInt& a,
417 const BigInt& b,
418 const BigInt& base_x,
419 const BigInt& base_y,
420 const BigInt& order) {
421 BOTAN_ARG_CHECK(oid.has_value(), "An OID is required for creating an EC_Group");
422
423 // TODO(Botan4) remove this and require 192 bits minimum
424#if defined(BOTAN_DISABLE_DEPRECATED_FEATURES)
425 constexpr size_t p_bits_lower_bound = 192;
426#else
427 constexpr size_t p_bits_lower_bound = 128;
428#endif
429
430 BOTAN_ARG_CHECK(p.bits() >= p_bits_lower_bound, "EC_Group p too small");
431 BOTAN_ARG_CHECK(p.bits() <= 521, "EC_Group p too large");
432
433 if(p.bits() == 521) {
434 const auto p521 = BigInt::power_of_2(521) - 1;
435 BOTAN_ARG_CHECK(p == p521, "EC_Group with p of 521 bits must be 2**521-1");
436 } else if(p.bits() == 239) {
437 const auto x962_p239 = []() {
438 BigInt p239;
439 for(size_t i = 0; i != 239; ++i) {
440 if(i < 47 || ((i >= 94) && (i != 143))) {
441 p239.set_bit(i);
442 }
443 }
444 return p239;
445 }();
446
447 BOTAN_ARG_CHECK(p == x962_p239, "EC_Group with p of 239 bits must be the X9.62 prime");
448 } else {
449 BOTAN_ARG_CHECK(p.bits() % 32 == 0, "EC_Group p must be a multiple of 32 bits");
450 }
451
452 BOTAN_ARG_CHECK(p % 4 == 3, "EC_Group p must be congruent to 3 modulo 4");
453
454 BOTAN_ARG_CHECK(a >= 0 && a < p, "EC_Group a is invalid");
455 BOTAN_ARG_CHECK(b > 0 && b < p, "EC_Group b is invalid");
456 BOTAN_ARG_CHECK(base_x >= 0 && base_x < p, "EC_Group base_x is invalid");
457 BOTAN_ARG_CHECK(base_y >= 0 && base_y < p, "EC_Group base_y is invalid");
458 BOTAN_ARG_CHECK(p.bits() == order.bits(), "EC_Group p and order must have the same number of bits");
459
461 BOTAN_ARG_CHECK(is_bailie_psw_probable_prime(p, mod_p), "EC_Group p is not prime");
462
464 BOTAN_ARG_CHECK(is_bailie_psw_probable_prime(order, mod_order), "EC_Group order is not prime");
465
466 // This catches someone "ignoring" a cofactor and just trying to
467 // provide the subgroup order
468 BOTAN_ARG_CHECK((p - order).abs().bits() <= (p.bits() / 2) + 1, "Hasse bound invalid");
469
470 // Check that 4*a^3 + 27*b^2 != 0
471 const auto discriminant = mod_p.reduce(mod_p.multiply(4, mod_p.cube(a)) + mod_p.multiply(27, mod_p.square(b)));
472 BOTAN_ARG_CHECK(discriminant != 0, "EC_Group discriminant is invalid");
473
474 // Check that the generator (base_x,base_y) is on the curve; y^2 = x^3 + a*x + b
475 auto y2 = mod_p.square(base_y);
476 auto x3_ax_b = mod_p.reduce(mod_p.cube(base_x) + mod_p.multiply(a, base_x) + b);
477 BOTAN_ARG_CHECK(y2 == x3_ax_b, "EC_Group generator is not on the curve");
478
479 BigInt cofactor(1);
480
481 m_data =
482 ec_group_data().lookup_or_create(p, a, b, base_x, base_y, order, cofactor, oid, EC_Group_Source::ExternalSource);
483}
484
485EC_Group::EC_Group(std::span<const uint8_t> ber) {
486 auto data = BER_decode_EC_group(ber, EC_Group_Source::ExternalSource);
487 m_data = data.first;
488 m_explicit_encoding = data.second;
489}
490
491const EC_Group_Data& EC_Group::data() const {
492 if(m_data == nullptr) {
493 throw Invalid_State("EC_Group uninitialized");
494 }
495 return *m_data;
496}
497
498size_t EC_Group::get_p_bits() const {
499 return data().p_bits();
500}
501
502size_t EC_Group::get_p_bytes() const {
503 return data().p_bytes();
504}
505
507 return data().order_bits();
508}
509
511 return data().order_bytes();
512}
513
514const BigInt& EC_Group::get_p() const {
515 return data().p();
516}
517
518const BigInt& EC_Group::get_a() const {
519 return data().a();
520}
521
522const BigInt& EC_Group::get_b() const {
523 return data().b();
524}
525
526#if defined(BOTAN_HAS_LEGACY_EC_POINT)
527const EC_Point& EC_Group::get_base_point() const {
528 return data().base_point();
529}
530
531const EC_Point& EC_Group::generator() const {
532 return data().base_point();
533}
534
535bool EC_Group::verify_public_element(const EC_Point& point) const {
536 //check that public point is not at infinity
537 if(point.is_zero()) {
538 return false;
539 }
540
541 //check that public point is on the curve
542 if(point.on_the_curve() == false) {
543 return false;
544 }
545
546 //check that public point has order q
547 if((point * get_order()).is_zero() == false) {
548 return false;
549 }
550
551 if(has_cofactor()) {
552 if((point * get_cofactor()).is_zero()) {
553 return false;
554 }
555 }
556
557 return true;
558}
559
560#endif
561
563 return data().order();
564}
565
566const BigInt& EC_Group::get_g_x() const {
567 return data().g_x();
568}
569
570const BigInt& EC_Group::get_g_y() const {
571 return data().g_y();
572}
573
575 return data().cofactor();
576}
577
579 return data().has_cofactor();
580}
581
583 return data().oid();
584}
585
587 return data().source();
588}
589
591 return data().engine();
592}
593
594std::vector<uint8_t> EC_Group::DER_encode() const {
595 const auto& der_named_curve = data().der_named_curve();
596 // TODO(Botan4) this can be removed because an OID will always be defined
597 if(der_named_curve.empty()) {
598 throw Encoding_Error("Cannot encode EC_Group as OID because OID not set");
599 }
600
601 return der_named_curve;
602}
603
604std::vector<uint8_t> EC_Group::DER_encode(EC_Group_Encoding form) const {
605 if(form == EC_Group_Encoding::Explicit) {
606 std::vector<uint8_t> output;
607 DER_Encoder der(output);
608 const size_t ecpVers1 = 1;
609 const OID curve_type("1.2.840.10045.1.1"); // prime field
610
611 const size_t p_bytes = get_p_bytes();
612
613 const auto generator = EC_AffinePoint::generator(*this).serialize_uncompressed();
614
615 der.start_sequence()
616 .encode(ecpVers1)
618 .encode(curve_type)
619 .encode(get_p())
620 .end_cons()
622 .encode(get_a().serialize(p_bytes), ASN1_Type::OctetString)
623 .encode(get_b().serialize(p_bytes), ASN1_Type::OctetString)
624 .end_cons()
625 .encode(generator, ASN1_Type::OctetString)
626 .encode(get_order())
628 .end_cons();
629 return output;
630 } else if(form == EC_Group_Encoding::NamedCurve) {
631 return this->DER_encode();
632 } else if(form == EC_Group_Encoding::ImplicitCA) {
633 return {0x00, 0x05};
634 } else {
635 throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
636 }
637}
638
639std::string EC_Group::PEM_encode() const {
640 const std::vector<uint8_t> der = DER_encode(EC_Group_Encoding::Explicit);
641 return PEM_Code::encode(der, "EC PARAMETERS");
642}
643
644bool EC_Group::operator==(const EC_Group& other) const {
645 if(m_data == other.m_data) {
646 return true; // same shared rep
647 }
648
649 return (get_p() == other.get_p() && get_a() == other.get_a() && get_b() == other.get_b() &&
650 get_g_x() == other.get_g_x() && get_g_y() == other.get_g_y() && get_order() == other.get_order() &&
651 get_cofactor() == other.get_cofactor());
652}
653
654bool EC_Group::verify_group(RandomNumberGenerator& rng, bool strong) const {
655 const bool is_builtin = source() == EC_Group_Source::Builtin;
656
657 if(is_builtin && !strong) {
658 return true;
659 }
660
661 // TODO(Botan4) this can probably all be removed once the deprecated EC_Group
662 // constructor is removed, since at that point it no longer becomes possible
663 // to create an EC_Group which fails to satisfy these conditions
664
665 const BigInt& p = get_p();
666 const BigInt& a = get_a();
667 const BigInt& b = get_b();
668 const BigInt& order = get_order();
669
670 if(p <= 3 || order <= 0) {
671 return false;
672 }
673 if(a < 0 || a >= p) {
674 return false;
675 }
676 if(b <= 0 || b >= p) {
677 return false;
678 }
679
680 const size_t test_prob = 128;
681 const bool is_randomly_generated = is_builtin;
682
683 //check if field modulus is prime
684 if(!is_prime(p, rng, test_prob, is_randomly_generated)) {
685 return false;
686 }
687
688 //check if order is prime
689 if(!is_prime(order, rng, test_prob, is_randomly_generated)) {
690 return false;
691 }
692
693 //compute the discriminant: 4*a^3 + 27*b^2 which must be nonzero
695
696 const BigInt discriminant = mod_p.reduce(mod_p.multiply(4, mod_p.cube(a)) + mod_p.multiply(27, mod_p.square(b)));
697
698 if(discriminant == 0) {
699 return false;
700 }
701
702 //check for valid cofactor
703 if(get_cofactor() < 1) {
704 return false;
705 }
706
707#if defined(BOTAN_HAS_LEGACY_EC_POINT)
708 const EC_Point& base_point = get_base_point();
709 //check if the base point is on the curve
710 if(!base_point.on_the_curve()) {
711 return false;
712 }
713 if((base_point * get_cofactor()).is_zero()) {
714 return false;
715 }
716 //check if order of the base point is correct
717 if(!(base_point * order).is_zero()) {
718 return false;
719 }
720#endif
721
722 // check the Hasse bound (roughly)
723 if((p - get_cofactor() * order).abs().bits() > (p.bits() / 2) + 1) {
724 return false;
725 }
726
727 return true;
728}
729
730EC_Group::Mul2Table::Mul2Table(const EC_AffinePoint& h) : m_tbl(h._group()->make_mul2_table(h._inner())) {}
731
733
734std::optional<EC_AffinePoint> EC_Group::Mul2Table::mul2_vartime(const EC_Scalar& x, const EC_Scalar& y) const {
735 auto pt = m_tbl->mul2_vartime(x._inner(), y._inner());
736 if(pt) {
737 return EC_AffinePoint::_from_inner(std::move(pt));
738 } else {
739 return {};
740 }
741}
742
744 const EC_Scalar& x,
745 const EC_Scalar& y) const {
746 return m_tbl->mul2_vartime_x_mod_order_eq(v._inner(), x._inner(), y._inner());
747}
748
750 const EC_Scalar& c,
751 const EC_Scalar& x,
752 const EC_Scalar& y) const {
753 return this->mul2_vartime_x_mod_order_eq(v, c * x, c * y);
754}
755
756} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
static BigInt decode(const uint8_t buf[], size_t length)
Definition bigint.h:867
void set_bit(size_t n)
Definition bigint.h:464
size_t bits() const
Definition bigint.cpp:295
static BigInt power_of_2(size_t n)
Definition bigint.h:830
DER_Encoder & start_sequence()
Definition der_enc.h:64
DER_Encoder & end_cons()
Definition der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
T serialize_uncompressed() const
Definition ec_apoint.h:194
static EC_AffinePoint _from_inner(std::unique_ptr< EC_AffinePoint_Data > inner)
static EC_AffinePoint generator(const EC_Group &group)
Return the standard group generator.
Definition ec_apoint.cpp:83
std::optional< EC_AffinePoint > mul2_vartime(const EC_Scalar &x, const EC_Scalar &y) const
Definition ec_group.cpp:734
Mul2Table(const EC_AffinePoint &h)
Definition ec_group.cpp:730
bool mul2_vartime_x_mod_order_eq(const EC_Scalar &v, const EC_Scalar &x, const EC_Scalar &y) const
Definition ec_group.cpp:743
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)
static EC_Group from_name(std::string_view name)
Definition ec_group.cpp:354
static EC_Group from_PEM(std::string_view pem)
Definition ec_group.cpp:397
const BigInt & get_b() const
Definition ec_group.cpp:522
const BigInt & get_a() const
Definition ec_group.cpp:518
const BigInt & get_g_y() const
Definition ec_group.cpp:570
const BigInt & get_cofactor() const
Definition ec_group.cpp:574
BigInt mod_order(const BigInt &x) const
Definition ec_group.h:646
bool operator==(const EC_Group &other) const
Definition ec_group.cpp:644
EC_Group_Engine engine() const
Definition ec_group.cpp:590
EC_Group_Source source() const
Definition ec_group.cpp:586
const BigInt & get_p() const
Definition ec_group.cpp:514
bool verify_group(RandomNumberGenerator &rng, bool strong=false) const
Definition ec_group.cpp:654
const BigInt & get_order() const
Definition ec_group.cpp:562
size_t get_p_bits() const
Definition ec_group.cpp:498
static EC_Group from_OID(const OID &oid)
Definition ec_group.cpp:343
static std::shared_ptr< EC_Group_Data > EC_group_info(const OID &oid)
Definition ec_named.cpp:15
std::vector< uint8_t > DER_encode() const
Definition ec_group.cpp:594
std::string PEM_encode() const
Definition ec_group.cpp:639
const BigInt & get_g_x() const
Definition ec_group.cpp:566
const OID & get_curve_oid() const
Definition ec_group.cpp:582
static bool supports_application_specific_group()
Definition ec_group.cpp:334
bool has_cofactor() const
Definition ec_group.cpp:578
static size_t clear_registered_curve_data()
Definition ec_group.cpp:182
EC_Group & operator=(const EC_Group &)
size_t get_p_bytes() const
Definition ec_group.cpp:502
static OID EC_group_identity_from_order(const BigInt &order)
Definition ec_named.cpp:356
size_t get_order_bits() const
Definition ec_group.cpp:506
size_t get_order_bytes() const
Definition ec_group.cpp:510
bool on_the_curve() const
Definition ec_point.cpp:636
const EC_Scalar_Data & _inner() const
Definition ec_scalar.h:222
static Modular_Reducer for_public_modulus(const BigInt &m)
Definition reducer.cpp:43
static std::optional< OID > from_name(std::string_view name)
Definition asn1_oid.cpp:72
bool has_value() const
Definition asn1_obj.h:272
std::string to_string() const
Definition asn1_oid.cpp:125
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
std::string name
int(* final)(unsigned char *, CTX *)
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Definition pem.cpp:39
secure_vector< uint8_t > decode_check_label(DataSource &source, std::string_view label_want)
Definition pem.cpp:49
EC_Group_Source
Definition ec_group.h:56
noop_mutex mutex_type
Definition mutex.h:37
std::string asn1_tag_to_string(ASN1_Type type)
Definition asn1_obj.cpp:93
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
EC_Group_Engine
Definition ec_group.h:66
BigInt abs(const BigInt &n)
Definition numthry.h:24
secure_vector< T > lock(const std::vector< T > &in)
Definition secmem.h:70
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition numthry.cpp:355
bool is_bailie_psw_probable_prime(const BigInt &n, const Modular_Reducer &mod_n)
Definition primality.cpp:90
const SIMD_8x32 & b
lock_guard< T > lock_guard_type
Definition mutex.h:55
BigInt sqrt_modulo_prime(const BigInt &a, const BigInt &p)
Definition numthry.cpp:26
EC_Group_Encoding
Definition ec_group.h:36