Botan 3.0.0-alpha0
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 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#include <botan/internal/point_mul.h>
13#include <botan/internal/primality.h>
14#include <botan/ber_dec.h>
15#include <botan/der_enc.h>
16#include <botan/pem.h>
17#include <botan/reducer.h>
18#include <botan/mutex.h>
19#include <botan/rng.h>
20#include <vector>
21
22#if defined(BOTAN_HAS_EC_HASH_TO_CURVE)
23 #include <botan/internal/ec_h2c.h>
24#endif
25
26namespace Botan {
27
28class EC_Group_Data final
29 {
30 public:
31
32 EC_Group_Data(const BigInt& p,
33 const BigInt& a,
34 const BigInt& b,
35 const BigInt& g_x,
36 const BigInt& g_y,
37 const BigInt& order,
38 const BigInt& cofactor,
39 const OID& oid,
40 EC_Group_Source source) :
41 m_curve(p, a, b),
42 m_base_point(m_curve, g_x, g_y),
43 m_g_x(g_x),
44 m_g_y(g_y),
45 m_order(order),
46 m_cofactor(cofactor),
47 m_mod_order(order),
48 m_base_mult(m_base_point, m_mod_order),
49 m_oid(oid),
50 m_p_bits(p.bits()),
51 m_order_bits(order.bits()),
52 m_a_is_minus_3(a == p - 3),
53 m_a_is_zero(a.is_zero()),
54 m_source(source)
55 {
56 }
57
58 bool params_match(const BigInt& p, const BigInt& a, const BigInt& b,
59 const BigInt& g_x, const BigInt& g_y,
60 const BigInt& order, const BigInt& cofactor) const
61 {
62 return (this->p() == p &&
63 this->a() == a &&
64 this->b() == b &&
65 this->order() == order &&
66 this->cofactor() == cofactor &&
67 this->g_x() == g_x &&
68 this->g_y() == g_y);
69 }
70
71 bool params_match(const EC_Group_Data& other) const
72 {
73 return params_match(other.p(), other.a(), other.b(),
74 other.g_x(), other.g_y(),
75 other.order(), other.cofactor());
76 }
77
78 void set_oid(const OID& oid)
79 {
80 BOTAN_STATE_CHECK(m_oid.empty());
81 m_oid = oid;
82 }
83
84 const OID& oid() const { return m_oid; }
85 const BigInt& p() const { return m_curve.get_p(); }
86 const BigInt& a() const { return m_curve.get_a(); }
87 const BigInt& b() const { return m_curve.get_b(); }
88 const BigInt& order() const { return m_order; }
89 const BigInt& cofactor() const { return m_cofactor; }
90 const BigInt& g_x() const { return m_g_x; }
91 const BigInt& g_y() const { return m_g_y; }
92
93 size_t p_bits() const { return m_p_bits; }
94 size_t p_bytes() const { return (m_p_bits + 7) / 8; }
95
96 size_t order_bits() const { return m_order_bits; }
97 size_t order_bytes() const { return (m_order_bits + 7) / 8; }
98
99 const CurveGFp& curve() const { return m_curve; }
100 const PointGFp& base_point() const { return m_base_point; }
101
102 bool a_is_minus_3() const { return m_a_is_minus_3; }
103 bool a_is_zero() const { return m_a_is_zero; }
104
105 BigInt mod_order(const BigInt& x) const { return m_mod_order.reduce(x); }
106
107 BigInt square_mod_order(const BigInt& x) const
108 {
109 return m_mod_order.square(x);
110 }
111
112 BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const
113 {
114 return m_mod_order.multiply(x, y);
115 }
116
117 BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const
118 {
119 return m_mod_order.multiply(m_mod_order.multiply(x, y), z);
120 }
121
122 BigInt inverse_mod_order(const BigInt& x) const
123 {
124 return inverse_mod(x, m_order);
125 }
126
127 PointGFp blinded_base_point_multiply(const BigInt& k,
128 RandomNumberGenerator& rng,
129 std::vector<BigInt>& ws) const
130 {
131 return m_base_mult.mul(k, rng, m_order, ws);
132 }
133
134 EC_Group_Source source() const { return m_source; }
135
136 private:
137 CurveGFp m_curve;
138 PointGFp m_base_point;
139
140 BigInt m_g_x;
141 BigInt m_g_y;
142 BigInt m_order;
143 BigInt m_cofactor;
144 Modular_Reducer m_mod_order;
145 PointGFp_Base_Point_Precompute m_base_mult;
146 OID m_oid;
147 size_t m_p_bits;
148 size_t m_order_bits;
149 bool m_a_is_minus_3;
150 bool m_a_is_zero;
151 EC_Group_Source m_source;
152 };
153
154class EC_Group_Data_Map final
155 {
156 public:
157 EC_Group_Data_Map() {}
158
159 size_t clear()
160 {
161 lock_guard_type<mutex_type> lock(m_mutex);
162 size_t count = m_registered_curves.size();
163 m_registered_curves.clear();
164 return count;
165 }
166
167 std::shared_ptr<EC_Group_Data> lookup(const OID& oid)
168 {
169 lock_guard_type<mutex_type> lock(m_mutex);
170
171 for(auto i : m_registered_curves)
172 {
173 if(i->oid() == oid)
174 return i;
175 }
176
177 // Not found, check hardcoded data
178 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
179
180 if(data)
181 {
182 for(auto curve : m_registered_curves)
183 {
184 if(curve->oid().empty() == true && curve->params_match(*data))
185 {
186 curve->set_oid(oid);
187 return curve;
188 }
189 }
190
191 m_registered_curves.push_back(data);
192 return data;
193 }
194
195 // Nope, unknown curve
196 return std::shared_ptr<EC_Group_Data>();
197 }
198
199 std::shared_ptr<EC_Group_Data> lookup_or_create(const BigInt& p,
200 const BigInt& a,
201 const BigInt& b,
202 const BigInt& g_x,
203 const BigInt& g_y,
204 const BigInt& order,
205 const BigInt& cofactor,
206 const OID& oid,
207 EC_Group_Source source)
208 {
209 lock_guard_type<mutex_type> lock(m_mutex);
210
211 for(auto i : m_registered_curves)
212 {
213 /*
214 * The params may be the same but you are trying to register under a
215 * different OID than the one we are using, so using a different
216 * group, since EC_Group's model assumes a single OID per group.
217 */
218 if(!oid.empty() && !i->oid().empty() && i->oid() != oid)
219 {
220 continue;
221 }
222
223 const bool same_oid = !oid.empty() && i->oid() == oid;
224 const bool same_params = i->params_match(p, a, b, g_x, g_y, order, cofactor);
225
226 /*
227 * If the params and OID are the same then we are done, just return
228 * the already registered curve obj.
229 */
230 if(same_params && same_oid)
231 {
232 return i;
233 }
234
235 /*
236 * If same params and the new OID is empty, then that's ok too
237 */
238 if(same_params && oid.empty())
239 {
240 return i;
241 }
242
243 /*
244 * Check for someone trying to reuse an already in-use OID
245 */
246 if(same_oid && !same_params)
247 {
248 throw Invalid_Argument("Attempting to register a curve using OID " + oid.to_string() +
249 " but a distinct curve is already registered using that OID");
250 }
251
252 /*
253 * If the same curve was previously created without an OID but is now
254 * being registered again using an OID, save that OID.
255 */
256 if(same_params && i->oid().empty() && !oid.empty())
257 {
258 i->set_oid(oid);
259 return i;
260 }
261 }
262
263 /*
264 Not found in current list, so we need to create a new entry
265
266 If an OID is set, try to look up relative our static tables to detect a duplicate
267 registration under an OID
268 */
269
270 std::shared_ptr<EC_Group_Data> new_group =
271 std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, source);
272
273 if(oid.has_value())
274 {
275 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
276 if(data != nullptr && !new_group->params_match(*data))
277 throw Invalid_Argument("Attempting to register an EC group under OID of hardcoded group");
278 }
279 else
280 {
281 // Here try to use the order as a hint to look up the group id, to identify common groups
282 const OID oid_from_store = EC_Group::EC_group_identity_from_order(order);
283 if(oid_from_store.has_value())
284 {
285 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid_from_store);
286
287 /*
288 If EC_group_identity_from_order returned an OID then looking up that OID
289 must always return a result.
290 */
291 BOTAN_ASSERT_NOMSG(data != nullptr);
292
293 /*
294 It is possible (if unlikely) that someone is registering another group
295 that happens to have an order equal to that of a well known group -
296 so verify all values before assigning the OID.
297 */
298 if(new_group->params_match(*data))
299 {
300 new_group->set_oid(oid_from_store);
301 }
302 }
303 }
304
305 m_registered_curves.push_back(new_group);
306 return new_group;
307 }
308
309 private:
310 mutex_type m_mutex;
311 std::vector<std::shared_ptr<EC_Group_Data>> m_registered_curves;
312 };
313
314//static
315EC_Group_Data_Map& EC_Group::ec_group_data()
316 {
317 /*
318 * This exists purely to ensure the allocator is constructed before g_ec_data,
319 * which ensures that its destructor runs after ~g_ec_data is complete.
320 */
321
322 static Allocator_Initializer g_init_allocator;
323 static EC_Group_Data_Map g_ec_data;
324 return g_ec_data;
325 }
326
327//static
329 {
330 return ec_group_data().clear();
331 }
332
333//static
334std::shared_ptr<EC_Group_Data>
335EC_Group::load_EC_group_info(const char* p_str,
336 const char* a_str,
337 const char* b_str,
338 const char* g_x_str,
339 const char* g_y_str,
340 const char* order_str,
341 const OID& oid)
342 {
343 const BigInt p(p_str);
344 const BigInt a(a_str);
345 const BigInt b(b_str);
346 const BigInt g_x(g_x_str);
347 const BigInt g_y(g_y_str);
348 const BigInt order(order_str);
349 const BigInt cofactor(1); // implicit
350
351 return std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, EC_Group_Source::Builtin);
352 }
353
354//static
355std::shared_ptr<EC_Group_Data> EC_Group::BER_decode_EC_group(const uint8_t bits[], size_t len,
356 EC_Group_Source source)
357 {
358 BER_Decoder ber(bits, len);
359 BER_Object obj = ber.get_next_object();
360
361 if(obj.type() == ASN1_Type::Null)
362 {
363 throw Decoding_Error("Cannot handle ImplicitCA ECC parameters");
364 }
365 else if(obj.type() == ASN1_Type::ObjectId)
366 {
367 OID dom_par_oid;
368 BER_Decoder(bits, len).decode(dom_par_oid);
369 return ec_group_data().lookup(dom_par_oid);
370 }
371 else if(obj.type() == ASN1_Type::Sequence)
372 {
373 BigInt p, a, b, order, cofactor;
374 std::vector<uint8_t> base_pt;
375 std::vector<uint8_t> seed;
376
377 BER_Decoder(bits, len)
378 .start_sequence()
379 .decode_and_check<size_t>(1, "Unknown ECC param version code")
380 .start_sequence()
381 .decode_and_check(OID("1.2.840.10045.1.1"),
382 "Only prime ECC fields supported")
383 .decode(p)
384 .end_cons()
385 .start_sequence()
386 .decode_octet_string_bigint(a)
387 .decode_octet_string_bigint(b)
388 .decode_optional_string(seed, ASN1_Type::BitString, ASN1_Type::BitString)
389 .end_cons()
390 .decode(base_pt, ASN1_Type::OctetString)
391 .decode(order)
392 .decode(cofactor)
393 .end_cons()
394 .verify_end();
395
396 if(p.bits() < 64 || p.is_negative() || !is_bailie_psw_probable_prime(p))
397 throw Decoding_Error("Invalid ECC p parameter");
398
399 if(a.is_negative() || a >= p)
400 throw Decoding_Error("Invalid ECC a parameter");
401
402 if(b <= 0 || b >= p)
403 throw Decoding_Error("Invalid ECC b parameter");
404
405 if(order <= 0 || !is_bailie_psw_probable_prime(order))
406 throw Decoding_Error("Invalid ECC order parameter");
407
408 if(cofactor <= 0 || cofactor >= 16)
409 throw Decoding_Error("Invalid ECC cofactor parameter");
410
411 std::pair<BigInt, BigInt> base_xy = Botan::OS2ECP(base_pt.data(), base_pt.size(), p, a, b);
412
413 return ec_group_data().lookup_or_create(p, a, b, base_xy.first, base_xy.second,
414 order, cofactor, OID(), source);
415 }
416 else
417 {
418 throw Decoding_Error("Unexpected tag while decoding ECC domain params");
419 }
420 }
421
423 {
424 }
425
427 {
428 // shared_ptr possibly freed here
429 }
430
431EC_Group::EC_Group(const OID& domain_oid)
432 {
433 this->m_data = ec_group_data().lookup(domain_oid);
434 if(!this->m_data)
435 throw Invalid_Argument("Unknown EC_Group " + domain_oid.to_string());
436 }
437
438EC_Group::EC_Group(const std::string& str)
439 {
440 if(str.empty())
441 return; // no initialization / uninitialized
442
443 try
444 {
445 const OID oid = OID::from_string(str);
446 if(oid.has_value())
447 m_data = ec_group_data().lookup(oid);
448 }
449 catch(...)
450 {
451 }
452
453 if(m_data == nullptr)
454 {
455 if(str.size() > 30 && str.substr(0, 29) == "-----BEGIN EC PARAMETERS-----")
456 {
457 // OK try it as PEM ...
458 secure_vector<uint8_t> ber = PEM_Code::decode_check_label(str, "EC PARAMETERS");
459 this->m_data = BER_decode_EC_group(ber.data(), ber.size(), EC_Group_Source::ExternalSource);
460 }
461 }
462
463 if(m_data == nullptr)
464 throw Invalid_Argument("Unknown ECC group '" + str + "'");
465 }
466
467//static
469 {
470 const auto ber = PEM_Code::decode_check_label(pem, "EC PARAMETERS");
471 return EC_Group(ber.data(), ber.size());
472 }
473
475 const BigInt& a,
476 const BigInt& b,
477 const BigInt& base_x,
478 const BigInt& base_y,
479 const BigInt& order,
480 const BigInt& cofactor,
481 const OID& oid)
482 {
483 m_data = ec_group_data().lookup_or_create(p, a, b, base_x, base_y, order, cofactor, oid,
485 }
486
487EC_Group::EC_Group(const uint8_t ber[], size_t ber_len)
488 {
489 m_data = BER_decode_EC_group(ber, ber_len, EC_Group_Source::ExternalSource);
490 }
491
492const EC_Group_Data& EC_Group::data() const
493 {
494 if(m_data == nullptr)
495 throw Invalid_State("EC_Group uninitialized");
496 return *m_data;
497 }
498
500 {
501 return data().a_is_minus_3();
502 }
503
505 {
506 return data().a_is_zero();
507 }
508
510 {
511 return data().p_bits();
512 }
513
515 {
516 return data().p_bytes();
517 }
518
520 {
521 return data().order_bits();
522 }
523
525 {
526 return data().order_bytes();
527 }
528
530 {
531 return data().p();
532 }
533
535 {
536 return data().a();
537 }
538
540 {
541 return data().b();
542 }
543
545 {
546 return data().base_point();
547 }
548
550 {
551 return data().order();
552 }
553
555 {
556 return data().g_x();
557 }
558
560 {
561 return data().g_y();
562 }
563
565 {
566 return data().cofactor();
567 }
568
570 {
571 return data().mod_order(k);
572 }
573
575 {
576 return data().square_mod_order(x);
577 }
578
580 {
581 return data().multiply_mod_order(x, y);
582 }
583
584BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const
585 {
586 return data().multiply_mod_order(x, y, z);
587 }
588
590 {
591 return data().inverse_mod_order(x);
592 }
593
595 {
596 return data().oid();
597 }
598
600 {
601 return data().source();
602 }
603
605 {
606 // Hybrid and standard format are (x,y), compressed is y, +1 format byte
607 if(format == PointGFp::COMPRESSED)
608 return (1 + get_p_bytes());
609 else
610 return (1 + 2*get_p_bytes());
611 }
612
613PointGFp EC_Group::OS2ECP(const uint8_t bits[], size_t len) const
614 {
615 return Botan::OS2ECP(bits, len, data().curve());
616 }
617
618PointGFp EC_Group::point(const BigInt& x, const BigInt& y) const
619 {
620 #if 0
621 BigInt l = (x*x*x + x*get_a() + get_b()) % get_p();
622 BigInt r = (y*y) % get_p();
623
624 if(l != r)
625 {
626 printf("invalid point in EC_Group::point\n");
627 }
628#endif
629 // TODO: randomize the representation?
630 return PointGFp(data().curve(), x, y);
631 }
632
633PointGFp EC_Group::point_multiply(const BigInt& x, const PointGFp& pt, const BigInt& y) const
634 {
636 return xy_mul.multi_exp(x, y);
637 }
638
641 std::vector<BigInt>& ws) const
642 {
643 return data().blinded_base_point_multiply(k, rng, ws);
644 }
645
648 std::vector<BigInt>& ws) const
649 {
650 const PointGFp pt = data().blinded_base_point_multiply(k, rng, ws);
651
652 if(pt.is_zero())
653 return BigInt::zero();
654 return pt.get_affine_x();
655 }
656
658 {
660 }
661
663 const BigInt& k,
665 std::vector<BigInt>& ws) const
666 {
668 return mul.mul(k, rng, get_order(), ws);
669 }
670
672 {
673 return PointGFp(data().curve());
674 }
675
676PointGFp EC_Group::hash_to_curve(const std::string& hash_fn,
677 const uint8_t input[],
678 size_t input_len,
679 const std::string& domain,
680 bool random_oracle) const
681 {
682 return this->hash_to_curve(hash_fn,
683 input,
684 input_len,
685 reinterpret_cast<const uint8_t*>(domain.c_str()),
686 domain.size(),
687 random_oracle);
688 }
689
690PointGFp EC_Group::hash_to_curve(const std::string& hash_fn,
691 const uint8_t input[],
692 size_t input_len,
693 const uint8_t domain_sep[],
694 size_t domain_sep_len,
695 bool random_oracle) const
696 {
697#if defined(BOTAN_HAS_EC_HASH_TO_CURVE)
698
699 // Only have SSWU currently
700 if(get_a().is_zero() || get_b().is_zero() || get_p() % 4 == 1)
701 {
702 throw Not_Implemented("EC_Group::hash_to_curve not available for this curve type");
703 }
704
705 return hash_to_curve_sswu(*this, hash_fn,
706 input, input_len,
707 domain_sep, domain_sep_len,
708 random_oracle);
709
710#else
711 BOTAN_UNUSED(hash_fn, random_oracle, input, input_len, domain_sep, domain_sep_len);
712 throw Not_Implemented("EC_Group::hash_to_curve functionality not available in this configuration");
713#endif
714 }
715
716std::vector<uint8_t>
718 {
719 std::vector<uint8_t> output;
720
721 DER_Encoder der(output);
722
724 {
725 const size_t ecpVers1 = 1;
726 const OID curve_type("1.2.840.10045.1.1"); // prime field
727
728 const size_t p_bytes = get_p_bytes();
729
730 der.start_sequence()
731 .encode(ecpVers1)
733 .encode(curve_type)
734 .encode(get_p())
735 .end_cons()
737 .encode(BigInt::encode_1363(get_a(), p_bytes),
739 .encode(BigInt::encode_1363(get_b(), p_bytes),
741 .end_cons()
743 .encode(get_order())
745 .end_cons();
746 }
747 else if(form == EC_Group_Encoding::NamedCurve)
748 {
749 const OID oid = get_curve_oid();
750 if(oid.empty())
751 {
752 throw Encoding_Error("Cannot encode EC_Group as OID because OID not set");
753 }
754 der.encode(oid);
755 }
756 else if(form == EC_Group_Encoding::ImplicitCA)
757 {
758 der.encode_null();
759 }
760 else
761 {
762 throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
763 }
764
765 return output;
766 }
767
768std::string EC_Group::PEM_encode() const
769 {
770 const std::vector<uint8_t> der = DER_encode(EC_Group_Encoding::Explicit);
771 return PEM_Code::encode(der, "EC PARAMETERS");
772 }
773
774bool EC_Group::operator==(const EC_Group& other) const
775 {
776 if(m_data == other.m_data)
777 return true; // same shared rep
778
779 return (get_p() == other.get_p() &&
780 get_a() == other.get_a() &&
781 get_b() == other.get_b() &&
782 get_g_x() == other.get_g_x() &&
783 get_g_y() == other.get_g_y() &&
784 get_order() == other.get_order() &&
785 get_cofactor() == other.get_cofactor());
786 }
787
789 {
790 //check that public point is not at infinity
791 if(point.is_zero())
792 return false;
793
794 //check that public point is on the curve
795 if(point.on_the_curve() == false)
796 return false;
797
798 //check that public point has order q
799 if((point * get_order()).is_zero() == false)
800 return false;
801
802 if(get_cofactor() > 1)
803 {
804 if((point * get_cofactor()).is_zero())
805 return false;
806 }
807
808 return true;
809 }
810
812 bool strong) const
813 {
814 const bool is_builtin = source() == EC_Group_Source::Builtin;
815
816 if(is_builtin && !strong)
817 return true;
818
819 const BigInt& p = get_p();
820 const BigInt& a = get_a();
821 const BigInt& b = get_b();
822 const BigInt& order = get_order();
823 const PointGFp& base_point = get_base_point();
824
825 if(p <= 3 || order <= 0)
826 return false;
827 if(a < 0 || a >= p)
828 return false;
829 if(b <= 0 || b >= p)
830 return false;
831
832 const size_t test_prob = 128;
833 const bool is_randomly_generated = is_builtin;
834
835 //check if field modulus is prime
836 if(!is_prime(p, rng, test_prob, is_randomly_generated))
837 {
838 return false;
839 }
840
841 //check if order is prime
842 if(!is_prime(order, rng, test_prob, is_randomly_generated))
843 {
844 return false;
845 }
846
847 //compute the discriminant: 4*a^3 + 27*b^2 which must be nonzero
848 const Modular_Reducer mod_p(p);
849
850 const BigInt discriminant = mod_p.reduce(
851 mod_p.multiply(4, mod_p.cube(a)) +
852 mod_p.multiply(27, mod_p.square(b)));
853
854 if(discriminant == 0)
855 {
856 return false;
857 }
858
859 //check for valid cofactor
860 if(get_cofactor() < 1)
861 {
862 return false;
863 }
864
865 //check if the base point is on the curve
866 if(!base_point.on_the_curve())
867 {
868 return false;
869 }
870 if((base_point * get_cofactor()).is_zero())
871 {
872 return false;
873 }
874 //check if order of the base point is correct
875 if(!(base_point * order).is_zero())
876 {
877 return false;
878 }
879
880 return true;
881 }
882
883}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:48
#define BOTAN_UNUSED(...)
Definition: assert.h:141
static BigInt zero()
Definition: bigint.h:45
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition: big_rand.cpp:45
static BigInt one()
Definition: bigint.h:50
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:106
DER_Encoder & start_sequence()
Definition: der_enc.h:66
DER_Encoder & encode_null()
Definition: der_enc.cpp:280
DER_Encoder & end_cons()
Definition: der_enc.cpp:194
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:288
PointGFp OS2ECP(const uint8_t bits[], size_t len) const
Definition: ec_group.cpp:613
bool a_is_minus_3() const
Definition: ec_group.cpp:499
PointGFp hash_to_curve(const std::string &hash_fn, const uint8_t input[], size_t input_len, const uint8_t domain_sep[], size_t domain_sep_len, bool random_oracle=true) const
Definition: ec_group.cpp:690
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition: ec_group.cpp:646
const BigInt & get_b() const
Definition: ec_group.cpp:539
const BigInt & get_a() const
Definition: ec_group.cpp:534
const BigInt & get_g_y() const
Definition: ec_group.cpp:559
PointGFp blinded_base_point_multiply(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition: ec_group.cpp:639
const BigInt & get_cofactor() const
Definition: ec_group.cpp:564
BigInt mod_order(const BigInt &x) const
Definition: ec_group.cpp:569
bool operator==(const EC_Group &other) const
Definition: ec_group.cpp:774
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:579
EC_Group_Source source() const
Definition: ec_group.cpp:599
bool a_is_zero() const
Definition: ec_group.cpp:504
PointGFp point_multiply(const BigInt &x, const PointGFp &pt, const BigInt &y) const
Definition: ec_group.cpp:633
const BigInt & get_p() const
Definition: ec_group.cpp:529
static EC_Group EC_Group_from_PEM(const std::string &pem)
Definition: ec_group.cpp:468
bool verify_group(RandomNumberGenerator &rng, bool strong=false) const
Definition: ec_group.cpp:811
PointGFp point(const BigInt &x, const BigInt &y) const
Definition: ec_group.cpp:618
size_t point_size(PointGFp::Compression_Type format) const
Definition: ec_group.cpp:604
const BigInt & get_order() const
Definition: ec_group.cpp:549
size_t get_p_bits() const
Definition: ec_group.cpp:509
bool verify_public_element(const PointGFp &y) const
Definition: ec_group.cpp:788
static std::shared_ptr< EC_Group_Data > EC_group_info(const OID &oid)
Definition: ec_named.cpp:13
std::string PEM_encode() const
Definition: ec_group.cpp:768
const BigInt & get_g_x() const
Definition: ec_group.cpp:554
const OID & get_curve_oid() const
Definition: ec_group.cpp:594
BigInt square_mod_order(const BigInt &x) const
Definition: ec_group.cpp:574
const PointGFp & get_base_point() const
Definition: ec_group.cpp:544
static size_t clear_registered_curve_data()
Definition: ec_group.cpp:328
std::vector< uint8_t > DER_encode(EC_Group_Encoding form) const
Definition: ec_group.cpp:717
BigInt inverse_mod_order(const BigInt &x) const
Definition: ec_group.cpp:589
PointGFp zero_point() const
Definition: ec_group.cpp:671
size_t get_p_bytes() const
Definition: ec_group.cpp:514
PointGFp blinded_var_point_multiply(const PointGFp &point, const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition: ec_group.cpp:662
static OID EC_group_identity_from_order(const BigInt &order)
Definition: ec_named.cpp:289
BigInt random_scalar(RandomNumberGenerator &rng) const
Definition: ec_group.cpp:657
size_t get_order_bits() const
Definition: ec_group.cpp:519
size_t get_order_bytes() const
Definition: ec_group.cpp:524
BigInt cube(const BigInt &x) const
Definition: reducer.h:54
BigInt square(const BigInt &x) const
Definition: reducer.h:46
BigInt multiply(const BigInt &x, const BigInt &y) const
Definition: reducer.h:31
BigInt reduce(const BigInt &x) const
Definition: reducer.cpp:37
bool has_value() const
Definition: asn1_obj.h:263
bool empty() const
Definition: asn1_obj.h:257
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:61
std::string to_string() const
Definition: asn1_oid.cpp:97
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
Definition: point_mul.cpp:377
PointGFp mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
Definition: point_mul.cpp:244
bool on_the_curve() const
Definition: point_gfp.cpp:543
BigInt get_affine_x() const
Definition: point_gfp.cpp:504
bool is_zero() const
Definition: point_gfp.h:159
int(* final)(unsigned char *, CTX *)
PolynomialVector b
Definition: kyber.cpp:821
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:41
secure_vector< uint8_t > decode_check_label(DataSource &source, const std::string &label_want)
Definition: pem.cpp:52
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:66
Definition: alg_id.cpp:13
EC_Group_Source
Definition: ec_group.h:33
PointGFp OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
Definition: point_gfp.cpp:666
PointGFp hash_to_curve_sswu(const EC_Group &group, const std::string &hash_fn, const uint8_t input[], size_t input_len, const uint8_t domain_sep[], size_t domain_sep_len, bool random_oracle)
Definition: ec_h2c.cpp:184
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition: numthry.cpp:370
bool is_bailie_psw_probable_prime(const BigInt &n, const Modular_Reducer &mod_n)
Definition: primality.cpp:89
EC_Group_Encoding
Definition: ec_group.h:23
noop_mutex mutex_type
Definition: mutex.h:52
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: mod_inv.cpp:177
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65