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

randombit / botan / 16395825001

19 Jul 2025 11:30PM UTC coverage: 90.635% (-0.07%) from 90.708%
16395825001

push

github

web-flow
Merge pull request #4998 from randombit/jack/fix-clang-tidy-readability-isolate-declaration

Enable and fix clang-tidy warning readability-isolate-declaration

99940 of 110266 relevant lines covered (90.64%)

12341110.13 hits per line

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

98.54
/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
#if defined(BOTAN_HAS_BIGINT)
10
   #include <botan/assert.h>
11
   #include <botan/bigint.h>
12
   #include <botan/internal/divide.h>
13
#endif
14

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

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

25
namespace Botan_CLI {
26

27
#if defined(BOTAN_HAS_BIGINT)
28

29
class PerfTest_MpMul final : public PerfTest {
1✔
30
   public:
31
      void go(const PerfConfig& config) override {
1✔
32
         std::chrono::milliseconds runtime_per_size = config.runtime();
1✔
33

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

38
            const Botan::BigInt y(config.rng(), bits);
9✔
39
            Botan::secure_vector<Botan::word> ws;
9✔
40

41
            while(mul_timer->under(runtime_per_size)) {
9,662✔
42
               Botan::BigInt x(config.rng(), bits);
9,653✔
43

44
               sqr_timer->start();
9,653✔
45
               x.square(ws);
9,653✔
46
               sqr_timer->stop();
9,653✔
47

48
               x.mask_bits(bits);
9,653✔
49

50
               mul_timer->start();
9,653✔
51
               x.mul(y, ws);
9,653✔
52
               mul_timer->stop();
9,653✔
53
            }
9,653✔
54

55
            config.record_result(*mul_timer);
9✔
56
            config.record_result(*sqr_timer);
18✔
57
         }
18✔
58
      }
1✔
59
};
60

61
BOTAN_REGISTER_PERF_TEST("mp_mul", PerfTest_MpMul);
1✔
62

63
class PerfTest_MpDiv final : public PerfTest {
1✔
64
   public:
65
      void go(const PerfConfig& config) override {
1✔
66
         std::chrono::milliseconds runtime_per_size = config.runtime();
1✔
67

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

72
            auto div_timer = config.make_timer("BigInt div " + bit_descr);
18✔
73
            auto ct_div_timer = config.make_timer("BigInt ct_div " + bit_descr);
18✔
74

75
            Botan::BigInt y;
9✔
76
            Botan::BigInt x;
9✔
77
            Botan::secure_vector<Botan::word> ws;
9✔
78

79
            Botan::BigInt q1;
9✔
80
            Botan::BigInt r1;
9✔
81
            Botan::BigInt q2;
9✔
82
            Botan::BigInt r2;
9✔
83

84
            while(ct_div_timer->under(runtime_per_size)) {
9✔
85
               x.randomize(config.rng(), n_bits);
69✔
86
               y.randomize(config.rng(), q_bits);
69✔
87

88
               div_timer->start();
69✔
89
               Botan::vartime_divide(x, y, q1, r1);
69✔
90
               div_timer->stop();
69✔
91

92
               ct_div_timer->start();
69✔
93
               Botan::ct_divide(x, y, q2, r2);
69✔
94
               ct_div_timer->stop();
69✔
95

96
               BOTAN_ASSERT_EQUAL(q1, q2, "Quotient ok");
69✔
97
               BOTAN_ASSERT_EQUAL(r1, r2, "Remainder ok");
147✔
98
            }
99

100
            config.record_result(*div_timer);
9✔
101
            config.record_result(*ct_div_timer);
9✔
102
         }
18✔
103
      }
1✔
104
};
105

106
BOTAN_REGISTER_PERF_TEST("mp_div", PerfTest_MpDiv);
1✔
107

108
class PerfTest_MpDiv10 final : public PerfTest {
1✔
109
   public:
110
      void go(const PerfConfig& config) override {
1✔
111
         std::chrono::milliseconds runtime_per_size = config.runtime();
1✔
112

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

116
            auto div_timer = config.make_timer("BigInt div " + bit_descr);
18✔
117
            auto ct_div_timer = config.make_timer("BigInt ct_div " + bit_descr);
18✔
118

119
            Botan::BigInt x;
9✔
120
            Botan::secure_vector<Botan::word> ws;
9✔
121

122
            const auto ten = Botan::BigInt::from_word(10);
9✔
123
            Botan::BigInt q1;
9✔
124
            Botan::BigInt r1;
9✔
125
            Botan::BigInt q2;
9✔
126
            Botan::word r2 = 0;
9✔
127

128
            while(ct_div_timer->under(runtime_per_size)) {
9✔
129
               x.randomize(config.rng(), n_bits);
721✔
130

131
               div_timer->start();
721✔
132
               Botan::vartime_divide(x, ten, q1, r1);
721✔
133
               div_timer->stop();
721✔
134

135
               ct_div_timer->start();
721✔
136
               Botan::ct_divide_word(x, 10, q2, r2);
721✔
137
               ct_div_timer->stop();
721✔
138

139
               BOTAN_ASSERT_EQUAL(q1, q2, "Quotient ok");
721✔
140
               BOTAN_ASSERT_EQUAL(r1, r2, "Remainder ok");
1,451✔
141
            }
142

143
            config.record_result(*div_timer);
9✔
144
            config.record_result(*ct_div_timer);
9✔
145
         }
18✔
146
      }
1✔
147
};
148

149
BOTAN_REGISTER_PERF_TEST("mp_div10", PerfTest_MpDiv10);
1✔
150

151
#endif
152

153
#if defined(BOTAN_HAS_NUMBERTHEORY)
154

155
class PerfTest_BnRedc final : public PerfTest {
1✔
156
   public:
157
      void go(const PerfConfig& config) override {
1✔
158
         const auto runtime = config.runtime();
1✔
159

160
         for(size_t bitsize : {512, 1024, 2048, 4096}) {
5✔
161
            Botan::BigInt p(config.rng(), bitsize);
4✔
162

163
            std::string bit_str = std::to_string(bitsize) + " bit ";
8✔
164
            auto barrett_setup_pub_timer = config.make_timer(bit_str + "Barrett setup public");
8✔
165
            auto barrett_setup_sec_timer = config.make_timer(bit_str + "Barrett setup secret");
8✔
166

167
            while(barrett_setup_sec_timer->under(runtime)) {
15✔
168
               barrett_setup_sec_timer->run([&]() { Botan::Barrett_Reduction::for_secret_modulus(p); });
22✔
169
               barrett_setup_pub_timer->run([&]() { Botan::Barrett_Reduction::for_public_modulus(p); });
22✔
170
            }
171

172
            config.record_result(*barrett_setup_pub_timer);
4✔
173
            config.record_result(*barrett_setup_sec_timer);
4✔
174

175
            auto mod_p = Botan::Barrett_Reduction::for_public_modulus(p);
4✔
176

177
            auto barrett_timer = config.make_timer(bit_str + "Barrett redc");
8✔
178
            auto knuth_timer = config.make_timer(bit_str + "Knuth redc");
8✔
179
            auto ct_modulo_timer = config.make_timer(bit_str + "ct_modulo");
8✔
180

181
            while(ct_modulo_timer->under(runtime)) {
11✔
182
               const Botan::BigInt x(config.rng(), p.bits() * 2 - 1);
7✔
183

184
               const Botan::BigInt r1 = barrett_timer->run([&] { return mod_p.reduce(x); });
14✔
185
               const Botan::BigInt r2 = knuth_timer->run([&] { return x % p; });
14✔
186
               const Botan::BigInt r3 = ct_modulo_timer->run([&] { return Botan::ct_modulo(x, p); });
14✔
187

188
               BOTAN_ASSERT(r1 == r2, "Computed different results");
7✔
189
               BOTAN_ASSERT(r1 == r3, "Computed different results");
7✔
190
            }
7✔
191

192
            config.record_result(*barrett_timer);
4✔
193
            config.record_result(*knuth_timer);
4✔
194
            config.record_result(*ct_modulo_timer);
8✔
195
         }
20✔
196
      }
1✔
197
};
198

199
BOTAN_REGISTER_PERF_TEST("bn_redc", PerfTest_BnRedc);
1✔
200

201
class PerfTest_InvMod final : public PerfTest {
1✔
202
   public:
203
      void go(const PerfConfig& config) override {
1✔
204
         const auto runtime = config.runtime();
1✔
205

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

209
            auto timer = config.make_timer("inverse_mod-" + bit_str);
10✔
210
            auto gcd_timer = config.make_timer("gcd-" + bit_str);
10✔
211

212
            while(timer->under(runtime) && gcd_timer->under(runtime)) {
26✔
213
               const Botan::BigInt x(config.rng(), bits - 1);
9✔
214
               Botan::BigInt mod(config.rng(), bits);
9✔
215

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

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

220
               if(x_inv == 0) {
9✔
221
                  BOTAN_ASSERT(g != 1, "Inversion only fails if gcd(x, mod) > 1");
3✔
222
               } else {
223
                  BOTAN_ASSERT(g == 1, "Inversion succeeds only if gcd != 1");
6✔
224
                  const Botan::BigInt check = (x_inv * x) % mod;
6✔
225
                  BOTAN_ASSERT_EQUAL(check, 1, "Const time inversion correct");
6✔
226
               }
6✔
227
            }
9✔
228

229
            config.record_result(*timer);
5✔
230
            config.record_result(*gcd_timer);
10✔
231
         }
10✔
232
      }
1✔
233
};
234

235
BOTAN_REGISTER_PERF_TEST("inverse_mod", PerfTest_InvMod);
1✔
236

237
class PerfTest_IsPrime final : public PerfTest {
1✔
238
   public:
239
      void go(const PerfConfig& config) override {
1✔
240
         const auto runtime = config.runtime();
1✔
241

242
         for(size_t bits : {256, 512, 1024}) {
4✔
243
            auto mr_timer = config.make_timer("Miller-Rabin-" + std::to_string(bits));
6✔
244
            auto bpsw_timer = config.make_timer("Bailie-PSW-" + std::to_string(bits));
6✔
245
            auto lucas_timer = config.make_timer("Lucas-" + std::to_string(bits));
6✔
246

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

249
            while(lucas_timer->under(runtime)) {
6✔
250
               auto mod_n = Botan::Barrett_Reduction::for_public_modulus(n);
3✔
251

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

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

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

258
               n += 2;
3✔
259
            }
3✔
260

261
            config.record_result(*mr_timer);
3✔
262
            config.record_result(*bpsw_timer);
3✔
263
            config.record_result(*lucas_timer);
3✔
264
         }
9✔
265
      }
1✔
266
};
267

268
BOTAN_REGISTER_PERF_TEST("primality_test", PerfTest_IsPrime);
1✔
269

270
class PerfTest_RandomPrime final : public PerfTest {
1✔
271
   public:
272
      void go(const PerfConfig& config) override {
1✔
273
         const auto coprime = Botan::BigInt::from_word(0x10001);
1✔
274
         const auto runtime = config.runtime();
1✔
275

276
         auto& rng = config.rng();
1✔
277

278
         for(size_t bits : {256, 384, 512, 768, 1024, 1536}) {
7✔
279
            auto genprime_timer = config.make_timer("random_prime " + std::to_string(bits));
12✔
280
            auto gensafe_timer = config.make_timer("random_safe_prime " + std::to_string(bits));
12✔
281
            auto is_prime_timer = config.make_timer("is_prime " + std::to_string(bits));
12✔
282

283
            while(gensafe_timer->under(runtime)) {
12✔
284
               const Botan::BigInt p = genprime_timer->run([&] { return Botan::random_prime(rng, bits, coprime); });
12✔
285

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

290
               const Botan::BigInt sg = gensafe_timer->run([&] { return Botan::random_safe_prime(rng, bits); });
12✔
291

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

296
               if(!is_prime_timer->run([&] { return Botan::is_prime(sg / 2, rng, 64, true); })) {
12✔
297
                  config.error_output() << "Generated prime " << sg / 2 << " which failed a primality test";
×
298
               }
299

300
               // Now test p+2, p+4, ... which may or may not be prime
301
               for(size_t i = 2; i <= 64; i += 2) {
198✔
302
                  is_prime_timer->run([&]() { Botan::is_prime(p + i, rng, 64, true); });
384✔
303
               }
304
            }
6✔
305

306
            config.record_result(*genprime_timer);
6✔
307
            config.record_result(*gensafe_timer);
6✔
308
            config.record_result(*is_prime_timer);
12✔
309
         }
12✔
310
      }
1✔
311
};
312

313
BOTAN_REGISTER_PERF_TEST("random_prime", PerfTest_RandomPrime);
1✔
314

315
#endif
316

317
#if defined(BOTAN_HAS_DL_GROUP)
318

319
class PerfTest_ModExp final : public PerfTest {
1✔
320
   public:
321
      void go(const PerfConfig& config) override {
1✔
322
         for(size_t group_bits : {1024, 1536, 2048, 3072, 4096, 6144, 8192}) {
8✔
323
            const std::string group_name = "modp/ietf/" + std::to_string(group_bits);
14✔
324
            auto group = Botan::DL_Group::from_name(group_name);
7✔
325

326
            const size_t e_bits = group.exponent_bits();
7✔
327
            const size_t f_bits = group_bits - 1;
7✔
328

329
            const Botan::BigInt random_e(config.rng(), e_bits);
7✔
330
            const Botan::BigInt random_f(config.rng(), f_bits);
7✔
331

332
            auto e_timer = config.make_timer(group_name + " short exp");
14✔
333
            auto f_timer = config.make_timer(group_name + "  full exp");
14✔
334

335
            while(f_timer->under(config.runtime())) {
15✔
336
               e_timer->run([&]() { group.power_g_p(random_e, e_bits); });
16✔
337
               f_timer->run([&]() { group.power_g_p(random_f, f_bits); });
16✔
338
            }
339

340
            config.record_result(*e_timer);
7✔
341
            config.record_result(*f_timer);
14✔
342
         }
21✔
343
      }
1✔
344
};
345

346
BOTAN_REGISTER_PERF_TEST("modexp", PerfTest_ModExp);
1✔
347

348
#endif
349

350
}  // 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