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

randombit / botan / 11540997855

27 Oct 2024 01:42PM UTC coverage: 91.074% (-0.06%) from 91.135%
11540997855

push

github

web-flow
Merge pull request #4385 from randombit/jack/remove-old-nist-redc

Remove the BigInt based NIST reduction functions

90362 of 99218 relevant lines covered (91.07%)

9565315.37 hits per line

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

98.41
/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/bigint.h>
11
   #include <botan/internal/divide.h>
12
#endif
13

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

20
#if defined(BOTAN_HAS_DL_GROUP)
21
   #include <botan/dl_group.h>
22
   #include <botan/internal/workfactor.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,542✔
42
               Botan::BigInt x(config.rng(), bits);
9,533✔
43

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

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

50
               mul_timer->start();
9,533✔
51
               x.mul(y, ws);
9,533✔
52
               mul_timer->stop();
9,533✔
53
            }
9,533✔
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, r1, q2, r2;
9✔
80

81
            while(ct_div_timer->under(runtime_per_size)) {
9✔
82
               x.randomize(config.rng(), n_bits);
97✔
83
               y.randomize(config.rng(), q_bits);
97✔
84

85
               div_timer->start();
97✔
86
               Botan::vartime_divide(x, y, q1, r1);
97✔
87
               div_timer->stop();
97✔
88

89
               ct_div_timer->start();
97✔
90
               Botan::ct_divide(x, y, q2, r2);
97✔
91
               ct_div_timer->stop();
97✔
92

93
               BOTAN_ASSERT_EQUAL(q1, q2, "Quotient ok");
97✔
94
               BOTAN_ASSERT_EQUAL(r1, r2, "Remainder ok");
203✔
95
            }
96

97
            config.record_result(*div_timer);
9✔
98
            config.record_result(*ct_div_timer);
18✔
99
         }
54✔
100
      }
1✔
101
};
102

103
BOTAN_REGISTER_PERF_TEST("mp_div", PerfTest_MpDiv);
1✔
104

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

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

113
            auto div_timer = config.make_timer("BigInt div " + bit_descr);
18✔
114
            auto ct_div_timer = config.make_timer("BigInt ct_div " + bit_descr);
18✔
115

116
            Botan::BigInt x;
9✔
117
            Botan::secure_vector<Botan::word> ws;
9✔
118

119
            const auto ten = Botan::BigInt::from_word(10);
9✔
120
            Botan::BigInt q1, r1, q2;
9✔
121
            Botan::word r2;
9✔
122

123
            while(ct_div_timer->under(runtime_per_size)) {
9✔
124
               x.randomize(config.rng(), n_bits);
719✔
125

126
               div_timer->start();
719✔
127
               Botan::vartime_divide(x, ten, q1, r1);
719✔
128
               div_timer->stop();
719✔
129

130
               ct_div_timer->start();
719✔
131
               Botan::ct_divide_word(x, 10, q2, r2);
719✔
132
               ct_div_timer->stop();
719✔
133

134
               BOTAN_ASSERT_EQUAL(q1, q2, "Quotient ok");
719✔
135
               BOTAN_ASSERT_EQUAL(r1, r2, "Remainder ok");
1,447✔
136
            }
137

138
            config.record_result(*div_timer);
9✔
139
            config.record_result(*ct_div_timer);
18✔
140
         }
45✔
141
      }
1✔
142
};
143

144
BOTAN_REGISTER_PERF_TEST("mp_div10", PerfTest_MpDiv10);
1✔
145

146
#endif
147

148
#if defined(BOTAN_HAS_NUMBERTHEORY)
149

150
class PerfTest_BnRedc final : public PerfTest {
1✔
151
   public:
152
      void go(const PerfConfig& config) override {
1✔
153
         const auto runtime = config.runtime();
1✔
154

155
         for(size_t bitsize : {512, 1024, 2048, 4096}) {
5✔
156
            Botan::BigInt p(config.rng(), bitsize);
4✔
157

158
            std::string bit_str = std::to_string(bitsize);
4✔
159
            auto barrett_timer = config.make_timer("Barrett-" + bit_str);
8✔
160
            auto schoolbook_timer = config.make_timer("Schoolbook-" + bit_str);
8✔
161

162
            Botan::Modular_Reducer mod_p(p);
4✔
163

164
            while(schoolbook_timer->under(runtime)) {
129✔
165
               const Botan::BigInt x(config.rng(), p.bits() * 2 - 2);
125✔
166

167
               const Botan::BigInt r1 = barrett_timer->run([&] { return mod_p.reduce(x); });
250✔
168
               const Botan::BigInt r2 = schoolbook_timer->run([&] { return x % p; });
250✔
169

170
               BOTAN_ASSERT(r1 == r2, "Computed different results");
125✔
171
            }
375✔
172

173
            config.record_result(*barrett_timer);
4✔
174
            config.record_result(*schoolbook_timer);
4✔
175
         }
8✔
176
      }
1✔
177
};
178

179
BOTAN_REGISTER_PERF_TEST("bn_redc", PerfTest_BnRedc);
1✔
180

181
class PerfTest_InvMod final : public PerfTest {
1✔
182
   public:
183
      void go(const PerfConfig& config) override {
1✔
184
         const auto runtime = config.runtime();
1✔
185

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

189
            auto timer = config.make_timer("inverse_mod-" + bit_str);
10✔
190
            auto gcd_timer = config.make_timer("gcd-" + bit_str);
10✔
191

192
            while(timer->under(runtime) && gcd_timer->under(runtime)) {
14✔
193
               const Botan::BigInt x(config.rng(), bits - 1);
9✔
194
               Botan::BigInt mod(config.rng(), bits);
9✔
195

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

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

200
               if(x_inv == 0) {
9✔
201
                  BOTAN_ASSERT(g != 1, "Inversion only fails if gcd(x, mod) > 1");
3✔
202
               } else {
203
                  BOTAN_ASSERT(g == 1, "Inversion succeeds only if gcd != 1");
6✔
204
                  const Botan::BigInt check = (x_inv * x) % mod;
6✔
205
                  BOTAN_ASSERT_EQUAL(check, 1, "Const time inversion correct");
6✔
206
               }
6✔
207
            }
34✔
208

209
            config.record_result(*timer);
5✔
210
            config.record_result(*gcd_timer);
5✔
211
         }
5✔
212
      }
1✔
213
};
214

215
BOTAN_REGISTER_PERF_TEST("inverse_mod", PerfTest_InvMod);
1✔
216

217
class PerfTest_IsPrime final : public PerfTest {
1✔
218
   public:
219
      void go(const PerfConfig& config) override {
1✔
220
         const auto runtime = config.runtime();
1✔
221

222
         for(size_t bits : {256, 512, 1024}) {
4✔
223
            auto mr_timer = config.make_timer("Miller-Rabin-" + std::to_string(bits));
6✔
224
            auto bpsw_timer = config.make_timer("Bailie-PSW-" + std::to_string(bits));
6✔
225
            auto lucas_timer = config.make_timer("Lucas-" + std::to_string(bits));
6✔
226

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

229
            while(lucas_timer->under(runtime)) {
6✔
230
               Botan::Modular_Reducer mod_n(n);
3✔
231

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

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

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

238
               n += 2;
3✔
239
            }
3✔
240

241
            config.record_result(*mr_timer);
3✔
242
            config.record_result(*bpsw_timer);
3✔
243
            config.record_result(*lucas_timer);
6✔
244
         }
3✔
245
      }
1✔
246
};
247

248
BOTAN_REGISTER_PERF_TEST("primality_test", PerfTest_IsPrime);
1✔
249

250
class PerfTest_RandomPrime final : public PerfTest {
1✔
251
   public:
252
      void go(const PerfConfig& config) override {
1✔
253
         const auto coprime = Botan::BigInt::from_word(0x10001);
1✔
254
         const auto runtime = config.runtime();
1✔
255

256
         auto& rng = config.rng();
1✔
257

258
         for(size_t bits : {256, 384, 512, 768, 1024, 1536}) {
7✔
259
            auto genprime_timer = config.make_timer("random_prime " + std::to_string(bits));
12✔
260
            auto gensafe_timer = config.make_timer("random_safe_prime " + std::to_string(bits));
12✔
261
            auto is_prime_timer = config.make_timer("is_prime " + std::to_string(bits));
12✔
262

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

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

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

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

276
               if(!is_prime_timer->run([&] { return Botan::is_prime(sg / 2, rng, 64, true); })) {
18✔
277
                  config.error_output() << "Generated prime " << sg / 2 << " which failed a primality test";
×
278
               }
279

280
               // Now test p+2, p+4, ... which may or may not be prime
281
               for(size_t i = 2; i <= 64; i += 2) {
198✔
282
                  is_prime_timer->run([&]() { Botan::is_prime(p + i, rng, 64, true); });
576✔
283
               }
284
            }
12✔
285

286
            config.record_result(*genprime_timer);
6✔
287
            config.record_result(*gensafe_timer);
6✔
288
            config.record_result(*is_prime_timer);
6✔
289
         }
6✔
290
      }
1✔
291
};
292

293
BOTAN_REGISTER_PERF_TEST("random_prime", PerfTest_RandomPrime);
1✔
294

295
#endif
296

297
#if defined(BOTAN_HAS_DL_GROUP)
298

299
class PerfTest_ModExp final : public PerfTest {
1✔
300
   public:
301
      void go(const PerfConfig& config) override {
1✔
302
         for(size_t group_bits : {1024, 1536, 2048, 3072, 4096}) {
6✔
303
            const std::string group_bits_str = std::to_string(group_bits);
5✔
304
            const Botan::DL_Group group("modp/srp/" + group_bits_str);
5✔
305

306
            const size_t e_bits = Botan::dl_exponent_size(group_bits);
5✔
307
            const size_t f_bits = group_bits - 1;
5✔
308

309
            const Botan::BigInt random_e(config.rng(), e_bits);
5✔
310
            const Botan::BigInt random_f(config.rng(), f_bits);
5✔
311

312
            auto e_timer = config.make_timer(group_bits_str + " short exponent");
10✔
313
            auto f_timer = config.make_timer(group_bits_str + "  full exponent");
10✔
314

315
            while(f_timer->under(config.runtime())) {
11✔
316
               e_timer->run([&]() { group.power_g_p(random_e); });
12✔
317
               f_timer->run([&]() { group.power_g_p(random_f); });
12✔
318
            }
319

320
            config.record_result(*e_timer);
5✔
321
            config.record_result(*f_timer);
5✔
322
         }
20✔
323
      }
6✔
324
};
325

326
BOTAN_REGISTER_PERF_TEST("modexp", PerfTest_ModExp);
1✔
327

328
#endif
329

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

© 2025 Coveralls, Inc