43 m_monty(m_p, m_mod_field),
46 m_p_words(p.sig_words()),
48 m_order_bits(order.bits()),
49 m_order_bytes((m_order_bits + 7) / 8),
50 m_a_is_minus_3(a == p - 3),
51 m_a_is_zero(a.is_zero()),
52 m_has_cofactor(m_cofactor != 1),
53 m_order_is_less_than_p(m_order < p),
56 DER_Encoder der(m_der_named_curve);
59 if(const auto id = PCurve::PrimeOrderCurveId::from_oid(m_oid)) {
60 m_pcurve = PCurve::PrimeOrderCurve::from_id(*id);
62 m_engine = EC_Group_Engine::Optimized;
69#if defined(BOTAN_HAS_LEGACY_EC_POINT)
71 m_a_r = m_monty.mul(a, m_monty.R2(), ws);
72 m_b_r = m_monty.mul(
b, m_monty.R2(), ws);
74 m_engine = EC_Group_Engine::Legacy;
79 throw Not_Implemented(
"EC_Group this group is not supported in this build configuration");
81 throw Not_Implemented(
82 fmt(
"EC_Group the group {} is not supported in this build configuration", oid.to_string()));
88std::shared_ptr<EC_Group_Data> EC_Group_Data::create(
const BigInt& p,
97 auto group = std::make_shared<EC_Group_Data>(p, a,
b, g_x, g_y, order, cofactor, oid, source);
99#if defined(BOTAN_HAS_LEGACY_EC_POINT)
100 group->m_curve =
CurveGFp(group.get());
101 group->m_base_point =
EC_Point(group->m_curve, g_x, g_y);
102 if(!group->m_pcurve) {
103 group->m_base_mult = std::make_unique<EC_Point_Base_Point_Precompute>(group->m_base_point, group->m_mod_order);
134std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_with_trunc(std::span<const uint8_t> bytes)
const {
135 const size_t bit_length = 8 * bytes.size();
137 if(bit_length < order_bits()) {
139 return this->scalar_from_bytes_mod_order(bytes);
141 const size_t shift = bit_length - order_bits();
143 const size_t new_length = bytes.size() - (shift / 8);
144 const size_t bit_shift = shift % 8;
148 return this->scalar_from_bytes_mod_order(bytes.first(new_length));
150 std::vector<uint8_t> sbytes(new_length);
153 for(
size_t i = 0; i != new_length; ++i) {
154 const uint8_t w = bytes[i];
155 sbytes[i] = (w >> bit_shift) |
carry;
156 carry = w << (8 - bit_shift);
159 return this->scalar_from_bytes_mod_order(sbytes);
164std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_mod_order(std::span<const uint8_t> bytes)
const {
165 if(bytes.size() > 2 * order_bytes()) {
170 if(
auto s = m_pcurve->scalar_from_wide_bytes(bytes)) {
171 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), std::move(*s));
176#if defined(BOTAN_HAS_LEGACY_EC_POINT)
177 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(
BigInt(bytes)));
179 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
186 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->random_scalar(rng));
188#if defined(BOTAN_HAS_LEGACY_EC_POINT)
189 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(),
190 BigInt::random_integer(rng, BigInt::one(), m_order));
192 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
237std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(
const EC_Scalar_Data& scalar,
239 std::vector<BigInt>& ws)
const {
241 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
242 auto gk_x_mod_order = m_pcurve->base_point_mul_x_mod_order(k.value(), rng);
243 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), gk_x_mod_order);
245#if defined(BOTAN_HAS_LEGACY_EC_POINT)
246 const auto& k = EC_Scalar_Data_BN::checked_ref(scalar);
248 const auto pt = m_base_mult->mul(k.value(), rng, m_order, ws);
251 return scalar_zero();
253 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(pt.get_affine_x()));
257 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
262std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_deserialize(std::span<const uint8_t> bytes)
const {
263 if(bytes.size() != m_order_bytes) {
268 if(
auto s = m_pcurve->deserialize_scalar(bytes)) {
269 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), *s);
274#if defined(BOTAN_HAS_LEGACY_EC_POINT)
277 if(r.
is_zero() || r >= m_order) {
281 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), std::move(r));
283 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
288std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_deserialize(std::span<const uint8_t> bytes)
const {
291 if(
auto pt = m_pcurve->deserialize_point(bytes)) {
292 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(*pt));
297#if defined(BOTAN_HAS_LEGACY_EC_POINT)
298 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), bytes);
300 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
308std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_ro(std::string_view hash_fn,
309 std::span<const uint8_t> input,
310 std::span<const uint8_t> domain_sep)
const {
312 auto pt = m_pcurve->hash_to_curve_ro(hash_fn, input, domain_sep);
313 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt.to_affine());
315 throw Not_Implemented(
"Hash to curve is not implemented for this curve");
319std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_nu(std::string_view hash_fn,
320 std::span<const uint8_t> input,
321 std::span<const uint8_t> domain_sep)
const {
323 auto pt = m_pcurve->hash_to_curve_nu(hash_fn, input, domain_sep);
324 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
326 throw Not_Implemented(
"Hash to curve is not implemented for this curve");
330std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_g_mul(
const EC_Scalar_Data& scalar,
332 std::vector<BigInt>& ws)
const {
334 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
335 auto pt = m_pcurve->mul_by_g(k.value(), rng).to_affine();
336 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
338#if defined(BOTAN_HAS_LEGACY_EC_POINT)
339 const auto& group = scalar.
group();
340 const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);
343 auto pt = group->m_base_mult->mul(bn.value(), rng, m_order, ws);
344 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
347 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
358 auto pt = m_pcurve->mul_px_qy(EC_AffinePoint_Data_PC::checked_ref(p).value(),
359 EC_Scalar_Data_PC::checked_ref(x).value(),
360 EC_AffinePoint_Data_PC::checked_ref(q).value(),
361 EC_Scalar_Data_PC::checked_ref(y).value(),
365 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt->to_affine());
370#if defined(BOTAN_HAS_LEGACY_EC_POINT)
371 std::vector<BigInt> ws;
372 const auto& group = p.
group();
378 const auto order = group->order() * group->cofactor();
380 auto px = p_mul.
mul(EC_Scalar_Data_BN::checked_ref(x).value(), rng, order, ws);
381 auto qy = q_mul.
mul(EC_Scalar_Data_BN::checked_ref(y).value(), rng, order, ws);
383 auto px_qy = px + qy;
385 if(!px_qy.is_zero()) {
386 px_qy.force_affine();
387 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(px_qy));
392 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
400 auto pt = m_pcurve->point_add_mixed(
401 PCurve::PrimeOrderCurve::ProjectivePoint::from_affine(EC_AffinePoint_Data_PC::checked_ref(p).value()),
402 EC_AffinePoint_Data_PC::checked_ref(q).value());
404 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt.to_affine());
406#if defined(BOTAN_HAS_LEGACY_EC_POINT)
407 auto pt = p.to_legacy_point() + q.to_legacy_point();
408 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
410 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
417 auto pt = m_pcurve->point_negate(EC_AffinePoint_Data_PC::checked_ref(p).value());
418 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt);
420#if defined(BOTAN_HAS_LEGACY_EC_POINT)
421 auto pt = p.to_legacy_point();
423 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
425 throw Not_Implemented(
"Legacy EC interfaces disabled in this build configuration");
EC_Group_Data(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)