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

randombit / botan / 23225340130

18 Mar 2026 01:53AM UTC coverage: 89.677% (-0.001%) from 89.678%
23225340130

push

github

web-flow
Merge pull request #5456 from randombit/jack/clang-tidy-22

Fix various warnings from clang-tidy 22

104438 of 116460 relevant lines covered (89.68%)

11819947.55 hits per line

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

99.49
/src/cli/perf_math.cpp
1
/*
2
* (C) 2024 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "perf.h"
8

9
#include <ostream>
10

11
#if defined(BOTAN_HAS_BIGINT)
12
   #include <botan/assert.h>
13
   #include <botan/bigint.h>
14
   #include <botan/internal/divide.h>
15
#endif
16

17
#if defined(BOTAN_HAS_NUMBERTHEORY)
18
   #include <botan/numthry.h>
19
   #include <botan/internal/barrett.h>
20
   #include <botan/internal/primality.h>
21
#endif
22

23
#if defined(BOTAN_HAS_DL_GROUP)
24
   #include <botan/dl_group.h>
25
#endif
26

27
namespace Botan_CLI {
28

29
namespace {
30

31
#if defined(BOTAN_HAS_BIGINT)
32

33
class PerfTest_MpMul final : public PerfTest {
1✔
34
   public:
35
      void go(const PerfConfig& config) override {
1✔
36
         const auto runtime_per_size = config.runtime();
1✔
37

38
         for(const size_t bits : {256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096}) {
10✔
39
            auto mul_timer = config.make_timer("BigInt mul " + std::to_string(bits));
18✔
40
            auto sqr_timer = config.make_timer("BigInt sqr " + std::to_string(bits));
18✔
41

42
            const Botan::BigInt y(config.rng(), bits);
9✔
43
            Botan::secure_vector<Botan::word> ws;
9✔
44

45
            while(mul_timer->under(runtime_per_size)) {
8,569✔
46
               Botan::BigInt x(config.rng(), bits);
8,560✔
47

48
               sqr_timer->start();
8,560✔
49
               x.square(ws);
8,560✔
50
               sqr_timer->stop();
8,560✔
51

52
               x.mask_bits(bits);
8,560✔
53

54
               mul_timer->start();
8,560✔
55
               x.mul(y, ws);
8,560✔
56
               mul_timer->stop();
8,560✔
57
            }
8,560✔
58

59
            config.record_result(*mul_timer);
9✔
60
            config.record_result(*sqr_timer);
18✔
61
         }
18✔
62
      }
1✔
63
};
64

65
BOTAN_REGISTER_PERF_TEST("mp_mul", PerfTest_MpMul);
1✔
66

67
class PerfTest_MpDiv final : public PerfTest {
1✔
68
   public:
69
      void go(const PerfConfig& config) override {
1✔
70
         const auto runtime_per_size = config.runtime();
1✔
71

72
         for(const size_t n_bits : {256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096}) {
10✔
73
            const size_t q_bits = n_bits / 2;
9✔
74
            const std::string bit_descr = std::to_string(n_bits) + "/" + std::to_string(q_bits);
27✔
75

76
            auto div_timer = config.make_timer("BigInt div " + bit_descr);
18✔
77
            auto ct_div_timer = config.make_timer("BigInt ct_div " + bit_descr);
18✔
78

79
            Botan::BigInt y;
9✔
80
            Botan::BigInt x;
9✔
81
            const Botan::secure_vector<Botan::word> ws;
9✔
82

83
            Botan::BigInt q1;
9✔
84
            Botan::BigInt r1;
9✔
85
            Botan::BigInt q2;
9✔
86
            Botan::BigInt r2;
9✔
87

88
            while(ct_div_timer->under(runtime_per_size)) {
9✔
89
               x.randomize(config.rng(), n_bits);
64✔
90
               y.randomize(config.rng(), q_bits);
64✔
91

92
               div_timer->start();
64✔
93
               Botan::vartime_divide(x, y, q1, r1);
64✔
94
               div_timer->stop();
64✔
95

96
               ct_div_timer->start();
64✔
97
               Botan::ct_divide(x, y, q2, r2);
64✔
98
               ct_div_timer->stop();
64✔
99

100
               BOTAN_ASSERT_EQUAL(q1, q2, "Quotient ok");
64✔
101
               BOTAN_ASSERT_EQUAL(r1, r2, "Remainder ok");
137✔
102
            }
103

104
            config.record_result(*div_timer);
9✔
105
            config.record_result(*ct_div_timer);
9✔
106
         }
18✔
107
      }
1✔
108
};
109

110
BOTAN_REGISTER_PERF_TEST("mp_div", PerfTest_MpDiv);
1✔
111

112
class PerfTest_MpDiv10 final : public PerfTest {
1✔
113
   public:
114
      void go(const PerfConfig& config) override {
1✔
115
         const auto runtime_per_size = config.runtime();
1✔
116

117
         for(const size_t n_bits : {256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096}) {
10✔
118
            const std::string bit_descr = std::to_string(n_bits) + "/10";
18✔
119

120
            auto div_timer = config.make_timer("BigInt div " + bit_descr);
18✔
121
            auto ct_div_timer = config.make_timer("BigInt ct_div " + bit_descr);
18✔
122

123
            Botan::BigInt x;
9✔
124
            const Botan::secure_vector<Botan::word> ws;
9✔
125

126
            const auto ten = Botan::BigInt::from_word(10);
9✔
127
            Botan::BigInt q1;
9✔
128
            Botan::BigInt r1;
9✔
129
            Botan::BigInt q2;
9✔
130
            Botan::word r2 = 0;
9✔
131

132
            while(ct_div_timer->under(runtime_per_size)) {
9✔
133
               x.randomize(config.rng(), n_bits);
674✔
134

135
               div_timer->start();
674✔
136
               Botan::vartime_divide(x, ten, q1, r1);
674✔
137
               div_timer->stop();
674✔
138

139
               ct_div_timer->start();
674✔
140
               Botan::ct_divide_word(x, 10, q2, r2);
674✔
141
               ct_div_timer->stop();
674✔
142

143
               BOTAN_ASSERT_EQUAL(q1, q2, "Quotient ok");
674✔
144
               BOTAN_ASSERT_EQUAL(r1, r2, "Remainder ok");
1,357✔
145
            }
146

147
            config.record_result(*div_timer);
9✔
148
            config.record_result(*ct_div_timer);
9✔
149
         }
18✔
150
      }
1✔
151
};
152

153
BOTAN_REGISTER_PERF_TEST("mp_div10", PerfTest_MpDiv10);
1✔
154

155
#endif
156

157
#if defined(BOTAN_HAS_NUMBERTHEORY)
158

159
class PerfTest_BnRedc final : public PerfTest {
1✔
160
   public:
161
      void go(const PerfConfig& config) override {
1✔
162
         const auto runtime = config.runtime();
1✔
163

164
         for(const size_t bitsize : {256, 512, 1024, 2048, 4096}) {
6✔
165
            Botan::BigInt p(config.rng(), bitsize);
5✔
166

167
            const std::string bit_str = std::to_string(bitsize) + " bit ";
10✔
168
            auto barrett_setup_pub_timer = config.make_timer(bit_str + "Barrett setup public");
10✔
169
            auto barrett_setup_sec_timer = config.make_timer(bit_str + "Barrett setup secret");
10✔
170

171
            while(barrett_setup_sec_timer->under(runtime)) {
63✔
172
               barrett_setup_sec_timer->run([&]() { Botan::Barrett_Reduction::for_secret_modulus(p); });
116✔
173
               barrett_setup_pub_timer->run([&]() { Botan::Barrett_Reduction::for_public_modulus(p); });
116✔
174
            }
175

176
            config.record_result(*barrett_setup_pub_timer);
5✔
177
            config.record_result(*barrett_setup_sec_timer);
5✔
178

179
            auto mod_p = Botan::Barrett_Reduction::for_public_modulus(p);
5✔
180

181
            auto barrett_timer = config.make_timer(bit_str + "Barrett redc");
10✔
182
            auto knuth_timer = config.make_timer(bit_str + "Knuth redc");
10✔
183
            auto ct_modulo_timer = config.make_timer(bit_str + "ct_modulo");
10✔
184

185
            while(ct_modulo_timer->under(runtime)) {
27✔
186
               const Botan::BigInt x(config.rng(), p.bits() * 2 - 1);
22✔
187

188
               const Botan::BigInt r1 = barrett_timer->run([&] { return mod_p.reduce(x); });
44✔
189
               const Botan::BigInt r2 = knuth_timer->run([&] { return x % p; });
44✔
190
               const Botan::BigInt r3 = ct_modulo_timer->run([&] { return Botan::ct_modulo(x, p); });
44✔
191

192
               BOTAN_ASSERT(r1 == r2, "Computed different results");
22✔
193
               BOTAN_ASSERT(r1 == r3, "Computed different results");
22✔
194
            }
22✔
195

196
            config.record_result(*barrett_timer);
5✔
197
            config.record_result(*knuth_timer);
5✔
198
            config.record_result(*ct_modulo_timer);
10✔
199
         }
25✔
200
      }
1✔
201
};
202

203
BOTAN_REGISTER_PERF_TEST("bn_redc", PerfTest_BnRedc);
1✔
204

205
class PerfTest_InvMod final : public PerfTest {
1✔
206
   public:
207
      void go(const PerfConfig& config) override {
1✔
208
         const auto runtime = config.runtime();
1✔
209

210
         for(const size_t bits : {256, 384, 512, 1024, 2048}) {
6✔
211
            const std::string bit_str = std::to_string(bits);
5✔
212

213
            auto timer = config.make_timer("inverse_mod-" + bit_str);
10✔
214
            auto gcd_timer = config.make_timer("gcd-" + bit_str);
10✔
215

216
            while(timer->under(runtime) && gcd_timer->under(runtime)) {
15✔
217
               const Botan::BigInt x(config.rng(), bits - 1);
10✔
218
               Botan::BigInt mod(config.rng(), bits);
10✔
219

220
               const Botan::BigInt x_inv = timer->run([&] { return Botan::inverse_mod(x, mod); });
20✔
221

222
               const Botan::BigInt g = gcd_timer->run([&] { return gcd(x, mod); });
20✔
223

224
               if(x_inv == 0) {
10✔
225
                  BOTAN_ASSERT(g != 1, "Inversion only fails if gcd(x, mod) > 1");
4✔
226
               } else {
227
                  BOTAN_ASSERT(g == 1, "Inversion succeeds only if gcd != 1");
6✔
228
                  const Botan::BigInt check = (x_inv * x) % mod;
6✔
229
                  BOTAN_ASSERT_EQUAL(check, 1, "Const time inversion correct");
6✔
230
               }
6✔
231
            }
10✔
232

233
            config.record_result(*timer);
5✔
234
            config.record_result(*gcd_timer);
10✔
235
         }
5✔
236
      }
1✔
237
};
238

239
BOTAN_REGISTER_PERF_TEST("inverse_mod", PerfTest_InvMod);
1✔
240

241
class PerfTest_IsPrime final : public PerfTest {
1✔
242
   public:
243
      void go(const PerfConfig& config) override {
1✔
244
         const auto runtime = config.runtime();
1✔
245

246
         for(const size_t bits : {256, 512, 1024}) {
4✔
247
            auto mr_timer = config.make_timer("Miller-Rabin-" + std::to_string(bits));
6✔
248
            auto bpsw_timer = config.make_timer("Bailie-PSW-" + std::to_string(bits));
6✔
249
            auto lucas_timer = config.make_timer("Lucas-" + std::to_string(bits));
6✔
250

251
            Botan::BigInt n = Botan::random_prime(config.rng(), bits);
3✔
252

253
            while(lucas_timer->under(runtime)) {
6✔
254
               auto mod_n = Botan::Barrett_Reduction::for_public_modulus(n);
3✔
255

256
               mr_timer->run([&]() { return Botan::is_miller_rabin_probable_prime(n, mod_n, config.rng(), 2); });
6✔
257

258
               bpsw_timer->run([&]() { return Botan::is_bailie_psw_probable_prime(n, mod_n); });
6✔
259

260
               lucas_timer->run([&]() { return Botan::is_lucas_probable_prime(n, mod_n); });
6✔
261

262
               n += 2;
3✔
263
            }
3✔
264

265
            config.record_result(*mr_timer);
3✔
266
            config.record_result(*bpsw_timer);
3✔
267
            config.record_result(*lucas_timer);
3✔
268
         }
9✔
269
      }
1✔
270
};
271

272
BOTAN_REGISTER_PERF_TEST("primality_test", PerfTest_IsPrime);
1✔
273

274
class PerfTest_RandomPrime final : public PerfTest {
1✔
275
   public:
276
      void go(const PerfConfig& config) override {
1✔
277
         const auto coprime = Botan::BigInt::from_word(0x10001);
1✔
278
         const auto runtime = config.runtime();
1✔
279

280
         auto& rng = config.rng();
1✔
281

282
         for(size_t bits : {256, 384, 512, 768, 1024, 1536}) {
7✔
283
            auto genprime_timer = config.make_timer("random_prime " + std::to_string(bits));
12✔
284
            auto is_prime_timer = config.make_timer("is_prime " + std::to_string(bits));
12✔
285

286
            while(genprime_timer->under(runtime) && is_prime_timer->under(runtime)) {
12✔
287
               const Botan::BigInt p = genprime_timer->run([&] { return Botan::random_prime(rng, bits, coprime); });
12✔
288

289
               if(!is_prime_timer->run([&] { return Botan::is_prime(p, rng, 64, true); })) {
12✔
290
                  config.error_output() << "Generated prime " << p << " which failed a primality test";
×
291
               }
292

293
               // Now test p+2, p+4, ... which may or may not be prime
294
               for(size_t i = 2; i <= 64; i += 2) {
198✔
295
                  is_prime_timer->run([&]() { Botan::is_prime(p + i, rng, 64, true); });
384✔
296
               }
297
            }
6✔
298

299
            config.record_result(*genprime_timer);
6✔
300
            config.record_result(*is_prime_timer);
12✔
301
         }
6✔
302
      }
1✔
303
};
304

305
BOTAN_REGISTER_PERF_TEST("random_prime", PerfTest_RandomPrime);
1✔
306

307
#endif
308

309
#if defined(BOTAN_HAS_DL_GROUP)
310

311
class PerfTest_ModExp final : public PerfTest {
1✔
312
   public:
313
      void go(const PerfConfig& config) override {
1✔
314
         for(const size_t group_bits : {1024, 1536, 2048, 3072, 4096, 6144, 8192}) {
8✔
315
            const std::string group_name = "modp/ietf/" + std::to_string(group_bits);
14✔
316
            auto group = Botan::DL_Group::from_name(group_name);
7✔
317

318
            const size_t e_bits = group.exponent_bits();
7✔
319
            const size_t f_bits = group_bits - 1;
7✔
320

321
            const Botan::BigInt random_e(config.rng(), e_bits);
7✔
322
            const Botan::BigInt random_f(config.rng(), f_bits);
7✔
323

324
            auto e_timer = config.make_timer(group_name + " short exp");
14✔
325
            auto f_timer = config.make_timer(group_name + "  full exp");
14✔
326

327
            while(f_timer->under(config.runtime())) {
15✔
328
               e_timer->run([&]() { group.power_g_p(random_e, e_bits); });
16✔
329
               f_timer->run([&]() { group.power_g_p(random_f, f_bits); });
16✔
330
            }
331

332
            config.record_result(*e_timer);
7✔
333
            config.record_result(*f_timer);
14✔
334
         }
21✔
335
      }
1✔
336
};
337

338
BOTAN_REGISTER_PERF_TEST("modexp", PerfTest_ModExp);
1✔
339

340
#endif
341

342
}  // namespace
343

344
}  // namespace Botan_CLI
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

© 2026 Coveralls, Inc