• 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

65.69
/src/cli/perf_pk_sig.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_PUBLIC_KEY_CRYPTO)
10
   #include <botan/pk_algs.h>
11
   #include <botan/pubkey.h>
12
   #include <botan/rng.h>
13
   #include <botan/internal/fmt.h>
14
#endif
15

16
namespace Botan_CLI {
17

18
namespace {
19

20
#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
21

22
class PerfTest_PKSig : public PerfTest {
9✔
23
   public:
24
      virtual std::string algo() const = 0;
25

26
      virtual std::string hash() const { return "SHA-256"; }
4✔
27

28
      virtual std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const { return {""}; }
2✔
29

30
      void go(const PerfConfig& config) override {
9✔
31
         const std::string alg = this->algo();
9✔
32
         const std::string padding = this->hash();
9✔
33

34
         const auto params = this->keygen_params(config);
9✔
35

36
         for(const auto& param : params) {
37✔
37
            const std::string nm = this->format_name(alg, param);
28✔
38
            bench_pk_sig(config, nm, alg, param, padding);
56✔
39
         }
28✔
40
      }
9✔
41

42
      static void bench_pk_sig(const PerfConfig& config,
28✔
43
                               const std::string& nm,
44
                               const std::string& alg,
45
                               const std::string& param,
46
                               const std::string& padding,
47
                               const std::string& provider = "") {
48
         auto& rng = config.rng();
28✔
49
         const auto msec = config.runtime();
28✔
50

51
         auto keygen_timer = config.make_timer(nm, 1, "keygen");
56✔
52

53
         auto sk = keygen_timer->run([&] { return Botan::create_private_key(alg, rng, param); });
56✔
54

55
         if(sk != nullptr) {
28✔
56
            while(keygen_timer->under(msec)) {
80✔
57
               sk = keygen_timer->run([&] { return Botan::create_private_key(alg, rng, param); });
156✔
58
            }
59

60
            config.record_result(*keygen_timer);
28✔
61

62
            auto pk = sk->public_key();
28✔
63

64
            std::vector<uint8_t> message;
28✔
65
            std::vector<uint8_t> signature;
28✔
66
            std::vector<uint8_t> bad_signature;
28✔
67

68
            Botan::PK_Signer sig(*sk, rng, padding, Botan::Signature_Format::Standard, provider);
28✔
69
            Botan::PK_Verifier ver(*pk, padding, Botan::Signature_Format::Standard, provider);
28✔
70

71
            auto sig_timer = config.make_timer(nm, 1, "sign");
56✔
72
            auto ver_timer = config.make_timer(nm, 1, "verify");
56✔
73

74
            size_t invalid_sigs = 0;
28✔
75

76
            while(ver_timer->under(msec) || sig_timer->under(msec)) {
175✔
77
               if(signature.empty() || sig_timer->under(msec)) {
119✔
78
                  /*
79
                  Length here is kind of arbitrary, but 48 bytes fits into a single
80
                  hash block so minimizes hashing overhead versus the PK op itself.
81
                  */
82
                  rng.random_vec(message, 48);
114✔
83

84
                  signature = sig_timer->run([&]() { return sig.sign_message(message, rng); });
228✔
85

86
                  bad_signature = signature;
114✔
87
                  bad_signature[rng.next_byte() % bad_signature.size()] ^= rng.next_nonzero_byte();
114✔
88
               }
89

90
               if(ver_timer->under(msec)) {
119✔
91
                  const bool verified = ver_timer->run([&] { return ver.verify_message(message, signature); });
88✔
92

93
                  if(!verified) {
44✔
94
                     invalid_sigs += 1;
×
95
                  }
96

97
                  const bool verified_bad = ver_timer->run([&] { return ver.verify_message(message, bad_signature); });
88✔
98

99
                  if(verified_bad) {
44✔
100
                     config.error_output() << "Bad signature accepted in " << nm << " signature bench\n";
×
101
                  }
102
               }
103
            }
104

105
            if(invalid_sigs > 0) {
28✔
106
               config.error_output() << invalid_sigs << " generated signatures rejected in " << nm
×
107
                                     << " signature bench\n";
×
108
            }
109
            config.record_result(*sig_timer);
28✔
110
            config.record_result(*ver_timer);
56✔
111
         }
56✔
112
      }
28✔
113
};
114

115
#endif
116

117
#if defined(BOTAN_HAS_DSA)
118

119
class PerfTest_DSA final : public PerfTest_PKSig {
1✔
120
   public:
121
      std::string algo() const override { return "DSA"; }
1✔
122

123
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
1✔
124
         return {"dsa/jce/1024", "dsa/botan/2048", "dsa/botan/3072"};
1✔
125
      }
126

127
      std::string format_name(const std::string& alg, const std::string& param) const override {
3✔
128
         return Botan::fmt("{}-{}", alg, param.substr(param.find_last_of('/') + 1));
6✔
129
      }
130
};
131

132
BOTAN_REGISTER_PERF_TEST("DSA", PerfTest_DSA);
1✔
133

134
#endif
135

136
#if defined(BOTAN_HAS_RSA)
137

138
class PerfTest_RSA final : public PerfTest_PKSig {
×
139
   public:
140
      std::string algo() const override { return "RSA"; }
×
141

142
      std::string hash() const override { return "PKCS1v15(SHA-256)"; }
×
143

144
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
145
         return {"1024", "2048", "3072", "4096"};
×
146
      }
147
};
148

149
BOTAN_REGISTER_PERF_TEST("RSA", PerfTest_RSA);
×
150

151
#endif
152

153
#if defined(BOTAN_HAS_ECDSA)
154

155
class PerfTest_ECDSA final : public PerfTest_PKSig {
1✔
156
   public:
157
      std::string algo() const override { return "ECDSA"; }
1✔
158

159
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
160
};
161

162
BOTAN_REGISTER_PERF_TEST("ECDSA", PerfTest_ECDSA);
1✔
163

164
#endif
165

166
#if defined(BOTAN_HAS_ECKCDSA)
167

168
class PerfTest_ECKCDSA final : public PerfTest_PKSig {
1✔
169
   public:
170
      std::string algo() const override { return "ECKCDSA"; }
1✔
171

172
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
173
};
174

175
BOTAN_REGISTER_PERF_TEST("ECKCDSA", PerfTest_ECKCDSA);
1✔
176

177
#endif
178

179
#if defined(BOTAN_HAS_ECGDSA)
180

181
class PerfTest_ECGDSA final : public PerfTest_PKSig {
1✔
182
   public:
183
      std::string algo() const override { return "ECGDSA"; }
1✔
184

185
      std::vector<std::string> keygen_params(const PerfConfig& config) const override { return config.ecc_groups(); }
1✔
186
};
187

188
BOTAN_REGISTER_PERF_TEST("ECGDSA", PerfTest_ECGDSA);
1✔
189

190
#endif
191

192
#if defined(BOTAN_HAS_GOST_34_10_2001) && defined(BOTAN_HAS_GOST_34_11)
193

194
class PerfTest_Gost3410 final : public PerfTest_PKSig {
1✔
195
   public:
196
      std::string algo() const override { return "GOST-34.10"; }
1✔
197

198
      std::string hash() const override { return "GOST-34.11"; }
1✔
199

200
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override { return {"gost_256A"}; }
1✔
201
};
202

203
BOTAN_REGISTER_PERF_TEST("GOST-34.10", PerfTest_Gost3410);
1✔
204

205
#endif
206

207
#if defined(BOTAN_HAS_SM2) && defined(BOTAN_HAS_SM3)
208

209
class PerfTest_SM2 final : public PerfTest_PKSig {
1✔
210
   public:
211
      std::string algo() const override { return "SM2"; }
1✔
212

213
      std::string hash() const override { return "SM3"; }
1✔
214

215
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override { return {"sm2p256v1"}; }
1✔
216
};
217

218
BOTAN_REGISTER_PERF_TEST("SM2", PerfTest_SM2);
1✔
219

220
#endif
221

222
#if defined(BOTAN_HAS_ED25519)
223

224
class PerfTest_Ed25519 final : public PerfTest_PKSig {
1✔
225
   public:
226
      std::string algo() const override { return "Ed25519"; }
1✔
227

228
      std::string hash() const override { return "Pure"; }
1✔
229
};
230

231
BOTAN_REGISTER_PERF_TEST("Ed25519", PerfTest_Ed25519);
1✔
232

233
#endif
234

235
#if defined(BOTAN_HAS_ED448)
236

237
class PerfTest_Ed448 final : public PerfTest_PKSig {
1✔
238
   public:
239
      std::string algo() const override { return "Ed448"; }
1✔
240

241
      std::string hash() const override { return "Pure"; }
1✔
242
};
243

244
BOTAN_REGISTER_PERF_TEST("Ed448", PerfTest_Ed448);
1✔
245

246
#endif
247

248
#if defined(BOTAN_HAS_XMSS_RFC8391)
249

250
class PerfTest_XMSS final : public PerfTest_PKSig {
×
251
   public:
252
      std::string algo() const override { return "XMSS"; }
×
253

254
      std::string hash() const override { return ""; }
×
255

256
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
257
         /*
258
         We only test H10 signatures here since already they are quite slow (a
259
         few seconds per signature). On a fast machine, H16 signatures take 1-2
260
         minutes to generate and H20 signatures take 5-10 minutes to generate
261
         */
262
         return {
×
263
            "XMSS-SHA2_10_256",
264
            "XMSS-SHAKE_10_256",
265
            "XMSS-SHA2_10_512",
266
            "XMSS-SHAKE_10_512",
267
         };
×
268
      }
269
};
270

271
BOTAN_REGISTER_PERF_TEST("XMSS", PerfTest_XMSS);
×
272

273
#endif
274

275
#if defined(BOTAN_HAS_HSS_LMS)
276

277
class PerfTest_HSS_LMS final : public PerfTest_PKSig {
×
278
   public:
279
      std::string algo() const override { return "HSS-LMS"; }
×
280

281
      std::string hash() const override { return ""; }
×
282

283
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
284
         // At first we compare instances with multiple hash functions. LMS trees with
285
         // height 10 are suitable, since they can be used for enough signatures and are
286
         // fast enough for speed testing.
287
         // Afterward, setups with multiple HSS layers are tested
288
         return {"SHA-256,HW(10,1)",
×
289
                 "SHAKE-256(256),HW(10,1)",
290
                 "SHAKE-256(192),HW(10,1)",
291
                 "Truncated(SHA-256,192),HW(10,1)",
292
                 "SHA-256,HW(10,1),HW(10,1)",
293
                 "SHA-256,HW(10,1),HW(10,1),HW(10,1)"};
×
294
      }
295
};
296

297
BOTAN_REGISTER_PERF_TEST("HSS-LMS", PerfTest_HSS_LMS);
×
298

299
#endif
300

301
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
302

303
class PerfTest_SPHINCSp final : public PerfTest_PKSig {
×
304
   public:
305
      std::string algo() const override { return "SPHINCS+"; }
×
306

307
      std::string hash() const override { return ""; }
×
308

309
      std::string format_name(const std::string& alg, const std::string& param) const override {
×
310
         return alg + param.substr(11);
×
311
      }
312

313
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
314
         return {"SphincsPlus-sha2-128s-r3.1",
×
315
                 "SphincsPlus-sha2-128f-r3.1",
316
                 "SphincsPlus-sha2-192s-r3.1",
317
                 "SphincsPlus-sha2-192f-r3.1",
318
                 "SphincsPlus-sha2-256s-r3.1",
319
                 "SphincsPlus-sha2-256f-r3.1",
320
                 "SphincsPlus-shake-128s-r3.1",
321
                 "SphincsPlus-shake-128f-r3.1",
322
                 "SphincsPlus-shake-192s-r3.1",
323
                 "SphincsPlus-shake-192f-r3.1",
324
                 "SphincsPlus-shake-256s-r3.1",
325
                 "SphincsPlus-shake-256f-r3.1"};
×
326
      }
327
};
328

329
BOTAN_REGISTER_PERF_TEST("SPHINCS+", PerfTest_SPHINCSp);
×
330

331
#endif
332

333
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
334

335
class PerfTest_SLH_DSA final : public PerfTest_PKSig {
×
336
   public:
337
      std::string algo() const override { return "SLH-DSA"; }
×
338

339
      std::string hash() const override { return ""; }
×
340

341
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
342
         return {"SLH-DSA-SHA2-128s",
×
343
                 "SLH-DSA-SHA2-128f",
344
                 "SLH-DSA-SHA2-192s",
345
                 "SLH-DSA-SHA2-192f",
346
                 "SLH-DSA-SHA2-256s",
347
                 "SLH-DSA-SHA2-256f",
348
                 "SLH-DSA-SHAKE-128s",
349
                 "SLH-DSA-SHAKE-128f",
350
                 "SLH-DSA-SHAKE-192s",
351
                 "SLH-DSA-SHAKE-192f",
352
                 "SLH-DSA-SHAKE-256s",
353
                 "SLH-DSA-SHAKE-256f"};
×
354
      }
355
};
356

357
BOTAN_REGISTER_PERF_TEST("SLH-DSA", PerfTest_SLH_DSA);
×
358

359
#endif
360

361
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
362

363
class PerfTest_Dilithium final : public PerfTest_PKSig {
×
364
   public:
365
      std::string algo() const override { return "Dilithium"; }
×
366

367
      std::string hash() const override { return ""; }
×
368

369
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
×
370
         return {
×
371
            "Dilithium-4x4-r3",
372
            "Dilithium-4x4-AES-r3",
373
            "Dilithium-6x5-r3",
374
            "Dilithium-6x5-AES-r3",
375
            "Dilithium-8x7-r3",
376
            "Dilithium-8x7-AES-r3",
377
         };
×
378
      }
379
};
380

381
BOTAN_REGISTER_PERF_TEST("Dilithium", PerfTest_Dilithium);
×
382

383
#endif
384

385
#if defined(BOTAN_HAS_ML_DSA)
386

387
class PerfTest_ML_DSA final : public PerfTest_PKSig {
1✔
388
   public:
389
      std::string algo() const override { return "ML-DSA"; }
1✔
390

391
      std::string hash() const override { return ""; }
1✔
392

393
      std::vector<std::string> keygen_params(const PerfConfig& /*config*/) const override {
1✔
394
         return {
1✔
395
            "ML-DSA-4x4",
396
            "ML-DSA-6x5",
397
            "ML-DSA-8x7",
398
         };
1✔
399
      }
400
};
401

402
BOTAN_REGISTER_PERF_TEST("ML-DSA", PerfTest_ML_DSA);
1✔
403

404
#endif
405

406
}  // namespace
407

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