• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 11972552403

22 Nov 2024 12:26PM UTC coverage: 91.244% (+0.004%) from 91.24%
11972552403

push

github

web-flow
Merge pull request #4436 from randombit/jack/cleanup-curvegfp

Cleanups relating to CurveGFp

93250 of 102198 relevant lines covered (91.24%)

11237819.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.16
/src/lib/pubkey/ec_group/ec_inner_data.cpp
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/ec_inner_bn.h>
11
#include <botan/internal/ec_inner_pc.h>
12
#include <botan/internal/mp_core.h>
13
#include <botan/internal/pcurves.h>
14
#include <botan/internal/point_mul.h>
15

16
namespace Botan {
17

18
EC_Group_Data::~EC_Group_Data() = default;
14,022✔
19

20
// Note this constructor *does not* initialize m_curve, m_base_point or m_base_mult
21
EC_Group_Data::EC_Group_Data(const BigInt& p,
1,169✔
22
                             const BigInt& a,
23
                             const BigInt& b,
24
                             const BigInt& g_x,
25
                             const BigInt& g_y,
26
                             const BigInt& order,
27
                             const BigInt& cofactor,
28
                             const OID& oid,
29
                             EC_Group_Source source) :
1,169✔
30
      m_p(p),
1,169✔
31
      m_a(a),
1,169✔
32
      m_b(b),
1,169✔
33
      m_g_x(g_x),
1,169✔
34
      m_g_y(g_y),
1,169✔
35
      m_order(order),
1,169✔
36
      m_cofactor(cofactor),
1,169✔
37
      m_monty(m_p),
1,169✔
38
      m_mod_order(order),
1,169✔
39
      m_oid(oid),
1,169✔
40
      m_p_words(p.sig_words()),
1,169✔
41
      m_p_bits(p.bits()),
1,169✔
42
      m_order_bits(order.bits()),
1,169✔
43
      m_order_bytes((m_order_bits + 7) / 8),
1,169✔
44
      m_a_is_minus_3(a == p - 3),
2,338✔
45
      m_a_is_zero(a.is_zero()),
1,169✔
46
      m_has_cofactor(m_cofactor != 1),
1,169✔
47
      m_order_is_less_than_p(m_order < p),
1,169✔
48
      m_source(source) {
3,507✔
49
   if(!m_oid.empty()) {
1,169✔
50
      DER_Encoder der(m_der_named_curve);
1,157✔
51
      der.encode(m_oid);
1,157✔
52

53
      if(const auto id = PCurve::PrimeOrderCurveId::from_oid(m_oid)) {
1,157✔
54
         m_pcurve = PCurve::PrimeOrderCurve::from_id(*id);
917✔
55
         // still possibly null, if the curve is supported in general but not
56
         // available in the build
57
      }
58
   }
1,157✔
59

60
   secure_vector<word> ws;
1,169✔
61
   m_a_r = m_monty.mul(a, m_monty.R2(), ws);
2,338✔
62
   m_b_r = m_monty.mul(b, m_monty.R2(), ws);
2,338✔
63
}
1,169✔
64

65
std::shared_ptr<EC_Group_Data> EC_Group_Data::create(const BigInt& p,
1,169✔
66
                                                     const BigInt& a,
67
                                                     const BigInt& b,
68
                                                     const BigInt& g_x,
69
                                                     const BigInt& g_y,
70
                                                     const BigInt& order,
71
                                                     const BigInt& cofactor,
72
                                                     const OID& oid,
73
                                                     EC_Group_Source source) {
74
   auto group = std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, source);
1,169✔
75

76
   group->m_curve = CurveGFp(group.get());
1,169✔
77
   group->m_base_point = EC_Point(group->m_curve, g_x, g_y);
2,338✔
78
   if(!group->m_pcurve) {
1,169✔
79
      group->m_base_mult = std::make_unique<EC_Point_Base_Point_Precompute>(group->m_base_point, group->m_mod_order);
252✔
80
   }
81

82
   return group;
1,169✔
83
}
×
84

85
bool EC_Group_Data::params_match(const BigInt& p,
934✔
86
                                 const BigInt& a,
87
                                 const BigInt& b,
88
                                 const BigInt& g_x,
89
                                 const BigInt& g_y,
90
                                 const BigInt& order,
91
                                 const BigInt& cofactor) const {
92
   return (this->p() == p && this->a() == a && this->b() == b && this->order() == order &&
1,032✔
93
           this->cofactor() == cofactor && this->g_x() == g_x && this->g_y() == g_y);
1,022✔
94
}
95

96
bool EC_Group_Data::params_match(const EC_Group_Data& other) const {
21✔
97
   return params_match(other.p(), other.a(), other.b(), other.g_x(), other.g_y(), other.order(), other.cofactor());
21✔
98
}
99

100
void EC_Group_Data::set_oid(const OID& oid) {
6✔
101
   BOTAN_ARG_CHECK(!oid.empty(), "OID should be set");
6✔
102
   BOTAN_STATE_CHECK(m_oid.empty() && m_der_named_curve.empty());
6✔
103
   m_oid = oid;
6✔
104

105
   DER_Encoder der(m_der_named_curve);
6✔
106
   der.encode(m_oid);
6✔
107
}
6✔
108

109
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_with_trunc(std::span<const uint8_t> bytes) const {
26,059✔
110
   const size_t bit_length = 8 * bytes.size();
26,059✔
111

112
   if(bit_length < order_bits()) {
26,059✔
113
      // No shifting required, but might still need to reduce by modulus
114
      return this->scalar_from_bytes_mod_order(bytes);
5,261✔
115
   } else {
116
      const size_t shift = bit_length - order_bits();
20,798✔
117

118
      const size_t new_length = bytes.size() - (shift / 8);
20,798✔
119
      const size_t bit_shift = shift % 8;
20,798✔
120

121
      if(bit_shift == 0) {
20,798✔
122
         // Easy case just read different bytes
123
         return this->scalar_from_bytes_mod_order(bytes.first(new_length));
18,152✔
124
      } else {
125
         std::vector<uint8_t> sbytes(new_length);
2,646✔
126

127
         uint8_t carry = 0;
2,646✔
128
         for(size_t i = 0; i != new_length; ++i) {
72,384✔
129
            const uint8_t w = bytes[i];
69,738✔
130
            sbytes[i] = (w >> bit_shift) | carry;
69,738✔
131
            carry = w << (8 - bit_shift);
69,738✔
132
         }
133

134
         return this->scalar_from_bytes_mod_order(sbytes);
2,646✔
135
      }
2,646✔
136
   }
137
}
138

139
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bytes_mod_order(std::span<const uint8_t> bytes) const {
26,782✔
140
   if(bytes.size() >= 2 * order_bytes()) {
26,782✔
141
      return {};
×
142
   }
143

144
   if(m_pcurve) {
26,782✔
145
      if(auto s = m_pcurve->scalar_from_wide_bytes(bytes)) {
19,802✔
146
         return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), std::move(*s));
19,802✔
147
      } else {
148
         return {};
×
149
      }
19,802✔
150
   } else {
151
      return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), mod_order(BigInt(bytes)));
20,940✔
152
   }
153
}
154

155
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_random(RandomNumberGenerator& rng) const {
6,869✔
156
   if(m_pcurve) {
6,869✔
157
      return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->random_scalar(rng));
3,423✔
158
   } else {
159
      return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(),
6,892✔
160
                                                 BigInt::random_integer(rng, BigInt::one(), m_order));
13,784✔
161
   }
162
}
163

164
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_zero() const {
×
165
   if(m_pcurve) {
×
166
      return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->scalar_zero());
×
167
   } else {
168
      return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::zero());
×
169
   }
170
}
171

172
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_one() const {
45✔
173
   if(m_pcurve) {
45✔
174
      return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->scalar_one());
37✔
175
   } else {
176
      return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::one());
8✔
177
   }
178
}
179

180
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bigint(const BigInt& bn) const {
8,075✔
181
   if(bn <= 0 || bn >= m_order) {
8,075✔
182
      return {};
×
183
   }
184

185
   if(m_pcurve) {
8,075✔
186
      return this->scalar_deserialize(bn.serialize(m_order_bytes));
13,534✔
187
   } else {
188
      return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), bn);
1,308✔
189
   }
190
}
191

192
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(const EC_Scalar_Data& scalar,
3,306✔
193
                                                              RandomNumberGenerator& rng,
194
                                                              std::vector<BigInt>& ws) const {
195
   if(m_pcurve) {
3,306✔
196
      const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
1,685✔
197
      auto gk_x_mod_order = m_pcurve->base_point_mul_x_mod_order(k.value(), rng);
1,685✔
198
      return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), gk_x_mod_order);
1,685✔
199
   } else {
1,685✔
200
      const auto& k = EC_Scalar_Data_BN::checked_ref(scalar);
1,621✔
201
      BOTAN_STATE_CHECK(m_base_mult != nullptr);
1,621✔
202
      const auto pt = m_base_mult->mul(k.value(), rng, m_order, ws);
1,621✔
203

204
      if(pt.is_zero()) {
3,242✔
205
         return scalar_zero();
×
206
      } else {
207
         return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), mod_order(pt.get_affine_x()));
4,863✔
208
      }
209
   }
1,621✔
210
}
211

212
std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_deserialize(std::span<const uint8_t> bytes) const {
66,418✔
213
   if(bytes.size() != m_order_bytes) {
66,418✔
214
      return nullptr;
6,358✔
215
   }
216

217
   if(m_pcurve) {
60,060✔
218
      if(auto s = m_pcurve->deserialize_scalar(bytes)) {
46,865✔
219
         return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), *s);
44,713✔
220
      } else {
221
         return nullptr;
2,152✔
222
      }
46,865✔
223
   } else {
224
      BigInt r(bytes);
13,195✔
225

226
      if(r.is_zero() || r >= m_order) {
26,390✔
227
         return nullptr;
713✔
228
      }
229

230
      return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), std::move(r));
12,482✔
231
   }
13,195✔
232
}
233

234
std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_deserialize(std::span<const uint8_t> bytes) const {
48,997✔
235
   try {
48,997✔
236
      if(m_pcurve) {
48,997✔
237
         if(auto pt = m_pcurve->deserialize_point(bytes)) {
41,458✔
238
            return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(*pt));
35,479✔
239
         } else {
240
            return nullptr;
5,979✔
241
         }
41,458✔
242
      } else {
243
         return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), bytes);
7,752✔
244
      }
245
   } catch(...) {
213✔
246
      return nullptr;
213✔
247
   }
213✔
248
}
249

250
std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_ro(std::string_view hash_fn,
24✔
251
                                                                           std::span<const uint8_t> input,
252
                                                                           std::span<const uint8_t> domain_sep) const {
253
   if(m_pcurve) {
24✔
254
      auto pt = m_pcurve->hash_to_curve_ro(hash_fn, input, domain_sep);
24✔
255
      return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt.to_affine());
24✔
256
   } else {
24✔
257
      throw Not_Implemented("Hash to curve is not implemented for this curve");
×
258
   }
259
}
260

261
std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_nu(std::string_view hash_fn,
33✔
262
                                                                           std::span<const uint8_t> input,
263
                                                                           std::span<const uint8_t> domain_sep) const {
264
   if(m_pcurve) {
33✔
265
      auto pt = m_pcurve->hash_to_curve_nu(hash_fn, input, domain_sep);
33✔
266
      return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
30✔
267
   } else {
30✔
268
      throw Not_Implemented("Hash to curve is not implemented for this curve");
×
269
   }
270
}
271

272
std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_g_mul(const EC_Scalar_Data& scalar,
8,630✔
273
                                                                RandomNumberGenerator& rng,
274
                                                                std::vector<BigInt>& ws) const {
275
   if(m_pcurve) {
8,630✔
276
      const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
5,310✔
277
      auto pt = m_pcurve->mul_by_g(k.value(), rng).to_affine();
10,620✔
278
      return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
5,310✔
279
   } else {
5,310✔
280
      const auto& group = scalar.group();
3,320✔
281
      const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);
3,320✔
282

283
      BOTAN_STATE_CHECK(group->m_base_mult != nullptr);
3,320✔
284
      auto pt = group->m_base_mult->mul(bn.value(), rng, m_order, ws);
3,320✔
285
      return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
3,320✔
286
   }
3,320✔
287
}
288

289
std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::mul_px_qy(const EC_AffinePoint_Data& p,
819✔
290
                                                              const EC_Scalar_Data& x,
291
                                                              const EC_AffinePoint_Data& q,
292
                                                              const EC_Scalar_Data& y,
293
                                                              RandomNumberGenerator& rng) const {
294
   if(m_pcurve) {
819✔
295
      auto pt = m_pcurve->mul_px_qy(EC_AffinePoint_Data_PC::checked_ref(p).value(),
1,260✔
296
                                    EC_Scalar_Data_PC::checked_ref(x).value(),
630✔
297
                                    EC_AffinePoint_Data_PC::checked_ref(q).value(),
630✔
298
                                    EC_Scalar_Data_PC::checked_ref(y).value(),
630✔
299
                                    rng);
630✔
300

301
      if(pt) {
630✔
302
         return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt->to_affine());
630✔
303
      } else {
304
         return nullptr;
×
305
      }
306
   } else {
630✔
307
      std::vector<BigInt> ws;
189✔
308
      const auto& group = p.group();
189✔
309

310
      // TODO this could be better!
311
      EC_Point_Var_Point_Precompute p_mul(p.to_legacy_point(), rng, ws);
189✔
312
      EC_Point_Var_Point_Precompute q_mul(q.to_legacy_point(), rng, ws);
189✔
313

314
      const auto order = group->order() * group->cofactor();  // See #3800
189✔
315

316
      auto px = p_mul.mul(EC_Scalar_Data_BN::checked_ref(x).value(), rng, order, ws);
189✔
317
      auto qy = q_mul.mul(EC_Scalar_Data_BN::checked_ref(y).value(), rng, order, ws);
189✔
318

319
      auto px_qy = px + qy;
189✔
320
      px_qy.force_affine();
189✔
321

322
      if(!px_qy.is_zero()) {
189✔
323
         return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(px_qy));
189✔
324
      } else {
325
         return nullptr;
×
326
      }
327
   }
756✔
328
}
329

330
std::unique_ptr<EC_Mul2Table_Data> EC_Group_Data::make_mul2_table(const EC_AffinePoint_Data& h) const {
11,458✔
331
   if(m_pcurve) {
11,458✔
332
      EC_AffinePoint_Data_PC g(shared_from_this(), m_pcurve->generator());
20,802✔
333
      return std::make_unique<EC_Mul2Table_Data_PC>(g, h);
10,401✔
334
   } else {
10,401✔
335
      EC_AffinePoint_Data_BN g(shared_from_this(), this->base_point());
2,114✔
336
      return std::make_unique<EC_Mul2Table_Data_BN>(g, h);
1,057✔
337
   }
1,057✔
338
}
339

340
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc