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>
24 class EC_Group_Data
final
28 EC_Group_Data(
const BigInt& p,
34 const BigInt& cofactor,
37 m_base_point(m_curve, g_x, g_y),
43 m_base_mult(m_base_point, m_mod_order),
46 m_order_bits(order.bits()),
52 bool match(
const BigInt& p,
const BigInt& a,
const BigInt& b,
53 const BigInt& g_x,
const BigInt& g_y,
54 const BigInt& order,
const BigInt& cofactor)
const
56 return (this->p() == p &&
59 this->order() == order &&
60 this->cofactor() == cofactor &&
65 const OID& oid()
const {
return m_oid; }
66 const BigInt& p()
const {
return m_curve.get_p(); }
67 const BigInt& a()
const {
return m_curve.get_a(); }
68 const BigInt& b()
const {
return m_curve.get_b(); }
69 const BigInt& order()
const {
return m_order; }
70 const BigInt& cofactor()
const {
return m_cofactor; }
71 const BigInt& g_x()
const {
return m_g_x; }
72 const BigInt& g_y()
const {
return m_g_y; }
74 size_t p_bits()
const {
return m_p_bits; }
75 size_t p_bytes()
const {
return (m_p_bits + 7) / 8; }
77 size_t order_bits()
const {
return m_order_bits; }
78 size_t order_bytes()
const {
return (m_order_bits + 7) / 8; }
80 const CurveGFp& curve()
const {
return m_curve; }
81 const PointGFp& base_point()
const {
return m_base_point; }
86 BigInt mod_order(
const BigInt& x)
const {
return m_mod_order.reduce(x); }
88 BigInt square_mod_order(
const BigInt& x)
const
90 return m_mod_order.square(x);
93 BigInt multiply_mod_order(
const BigInt& x,
const BigInt& y)
const
95 return m_mod_order.multiply(x, y);
98 BigInt multiply_mod_order(
const BigInt& x,
const BigInt& y,
const BigInt& z)
const
100 return m_mod_order.multiply(m_mod_order.multiply(x, y), z);
103 BigInt inverse_mod_order(
const BigInt& x)
const
108 PointGFp blinded_base_point_multiply(
const BigInt& k,
109 RandomNumberGenerator& rng,
110 std::vector<BigInt>& ws)
const
112 return m_base_mult.mul(k, rng, m_order, ws);
117 PointGFp m_base_point;
123 Modular_Reducer m_mod_order;
124 PointGFp_Base_Point_Precompute m_base_mult;
132 class EC_Group_Data_Map
final
135 EC_Group_Data_Map() {}
139 lock_guard_type<mutex_type> lock(
m_mutex);
140 size_t count = m_registered_curves.size();
141 m_registered_curves.clear();
145 std::shared_ptr<EC_Group_Data>
lookup(
const OID& oid)
147 lock_guard_type<mutex_type> lock(
m_mutex);
149 for(
auto i : m_registered_curves)
160 m_registered_curves.push_back(data);
165 return std::shared_ptr<EC_Group_Data>();
168 std::shared_ptr<EC_Group_Data> lookup_or_create(
const BigInt& p,
174 const BigInt& cofactor,
177 lock_guard_type<mutex_type> lock(
m_mutex);
179 for(
auto i : m_registered_curves)
185 else if(i->oid().has_value())
189 if(i->match(p, a, b, g_x, g_y, order, cofactor))
202 m_registered_curves.push_back(data);
208 return add_curve(p, a, b, g_x, g_y, order, cofactor, oid);
213 std::shared_ptr<EC_Group_Data> add_curve(
const BigInt& p,
219 const BigInt& cofactor,
222 std::shared_ptr<EC_Group_Data> d =
223 std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid);
226 m_registered_curves.push_back(d);
231 std::vector<std::shared_ptr<EC_Group_Data>> m_registered_curves;
235 EC_Group_Data_Map& EC_Group::ec_group_data()
242 static Allocator_Initializer g_init_allocator;
243 static EC_Group_Data_Map g_ec_data;
250 return ec_group_data().clear();
254 std::shared_ptr<EC_Group_Data>
255 EC_Group::load_EC_group_info(
const char* p_str,
260 const char* order_str,
266 const BigInt g_x(g_x_str);
267 const BigInt g_y(g_y_str);
268 const BigInt order(order_str);
271 return std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid);
275 std::shared_ptr<EC_Group_Data> EC_Group::BER_decode_EC_group(
const uint8_t bits[],
size_t len)
277 BER_Decoder ber(bits, len);
278 BER_Object obj = ber.get_next_object();
282 throw Decoding_Error(
"Cannot handle ImplicitCA ECC parameters");
287 BER_Decoder(bits, len).decode(dom_par_oid);
288 return ec_group_data().lookup(dom_par_oid);
292 BigInt p, a, b, order, cofactor;
293 std::vector<uint8_t> base_pt;
294 std::vector<uint8_t> seed;
296 BER_Decoder(bits, len)
298 .decode_and_check<
size_t>(1,
"Unknown ECC param version code")
300 .decode_and_check(OID(
"1.2.840.10045.1.1"),
301 "Only prime ECC fields supported")
305 .decode_octet_string_bigint(a)
306 .decode_octet_string_bigint(b)
316 throw Decoding_Error(
"Invalid ECC p parameter");
318 if(a.is_negative() || a >= p)
319 throw Decoding_Error(
"Invalid ECC a parameter");
322 throw Decoding_Error(
"Invalid ECC b parameter");
325 throw Decoding_Error(
"Invalid ECC order parameter");
327 if(cofactor <= 0 || cofactor >= 16)
328 throw Decoding_Error(
"Invalid ECC cofactor parameter");
330 std::pair<BigInt, BigInt> base_xy =
Botan::OS2ECP(base_pt.data(), base_pt.size(), p, a, b);
332 return ec_group_data().lookup_or_create(p, a, b, base_xy.first, base_xy.second, order, cofactor, OID());
336 throw Decoding_Error(
"Unexpected tag while decoding ECC domain params");
351 this->m_data = ec_group_data().lookup(domain_oid);
365 m_data = ec_group_data().lookup(oid);
371 if(m_data ==
nullptr)
373 if(str.size() > 30 && str.substr(0, 29) ==
"-----BEGIN EC PARAMETERS-----")
377 this->m_data = BER_decode_EC_group(ber.data(), ber.size());
381 if(m_data ==
nullptr)
408 m_data = ec_group_data().lookup_or_create(p, a, b, base_x, base_y, order, cofactor, oid);
413 m_data = BER_decode_EC_group(ber.data(), ber.size());
416 const EC_Group_Data& EC_Group::data()
const
418 if(m_data ==
nullptr)
425 return data().curve();
430 return data().a_is_minus_3();
435 return data().a_is_zero();
440 return data().p_bits();
445 return data().p_bytes();
450 return data().order_bits();
455 return data().order_bytes();
475 return data().base_point();
480 return data().order();
495 return data().cofactor();
500 return data().mod_order(k);
505 return data().square_mod_order(x);
510 return data().multiply_mod_order(x, y);
515 return data().multiply_mod_order(x, y, z);
520 return data().inverse_mod_order(x);
545 return PointGFp(data().curve(), x, y);
556 std::vector<BigInt>& ws)
const
558 return data().blinded_base_point_multiply(k, rng, ws);
563 std::vector<BigInt>& ws)
const
565 const PointGFp pt = data().blinded_base_point_multiply(k, rng, ws);
580 std::vector<BigInt>& ws)
const
594 std::vector<uint8_t> output;
600 const size_t ecpVers1 = 1;
601 const OID curve_type(
"1.2.840.10045.1.1");
627 throw Encoding_Error(
"Cannot encode EC_Group as OID because OID not set");
651 if(m_data == other.m_data)
676 if((point *
get_order()).is_zero() ==
false)
723 if(discriminant == 0)
744 if(!(base_point * order).is_zero())
const BigInt & get_b() const
const PointGFp & get_base_point() const
BigInt cube(const BigInt &x) const
PointGFp point(const BigInt &x, const BigInt &y) const
bool a_is_minus_3() const
size_t point_size(PointGFp::Compression_Type format) const
const BigInt & get_a() const
int(* final)(unsigned char *, CTX *)
BigInt inverse_mod_order(const BigInt &x) const
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
const BigInt & get_g_x() const
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
const OID & get_curve_oid() const
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
PointGFp blinded_var_point_multiply(const PointGFp &point, const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
static std::string PEM_for_named_group(const std::string &name)
size_t get_order_bytes() const
BigInt get_affine_x() const
DER_Encoder & encode(bool b)
secure_vector< uint8_t > decode_check_label(DataSource &source, const std::string &label_want)
bool is_bailie_psw_probable_prime(const BigInt &n, const Modular_Reducer &mod_n)
const BigInt & get_g_y() const
size_t get_p_bytes() const
std::vector< T, secure_allocator< T >> secure_vector
BigInt square_mod_order(const BigInt &x) const
BigInt mod_order(const BigInt &x) const
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
const BigInt & get_order() const
const CurveGFp & get_curve() const
std::string PEM_encode() const
BigInt multiply(const BigInt &x, const BigInt &y) const
PointGFp mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
DER_Encoder & encode_null()
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
std::string to_string() const
PointGFp point_multiply(const BigInt &x, const PointGFp &pt, const BigInt &y) const
std::vector< uint8_t > DER_encode(EC_Group_Encoding form) const
bool operator==(const EC_Group &other) const
BigInt reduce(const BigInt &x) const
static std::shared_ptr< EC_Group_Data > EC_group_info(const OID &oid)
size_t get_p_bits() const
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
bool on_the_curve() const
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
bool verify_public_element(const PointGFp &y) const
PointGFp OS2ECP(const uint8_t bits[], size_t len) const
bool verify_group(RandomNumberGenerator &rng, bool strong=false) const
PointGFp blinded_base_point_multiply(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
BigInt square(const BigInt &x) const
PointGFp multi_exp(const BigInt &k1, const BigInt &k2) const
const BigInt & get_cofactor() const
std::string lookup(const OID &oid)
const BigInt & get_p() const
BigInt random_scalar(RandomNumberGenerator &rng) const
PointGFp OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
size_t get_order_bits() const
static size_t clear_registered_curve_data()
PointGFp zero_point() const
static OID from_string(const std::string &str)